From 0993489bafdcfb42e568bc69d459bc5a3597c720 Mon Sep 17 00:00:00 2001 From: Igor Zhukov Date: Sun, 5 Jan 2014 20:07:11 +0400 Subject: [PATCH] Initial import --- README.md | 88 +- app/css/app.css | 1162 + app/img/Logo_1x.png | Bin 0 -> 1550 bytes app/img/Logo_2x.png | Bin 0 -> 2857 bytes app/img/bg_full.png | Bin 0 -> 587517 bytes app/img/bg_tile.png | Bin 0 -> 287451 bytes app/img/icons/Arrow_1x.png | Bin 0 -> 167 bytes app/img/icons/Arrow_2x.png | Bin 0 -> 229 bytes app/img/icons/Attach_1x.png | Bin 0 -> 515 bytes app/img/icons/Attach_2x.png | Bin 0 -> 892 bytes app/img/icons/Attach_pressed_1x.png | Bin 0 -> 527 bytes app/img/icons/Attach_pressed_2x.png | Bin 0 -> 904 bytes app/img/icons/CheckIn_Recent.png | Bin 0 -> 518 bytes app/img/icons/Checks1_1x.png | Bin 0 -> 362 bytes app/img/icons/Checks1_2x.png | Bin 0 -> 535 bytes app/img/icons/Checks2_1x.png | Bin 0 -> 469 bytes app/img/icons/Checks2_2x.png | Bin 0 -> 713 bytes app/img/icons/CloseHover_1x.png | Bin 0 -> 789 bytes app/img/icons/CloseHover_2x.png | Bin 0 -> 1496 bytes app/img/icons/Close_1x.png | Bin 0 -> 783 bytes app/img/icons/Close_2x.png | Bin 0 -> 1515 bytes app/img/icons/DialogListGroupChatIcon@2x.png | Bin 0 -> 3258 bytes ...DialogListGroupChatIcon_Highlighted@2x.png | Bin 0 -> 529 bytes app/img/icons/DocBlue_1x.png | Bin 0 -> 476 bytes app/img/icons/DocBlue_2x.png | Bin 0 -> 875 bytes app/img/icons/DocGrey_1x.png | Bin 0 -> 474 bytes app/img/icons/DocGrey_2x.png | Bin 0 -> 898 bytes app/img/icons/Location_Active.png | Bin 0 -> 574 bytes app/img/icons/Logo_1x.png | Bin 0 -> 1550 bytes app/img/icons/Logo_2x.png | Bin 0 -> 2857 bytes app/img/icons/NoResults.png | Bin 0 -> 4655 bytes app/img/icons/Search_1x.png | Bin 0 -> 431 bytes app/img/icons/Search_2x.png | Bin 0 -> 706 bytes app/img/icons/Smile_1x.png | Bin 0 -> 773 bytes app/img/icons/Smile_2x.png | Bin 0 -> 1384 bytes app/img/icons/Smile_pressed_1x.png | Bin 0 -> 712 bytes app/img/icons/Smile_pressed_2x.png | Bin 0 -> 1377 bytes app/img/icons/VideoIcon.png | Bin 0 -> 321 bytes app/img/icons/icon128.png | Bin 0 -> 35542 bytes app/img/icons/icon16.png | Bin 0 -> 4262 bytes .../DialogListAvatarSystem@2x.png | Bin 0 -> 5587 bytes app/img/placeholders/GroupAvatar1@2x.png | Bin 0 -> 1834 bytes app/img/placeholders/GroupAvatar2@2x.png | Bin 0 -> 1781 bytes app/img/placeholders/GroupAvatar3@2x.png | Bin 0 -> 1718 bytes app/img/placeholders/GroupAvatar4@2x.png | Bin 0 -> 1680 bytes app/img/placeholders/UserAvatar1@2x.png | Bin 0 -> 1551 bytes app/img/placeholders/UserAvatar2@2x.png | Bin 0 -> 1569 bytes app/img/placeholders/UserAvatar3@2x.png | Bin 0 -> 1427 bytes app/img/placeholders/UserAvatar4@2x.png | Bin 0 -> 1477 bytes app/img/placeholders/UserAvatar5@2x.png | Bin 0 -> 1398 bytes app/img/placeholders/UserAvatar6@2x.png | Bin 0 -> 1523 bytes app/img/placeholders/UserAvatar7@2x.png | Bin 0 -> 1477 bytes app/img/placeholders/UserAvatar8@2x.png | Bin 0 -> 1426 bytes app/index.html | 45 + app/js/app.js | 55 + app/js/background.js | 18 + app/js/controllers.js | 507 + app/js/directives.js | 512 + app/js/filters.js | 126 + app/js/lib/aes_worker.js | 21 + app/js/lib/config.js | 14 + app/js/lib/mtproto.js | 2612 + app/js/lib/pq_worker.js | 12 + app/js/lib/sha1_worker.js | 14 + app/js/services.js | 1439 + app/js/util.js | 55 + app/manifest.json | 18 + app/partials/chat_modal.html | 41 + app/partials/dialog.html | 73 + app/partials/head.html | 17 + app/partials/im.html | 118 + app/partials/login.html | 28 + app/partials/message.html | 91 + app/partials/photo_modal.html | 11 + app/partials/user_modal.html | 25 + app/partials/video_modal.html | 11 + app/partials/welcome.html | 5 + app/vendor/README.md | 70 + app/vendor/angular/angular-animate.js | 1294 + app/vendor/angular/angular-animate.min.js | 22 + app/vendor/angular/angular-animate.min.js.map | 8 + app/vendor/angular/angular-cookies.js | 202 + app/vendor/angular/angular-cookies.min.js | 8 + app/vendor/angular/angular-cookies.min.js.map | 8 + app/vendor/angular/angular-csp.css | 24 + app/vendor/angular/angular-loader.js | 410 + app/vendor/angular/angular-loader.min.js | 9 + app/vendor/angular/angular-loader.min.js.map | 8 + app/vendor/angular/angular-resource.js | 546 + app/vendor/angular/angular-resource.min.js | 12 + .../angular/angular-resource.min.js.map | 8 + app/vendor/angular/angular-route.js | 891 + app/vendor/angular/angular-route.min.js | 14 + app/vendor/angular/angular-route.min.js.map | 8 + app/vendor/angular/angular-sanitize.js | 615 + app/vendor/angular/angular-sanitize.min.js | 14 + .../angular/angular-sanitize.min.js.map | 8 + app/vendor/angular/angular-touch.js | 563 + app/vendor/angular/angular-touch.min.js | 13 + app/vendor/angular/angular-touch.min.js.map | 8 + app/vendor/angular/angular.js | 20282 +++ app/vendor/angular/angular.min.js | 201 + app/vendor/angular/angular.min.js.map | 8 + app/vendor/angular/errors.json | 1 + .../angular/i18n/angular-locale_af-na.js | 99 + .../angular/i18n/angular-locale_af-za.js | 99 + app/vendor/angular/i18n/angular-locale_af.js | 99 + .../angular/i18n/angular-locale_am-et.js | 99 + app/vendor/angular/i18n/angular-locale_am.js | 99 + .../angular/i18n/angular-locale_ar-001.js | 99 + .../angular/i18n/angular-locale_ar-ae.js | 99 + .../angular/i18n/angular-locale_ar-bh.js | 99 + .../angular/i18n/angular-locale_ar-dz.js | 99 + .../angular/i18n/angular-locale_ar-eg.js | 99 + .../angular/i18n/angular-locale_ar-iq.js | 99 + .../angular/i18n/angular-locale_ar-jo.js | 99 + .../angular/i18n/angular-locale_ar-kw.js | 99 + .../angular/i18n/angular-locale_ar-lb.js | 99 + .../angular/i18n/angular-locale_ar-ly.js | 99 + .../angular/i18n/angular-locale_ar-ma.js | 99 + .../angular/i18n/angular-locale_ar-om.js | 99 + .../angular/i18n/angular-locale_ar-qa.js | 99 + .../angular/i18n/angular-locale_ar-sa.js | 99 + .../angular/i18n/angular-locale_ar-sd.js | 99 + .../angular/i18n/angular-locale_ar-sy.js | 99 + .../angular/i18n/angular-locale_ar-tn.js | 99 + .../angular/i18n/angular-locale_ar-ye.js | 99 + app/vendor/angular/i18n/angular-locale_ar.js | 99 + .../angular/i18n/angular-locale_bg-bg.js | 99 + app/vendor/angular/i18n/angular-locale_bg.js | 99 + .../angular/i18n/angular-locale_bn-bd.js | 99 + .../angular/i18n/angular-locale_bn-in.js | 99 + app/vendor/angular/i18n/angular-locale_bn.js | 99 + .../angular/i18n/angular-locale_ca-ad.js | 99 + .../angular/i18n/angular-locale_ca-es.js | 99 + app/vendor/angular/i18n/angular-locale_ca.js | 99 + .../angular/i18n/angular-locale_cs-cz.js | 99 + app/vendor/angular/i18n/angular-locale_cs.js | 99 + .../angular/i18n/angular-locale_da-dk.js | 99 + app/vendor/angular/i18n/angular-locale_da.js | 99 + .../angular/i18n/angular-locale_de-at.js | 99 + .../angular/i18n/angular-locale_de-be.js | 99 + .../angular/i18n/angular-locale_de-ch.js | 99 + .../angular/i18n/angular-locale_de-de.js | 99 + .../angular/i18n/angular-locale_de-li.js | 99 + .../angular/i18n/angular-locale_de-lu.js | 99 + app/vendor/angular/i18n/angular-locale_de.js | 99 + .../angular/i18n/angular-locale_el-cy.js | 99 + .../angular/i18n/angular-locale_el-gr.js | 99 + app/vendor/angular/i18n/angular-locale_el.js | 99 + .../angular/i18n/angular-locale_en-as.js | 99 + .../angular/i18n/angular-locale_en-au.js | 99 + .../angular/i18n/angular-locale_en-bb.js | 99 + .../angular/i18n/angular-locale_en-be.js | 99 + .../angular/i18n/angular-locale_en-bm.js | 99 + .../angular/i18n/angular-locale_en-bw.js | 99 + .../angular/i18n/angular-locale_en-bz.js | 99 + .../angular/i18n/angular-locale_en-ca.js | 99 + .../angular/i18n/angular-locale_en-dsrt-us.js | 99 + .../angular/i18n/angular-locale_en-dsrt.js | 99 + .../angular/i18n/angular-locale_en-fm.js | 99 + .../angular/i18n/angular-locale_en-gb.js | 99 + .../angular/i18n/angular-locale_en-gu.js | 99 + .../angular/i18n/angular-locale_en-gy.js | 99 + .../angular/i18n/angular-locale_en-hk.js | 99 + .../angular/i18n/angular-locale_en-ie.js | 99 + .../angular/i18n/angular-locale_en-in.js | 99 + .../angular/i18n/angular-locale_en-iso.js | 99 + .../angular/i18n/angular-locale_en-jm.js | 99 + .../angular/i18n/angular-locale_en-mh.js | 99 + .../angular/i18n/angular-locale_en-mp.js | 99 + .../angular/i18n/angular-locale_en-mt.js | 99 + .../angular/i18n/angular-locale_en-mu.js | 99 + .../angular/i18n/angular-locale_en-na.js | 99 + .../angular/i18n/angular-locale_en-nz.js | 99 + .../angular/i18n/angular-locale_en-ph.js | 99 + .../angular/i18n/angular-locale_en-pk.js | 99 + .../angular/i18n/angular-locale_en-pr.js | 99 + .../angular/i18n/angular-locale_en-pw.js | 99 + .../angular/i18n/angular-locale_en-sg.js | 99 + .../angular/i18n/angular-locale_en-tc.js | 99 + .../angular/i18n/angular-locale_en-tt.js | 99 + .../angular/i18n/angular-locale_en-um.js | 99 + .../angular/i18n/angular-locale_en-us.js | 99 + .../angular/i18n/angular-locale_en-vg.js | 99 + .../angular/i18n/angular-locale_en-vi.js | 99 + .../angular/i18n/angular-locale_en-za.js | 99 + .../angular/i18n/angular-locale_en-zw.js | 99 + app/vendor/angular/i18n/angular-locale_en.js | 99 + .../angular/i18n/angular-locale_es-419.js | 99 + .../angular/i18n/angular-locale_es-ar.js | 99 + .../angular/i18n/angular-locale_es-bo.js | 99 + .../angular/i18n/angular-locale_es-cl.js | 99 + .../angular/i18n/angular-locale_es-co.js | 99 + .../angular/i18n/angular-locale_es-cr.js | 99 + .../angular/i18n/angular-locale_es-do.js | 99 + .../angular/i18n/angular-locale_es-ea.js | 99 + .../angular/i18n/angular-locale_es-ec.js | 99 + .../angular/i18n/angular-locale_es-es.js | 99 + .../angular/i18n/angular-locale_es-gq.js | 99 + .../angular/i18n/angular-locale_es-gt.js | 99 + .../angular/i18n/angular-locale_es-hn.js | 99 + .../angular/i18n/angular-locale_es-ic.js | 99 + .../angular/i18n/angular-locale_es-mx.js | 99 + .../angular/i18n/angular-locale_es-ni.js | 99 + .../angular/i18n/angular-locale_es-pa.js | 99 + .../angular/i18n/angular-locale_es-pe.js | 99 + .../angular/i18n/angular-locale_es-pr.js | 99 + .../angular/i18n/angular-locale_es-py.js | 99 + .../angular/i18n/angular-locale_es-sv.js | 99 + .../angular/i18n/angular-locale_es-us.js | 99 + .../angular/i18n/angular-locale_es-uy.js | 99 + .../angular/i18n/angular-locale_es-ve.js | 99 + app/vendor/angular/i18n/angular-locale_es.js | 99 + .../angular/i18n/angular-locale_et-ee.js | 99 + app/vendor/angular/i18n/angular-locale_et.js | 99 + .../angular/i18n/angular-locale_eu-es.js | 99 + app/vendor/angular/i18n/angular-locale_eu.js | 99 + .../angular/i18n/angular-locale_fa-af.js | 99 + .../angular/i18n/angular-locale_fa-ir.js | 99 + app/vendor/angular/i18n/angular-locale_fa.js | 99 + .../angular/i18n/angular-locale_fi-fi.js | 99 + app/vendor/angular/i18n/angular-locale_fi.js | 99 + .../angular/i18n/angular-locale_fil-ph.js | 99 + app/vendor/angular/i18n/angular-locale_fil.js | 99 + .../angular/i18n/angular-locale_fr-be.js | 99 + .../angular/i18n/angular-locale_fr-bf.js | 99 + .../angular/i18n/angular-locale_fr-bi.js | 99 + .../angular/i18n/angular-locale_fr-bj.js | 99 + .../angular/i18n/angular-locale_fr-bl.js | 99 + .../angular/i18n/angular-locale_fr-ca.js | 99 + .../angular/i18n/angular-locale_fr-cd.js | 99 + .../angular/i18n/angular-locale_fr-cf.js | 99 + .../angular/i18n/angular-locale_fr-cg.js | 99 + .../angular/i18n/angular-locale_fr-ch.js | 99 + .../angular/i18n/angular-locale_fr-ci.js | 99 + .../angular/i18n/angular-locale_fr-cm.js | 99 + .../angular/i18n/angular-locale_fr-dj.js | 99 + .../angular/i18n/angular-locale_fr-fr.js | 99 + .../angular/i18n/angular-locale_fr-ga.js | 99 + .../angular/i18n/angular-locale_fr-gf.js | 99 + .../angular/i18n/angular-locale_fr-gn.js | 99 + .../angular/i18n/angular-locale_fr-gp.js | 99 + .../angular/i18n/angular-locale_fr-gq.js | 99 + .../angular/i18n/angular-locale_fr-km.js | 99 + .../angular/i18n/angular-locale_fr-lu.js | 99 + .../angular/i18n/angular-locale_fr-mc.js | 99 + .../angular/i18n/angular-locale_fr-mf.js | 99 + .../angular/i18n/angular-locale_fr-mg.js | 99 + .../angular/i18n/angular-locale_fr-ml.js | 99 + .../angular/i18n/angular-locale_fr-mq.js | 99 + .../angular/i18n/angular-locale_fr-ne.js | 99 + .../angular/i18n/angular-locale_fr-re.js | 99 + .../angular/i18n/angular-locale_fr-yt.js | 99 + app/vendor/angular/i18n/angular-locale_fr.js | 99 + .../angular/i18n/angular-locale_gl-es.js | 99 + app/vendor/angular/i18n/angular-locale_gl.js | 99 + .../angular/i18n/angular-locale_gsw-ch.js | 99 + app/vendor/angular/i18n/angular-locale_gsw.js | 99 + .../angular/i18n/angular-locale_gu-in.js | 99 + app/vendor/angular/i18n/angular-locale_gu.js | 99 + .../angular/i18n/angular-locale_he-il.js | 99 + app/vendor/angular/i18n/angular-locale_he.js | 99 + .../angular/i18n/angular-locale_hi-in.js | 99 + app/vendor/angular/i18n/angular-locale_hi.js | 99 + .../angular/i18n/angular-locale_hr-hr.js | 99 + app/vendor/angular/i18n/angular-locale_hr.js | 99 + .../angular/i18n/angular-locale_hu-hu.js | 99 + app/vendor/angular/i18n/angular-locale_hu.js | 99 + .../angular/i18n/angular-locale_id-id.js | 99 + app/vendor/angular/i18n/angular-locale_id.js | 99 + app/vendor/angular/i18n/angular-locale_in.js | 99 + .../angular/i18n/angular-locale_is-is.js | 99 + app/vendor/angular/i18n/angular-locale_is.js | 99 + .../angular/i18n/angular-locale_it-it.js | 99 + .../angular/i18n/angular-locale_it-sm.js | 99 + app/vendor/angular/i18n/angular-locale_it.js | 99 + app/vendor/angular/i18n/angular-locale_iw.js | 99 + .../angular/i18n/angular-locale_ja-jp.js | 99 + app/vendor/angular/i18n/angular-locale_ja.js | 99 + .../angular/i18n/angular-locale_kn-in.js | 99 + app/vendor/angular/i18n/angular-locale_kn.js | 99 + .../angular/i18n/angular-locale_ko-kr.js | 99 + app/vendor/angular/i18n/angular-locale_ko.js | 99 + .../angular/i18n/angular-locale_ln-cd.js | 99 + app/vendor/angular/i18n/angular-locale_ln.js | 99 + .../angular/i18n/angular-locale_lt-lt.js | 99 + app/vendor/angular/i18n/angular-locale_lt.js | 99 + .../angular/i18n/angular-locale_lv-lv.js | 99 + app/vendor/angular/i18n/angular-locale_lv.js | 99 + .../angular/i18n/angular-locale_ml-in.js | 99 + app/vendor/angular/i18n/angular-locale_ml.js | 99 + .../angular/i18n/angular-locale_mr-in.js | 99 + app/vendor/angular/i18n/angular-locale_mr.js | 99 + .../angular/i18n/angular-locale_ms-my.js | 99 + app/vendor/angular/i18n/angular-locale_ms.js | 99 + .../angular/i18n/angular-locale_mt-mt.js | 99 + app/vendor/angular/i18n/angular-locale_mt.js | 99 + .../angular/i18n/angular-locale_nl-cw.js | 99 + .../angular/i18n/angular-locale_nl-nl.js | 99 + .../angular/i18n/angular-locale_nl-sx.js | 99 + app/vendor/angular/i18n/angular-locale_nl.js | 99 + app/vendor/angular/i18n/angular-locale_no.js | 99 + .../angular/i18n/angular-locale_or-in.js | 99 + app/vendor/angular/i18n/angular-locale_or.js | 99 + .../angular/i18n/angular-locale_pl-pl.js | 99 + app/vendor/angular/i18n/angular-locale_pl.js | 99 + .../angular/i18n/angular-locale_pt-br.js | 99 + .../angular/i18n/angular-locale_pt-pt.js | 99 + app/vendor/angular/i18n/angular-locale_pt.js | 99 + .../angular/i18n/angular-locale_ro-ro.js | 99 + app/vendor/angular/i18n/angular-locale_ro.js | 99 + .../angular/i18n/angular-locale_ru-ru.js | 99 + app/vendor/angular/i18n/angular-locale_ru.js | 99 + .../angular/i18n/angular-locale_sk-sk.js | 99 + app/vendor/angular/i18n/angular-locale_sk.js | 99 + .../angular/i18n/angular-locale_sl-si.js | 99 + app/vendor/angular/i18n/angular-locale_sl.js | 99 + .../angular/i18n/angular-locale_sq-al.js | 99 + app/vendor/angular/i18n/angular-locale_sq.js | 99 + .../angular/i18n/angular-locale_sr-cyrl-rs.js | 99 + .../angular/i18n/angular-locale_sr-latn-rs.js | 99 + app/vendor/angular/i18n/angular-locale_sr.js | 99 + .../angular/i18n/angular-locale_sv-se.js | 99 + app/vendor/angular/i18n/angular-locale_sv.js | 99 + .../angular/i18n/angular-locale_sw-tz.js | 99 + app/vendor/angular/i18n/angular-locale_sw.js | 99 + .../angular/i18n/angular-locale_ta-in.js | 99 + app/vendor/angular/i18n/angular-locale_ta.js | 99 + .../angular/i18n/angular-locale_te-in.js | 99 + app/vendor/angular/i18n/angular-locale_te.js | 99 + .../angular/i18n/angular-locale_th-th.js | 99 + app/vendor/angular/i18n/angular-locale_th.js | 99 + app/vendor/angular/i18n/angular-locale_tl.js | 99 + .../angular/i18n/angular-locale_tr-tr.js | 99 + app/vendor/angular/i18n/angular-locale_tr.js | 99 + .../angular/i18n/angular-locale_uk-ua.js | 99 + app/vendor/angular/i18n/angular-locale_uk.js | 99 + .../angular/i18n/angular-locale_ur-pk.js | 99 + app/vendor/angular/i18n/angular-locale_ur.js | 99 + .../angular/i18n/angular-locale_vi-vn.js | 99 + app/vendor/angular/i18n/angular-locale_vi.js | 99 + .../angular/i18n/angular-locale_zh-cn.js | 99 + .../angular/i18n/angular-locale_zh-hans-cn.js | 99 + .../angular/i18n/angular-locale_zh-hk.js | 99 + .../angular/i18n/angular-locale_zh-tw.js | 99 + app/vendor/angular/i18n/angular-locale_zh.js | 99 + .../angular/i18n/angular-locale_zu-za.js | 99 + app/vendor/angular/i18n/angular-locale_zu.js | 99 + app/vendor/angular/version.json | 1 + app/vendor/angular/version.txt | 1 + app/vendor/bootstrap/css/bootstrap.css | 7098 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20290 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41236 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23292 bytes app/vendor/bootstrap/js/bootstrap.js | 2002 + app/vendor/cryptoJS/THIRDPARTY_LICENSE | 7 + app/vendor/cryptoJS/crypto.js | 2042 + app/vendor/gemoji/THIRDPARTY_LICENSE | 14 + app/vendor/gemoji/images/0023-20e3.png | Bin 0 -> 3742 bytes app/vendor/gemoji/images/0023-fe0f-20e3.png | Bin 0 -> 3742 bytes app/vendor/gemoji/images/0030-20e3.png | Bin 0 -> 3611 bytes app/vendor/gemoji/images/0030-fe0f-20e3.png | Bin 0 -> 3611 bytes app/vendor/gemoji/images/0031-20e3.png | Bin 0 -> 2825 bytes app/vendor/gemoji/images/0031-fe0f-20e3.png | Bin 0 -> 2825 bytes app/vendor/gemoji/images/0032-20e3.png | Bin 0 -> 3518 bytes app/vendor/gemoji/images/0032-fe0f-20e3.png | Bin 0 -> 3518 bytes app/vendor/gemoji/images/0033-20e3.png | Bin 0 -> 3758 bytes app/vendor/gemoji/images/0033-fe0f-20e3.png | Bin 0 -> 3758 bytes app/vendor/gemoji/images/0034-20e3.png | Bin 0 -> 3176 bytes app/vendor/gemoji/images/0034-fe0f-20e3.png | Bin 0 -> 3176 bytes app/vendor/gemoji/images/0035-20e3.png | Bin 0 -> 3593 bytes app/vendor/gemoji/images/0035-fe0f-20e3.png | Bin 0 -> 3593 bytes app/vendor/gemoji/images/0036-20e3.png | Bin 0 -> 3791 bytes app/vendor/gemoji/images/0036-fe0f-20e3.png | Bin 0 -> 3791 bytes app/vendor/gemoji/images/0037-20e3.png | Bin 0 -> 3055 bytes app/vendor/gemoji/images/0037-fe0f-20e3.png | Bin 0 -> 3055 bytes app/vendor/gemoji/images/0038-20e3.png | Bin 0 -> 3844 bytes app/vendor/gemoji/images/0038-fe0f-20e3.png | Bin 0 -> 3844 bytes app/vendor/gemoji/images/0039-20e3.png | Bin 0 -> 3776 bytes app/vendor/gemoji/images/0039-fe0f-20e3.png | Bin 0 -> 3776 bytes app/vendor/gemoji/images/00a9.png | Bin 0 -> 1600 bytes app/vendor/gemoji/images/00ae.png | Bin 0 -> 1634 bytes app/vendor/gemoji/images/1f004-fe0f.png | Bin 0 -> 3309 bytes app/vendor/gemoji/images/1f004.png | Bin 0 -> 3309 bytes app/vendor/gemoji/images/1f0cf.png | Bin 0 -> 3877 bytes app/vendor/gemoji/images/1f170.png | Bin 0 -> 3175 bytes app/vendor/gemoji/images/1f171.png | Bin 0 -> 3025 bytes app/vendor/gemoji/images/1f17e.png | Bin 0 -> 3498 bytes app/vendor/gemoji/images/1f17f-fe0f.png | Bin 0 -> 3083 bytes app/vendor/gemoji/images/1f17f.png | Bin 0 -> 3083 bytes app/vendor/gemoji/images/1f18e.png | Bin 0 -> 3859 bytes app/vendor/gemoji/images/1f191.png | Bin 0 -> 3493 bytes app/vendor/gemoji/images/1f192.png | Bin 0 -> 4182 bytes app/vendor/gemoji/images/1f193.png | Bin 0 -> 3605 bytes app/vendor/gemoji/images/1f194.png | Bin 0 -> 3905 bytes app/vendor/gemoji/images/1f195.png | Bin 0 -> 3927 bytes app/vendor/gemoji/images/1f196.png | Bin 0 -> 4201 bytes app/vendor/gemoji/images/1f197.png | Bin 0 -> 4158 bytes app/vendor/gemoji/images/1f198.png | Bin 0 -> 4262 bytes app/vendor/gemoji/images/1f199.png | Bin 0 -> 3721 bytes app/vendor/gemoji/images/1f19a.png | Bin 0 -> 3424 bytes app/vendor/gemoji/images/1f1e8-1f1f3.png | Bin 0 -> 3634 bytes app/vendor/gemoji/images/1f1e9-1f1ea.png | Bin 0 -> 2640 bytes app/vendor/gemoji/images/1f1ea-1f1f8.png | Bin 0 -> 4302 bytes app/vendor/gemoji/images/1f1eb-1f1f7.png | Bin 0 -> 3398 bytes app/vendor/gemoji/images/1f1ec-1f1e7.png | Bin 0 -> 5894 bytes app/vendor/gemoji/images/1f1ee-1f1f9.png | Bin 0 -> 3495 bytes app/vendor/gemoji/images/1f1ef-1f1f5.png | Bin 0 -> 2827 bytes app/vendor/gemoji/images/1f1f0-1f1f7.png | Bin 0 -> 5105 bytes app/vendor/gemoji/images/1f1f7-1f1fa.png | Bin 0 -> 3920 bytes app/vendor/gemoji/images/1f1fa-1f1f8.png | Bin 0 -> 6285 bytes app/vendor/gemoji/images/1f201.png | Bin 0 -> 2854 bytes app/vendor/gemoji/images/1f202.png | Bin 0 -> 3556 bytes app/vendor/gemoji/images/1f21a-fe0f.png | Bin 0 -> 3942 bytes app/vendor/gemoji/images/1f21a.png | Bin 0 -> 3942 bytes app/vendor/gemoji/images/1f22f-fe0f.png | Bin 0 -> 4103 bytes app/vendor/gemoji/images/1f22f.png | Bin 0 -> 4103 bytes app/vendor/gemoji/images/1f232.png | Bin 0 -> 5175 bytes app/vendor/gemoji/images/1f233.png | Bin 0 -> 4180 bytes app/vendor/gemoji/images/1f234.png | Bin 0 -> 3890 bytes app/vendor/gemoji/images/1f235.png | Bin 0 -> 4419 bytes app/vendor/gemoji/images/1f236.png | Bin 0 -> 3198 bytes app/vendor/gemoji/images/1f237.png | Bin 0 -> 3011 bytes app/vendor/gemoji/images/1f238.png | Bin 0 -> 3048 bytes app/vendor/gemoji/images/1f239.png | Bin 0 -> 4533 bytes app/vendor/gemoji/images/1f23a.png | Bin 0 -> 3411 bytes app/vendor/gemoji/images/1f250.png | Bin 0 -> 3095 bytes app/vendor/gemoji/images/1f251.png | Bin 0 -> 4729 bytes app/vendor/gemoji/images/1f300.png | Bin 0 -> 4986 bytes app/vendor/gemoji/images/1f301.png | Bin 0 -> 4623 bytes app/vendor/gemoji/images/1f302.png | Bin 0 -> 3964 bytes app/vendor/gemoji/images/1f303.png | Bin 0 -> 4963 bytes app/vendor/gemoji/images/1f304.png | Bin 0 -> 6594 bytes app/vendor/gemoji/images/1f305.png | Bin 0 -> 3914 bytes app/vendor/gemoji/images/1f306.png | Bin 0 -> 3841 bytes app/vendor/gemoji/images/1f307.png | Bin 0 -> 4312 bytes app/vendor/gemoji/images/1f308.png | Bin 0 -> 5314 bytes app/vendor/gemoji/images/1f309.png | Bin 0 -> 5137 bytes app/vendor/gemoji/images/1f30a.png | Bin 0 -> 5777 bytes app/vendor/gemoji/images/1f30b.png | Bin 0 -> 6167 bytes app/vendor/gemoji/images/1f30c.png | Bin 0 -> 5878 bytes app/vendor/gemoji/images/1f30d.png | Bin 0 -> 7164 bytes app/vendor/gemoji/images/1f30e.png | Bin 0 -> 7039 bytes app/vendor/gemoji/images/1f30f.png | Bin 0 -> 7303 bytes app/vendor/gemoji/images/1f310.png | Bin 0 -> 5837 bytes app/vendor/gemoji/images/1f311.png | Bin 0 -> 5371 bytes app/vendor/gemoji/images/1f312.png | Bin 0 -> 6198 bytes app/vendor/gemoji/images/1f313.png | Bin 0 -> 5967 bytes app/vendor/gemoji/images/1f314.png | Bin 0 -> 6455 bytes app/vendor/gemoji/images/1f315.png | Bin 0 -> 6458 bytes app/vendor/gemoji/images/1f316.png | Bin 0 -> 6510 bytes app/vendor/gemoji/images/1f317.png | Bin 0 -> 6176 bytes app/vendor/gemoji/images/1f318.png | Bin 0 -> 5885 bytes app/vendor/gemoji/images/1f319.png | Bin 0 -> 3541 bytes app/vendor/gemoji/images/1f31a.png | Bin 0 -> 6750 bytes app/vendor/gemoji/images/1f31b.png | Bin 0 -> 4280 bytes app/vendor/gemoji/images/1f31c.png | Bin 0 -> 4328 bytes app/vendor/gemoji/images/1f31d.png | Bin 0 -> 7224 bytes app/vendor/gemoji/images/1f31e.png | Bin 0 -> 7958 bytes app/vendor/gemoji/images/1f31f.png | Bin 0 -> 4068 bytes app/vendor/gemoji/images/1f320.png | Bin 0 -> 4366 bytes app/vendor/gemoji/images/1f330.png | Bin 0 -> 5875 bytes app/vendor/gemoji/images/1f331.png | Bin 0 -> 2260 bytes app/vendor/gemoji/images/1f332.png | Bin 0 -> 4924 bytes app/vendor/gemoji/images/1f333.png | Bin 0 -> 7374 bytes app/vendor/gemoji/images/1f334.png | Bin 0 -> 3664 bytes app/vendor/gemoji/images/1f335.png | Bin 0 -> 4509 bytes app/vendor/gemoji/images/1f337.png | Bin 0 -> 6065 bytes app/vendor/gemoji/images/1f338.png | Bin 0 -> 7174 bytes app/vendor/gemoji/images/1f339.png | Bin 0 -> 4202 bytes app/vendor/gemoji/images/1f33a.png | Bin 0 -> 8352 bytes app/vendor/gemoji/images/1f33b.png | Bin 0 -> 6567 bytes app/vendor/gemoji/images/1f33c.png | Bin 0 -> 4232 bytes app/vendor/gemoji/images/1f33d.png | Bin 0 -> 6694 bytes app/vendor/gemoji/images/1f33e.png | Bin 0 -> 4758 bytes app/vendor/gemoji/images/1f33f.png | Bin 0 -> 5889 bytes app/vendor/gemoji/images/1f340.png | Bin 0 -> 5995 bytes app/vendor/gemoji/images/1f341.png | Bin 0 -> 4450 bytes app/vendor/gemoji/images/1f342.png | Bin 0 -> 4890 bytes app/vendor/gemoji/images/1f343.png | Bin 0 -> 5649 bytes app/vendor/gemoji/images/1f344.png | Bin 0 -> 4887 bytes app/vendor/gemoji/images/1f345.png | Bin 0 -> 5748 bytes app/vendor/gemoji/images/1f346.png | Bin 0 -> 4800 bytes app/vendor/gemoji/images/1f347.png | Bin 0 -> 5423 bytes app/vendor/gemoji/images/1f348.png | Bin 0 -> 8233 bytes app/vendor/gemoji/images/1f349.png | Bin 0 -> 5501 bytes app/vendor/gemoji/images/1f34a.png | Bin 0 -> 6645 bytes app/vendor/gemoji/images/1f34b.png | Bin 0 -> 6055 bytes app/vendor/gemoji/images/1f34c.png | Bin 0 -> 3915 bytes app/vendor/gemoji/images/1f34d.png | Bin 0 -> 5634 bytes app/vendor/gemoji/images/1f34e.png | Bin 0 -> 5630 bytes app/vendor/gemoji/images/1f34f.png | Bin 0 -> 6205 bytes app/vendor/gemoji/images/1f350.png | Bin 0 -> 6936 bytes app/vendor/gemoji/images/1f351.png | Bin 0 -> 5920 bytes app/vendor/gemoji/images/1f352.png | Bin 0 -> 5604 bytes app/vendor/gemoji/images/1f353.png | Bin 0 -> 5477 bytes app/vendor/gemoji/images/1f354.png | Bin 0 -> 5706 bytes app/vendor/gemoji/images/1f355.png | Bin 0 -> 5273 bytes app/vendor/gemoji/images/1f356.png | Bin 0 -> 5534 bytes app/vendor/gemoji/images/1f357.png | Bin 0 -> 4200 bytes app/vendor/gemoji/images/1f358.png | Bin 0 -> 7787 bytes app/vendor/gemoji/images/1f359.png | Bin 0 -> 5408 bytes app/vendor/gemoji/images/1f35a.png | Bin 0 -> 4743 bytes app/vendor/gemoji/images/1f35b.png | Bin 0 -> 5336 bytes app/vendor/gemoji/images/1f35c.png | Bin 0 -> 6574 bytes app/vendor/gemoji/images/1f35d.png | Bin 0 -> 6955 bytes app/vendor/gemoji/images/1f35e.png | Bin 0 -> 6214 bytes app/vendor/gemoji/images/1f35f.png | Bin 0 -> 6405 bytes app/vendor/gemoji/images/1f360.png | Bin 0 -> 5684 bytes app/vendor/gemoji/images/1f361.png | Bin 0 -> 4449 bytes app/vendor/gemoji/images/1f362.png | Bin 0 -> 5543 bytes app/vendor/gemoji/images/1f363.png | Bin 0 -> 5257 bytes app/vendor/gemoji/images/1f364.png | Bin 0 -> 7550 bytes app/vendor/gemoji/images/1f365.png | Bin 0 -> 5818 bytes app/vendor/gemoji/images/1f366.png | Bin 0 -> 4603 bytes app/vendor/gemoji/images/1f367.png | Bin 0 -> 5908 bytes app/vendor/gemoji/images/1f368.png | Bin 0 -> 5469 bytes app/vendor/gemoji/images/1f369.png | Bin 0 -> 5209 bytes app/vendor/gemoji/images/1f36a.png | Bin 0 -> 8149 bytes app/vendor/gemoji/images/1f36b.png | Bin 0 -> 5249 bytes app/vendor/gemoji/images/1f36c.png | Bin 0 -> 4502 bytes app/vendor/gemoji/images/1f36d.png | Bin 0 -> 5771 bytes app/vendor/gemoji/images/1f36e.png | Bin 0 -> 5810 bytes app/vendor/gemoji/images/1f36f.png | Bin 0 -> 5830 bytes app/vendor/gemoji/images/1f370.png | Bin 0 -> 6129 bytes app/vendor/gemoji/images/1f371.png | Bin 0 -> 5732 bytes app/vendor/gemoji/images/1f372.png | Bin 0 -> 5612 bytes app/vendor/gemoji/images/1f373.png | Bin 0 -> 5211 bytes app/vendor/gemoji/images/1f374.png | Bin 0 -> 3608 bytes app/vendor/gemoji/images/1f375.png | Bin 0 -> 5954 bytes app/vendor/gemoji/images/1f376.png | Bin 0 -> 5073 bytes app/vendor/gemoji/images/1f377.png | Bin 0 -> 3151 bytes app/vendor/gemoji/images/1f378.png | Bin 0 -> 2949 bytes app/vendor/gemoji/images/1f379.png | Bin 0 -> 4189 bytes app/vendor/gemoji/images/1f37a.png | Bin 0 -> 6097 bytes app/vendor/gemoji/images/1f37b.png | Bin 0 -> 6591 bytes app/vendor/gemoji/images/1f37c.png | Bin 0 -> 4461 bytes app/vendor/gemoji/images/1f380.png | Bin 0 -> 5581 bytes app/vendor/gemoji/images/1f381.png | Bin 0 -> 6712 bytes app/vendor/gemoji/images/1f382.png | Bin 0 -> 5404 bytes app/vendor/gemoji/images/1f383.png | Bin 0 -> 5633 bytes app/vendor/gemoji/images/1f384.png | Bin 0 -> 4721 bytes app/vendor/gemoji/images/1f385.png | Bin 0 -> 6271 bytes app/vendor/gemoji/images/1f386.png | Bin 0 -> 6269 bytes app/vendor/gemoji/images/1f387.png | Bin 0 -> 5696 bytes app/vendor/gemoji/images/1f388.png | Bin 0 -> 2417 bytes app/vendor/gemoji/images/1f389.png | Bin 0 -> 5945 bytes app/vendor/gemoji/images/1f38a.png | Bin 0 -> 5521 bytes app/vendor/gemoji/images/1f38b.png | Bin 0 -> 4409 bytes app/vendor/gemoji/images/1f38c.png | Bin 0 -> 4036 bytes app/vendor/gemoji/images/1f38d.png | Bin 0 -> 4672 bytes app/vendor/gemoji/images/1f38e.png | Bin 0 -> 7138 bytes app/vendor/gemoji/images/1f38f.png | Bin 0 -> 6124 bytes app/vendor/gemoji/images/1f390.png | Bin 0 -> 3487 bytes app/vendor/gemoji/images/1f391.png | Bin 0 -> 6261 bytes app/vendor/gemoji/images/1f392.png | Bin 0 -> 5741 bytes app/vendor/gemoji/images/1f393.png | Bin 0 -> 4165 bytes app/vendor/gemoji/images/1f3a0.png | Bin 0 -> 5893 bytes app/vendor/gemoji/images/1f3a1.png | Bin 0 -> 6213 bytes app/vendor/gemoji/images/1f3a2.png | Bin 0 -> 5148 bytes app/vendor/gemoji/images/1f3a3.png | Bin 0 -> 4470 bytes app/vendor/gemoji/images/1f3a4.png | Bin 0 -> 3741 bytes app/vendor/gemoji/images/1f3a5.png | Bin 0 -> 4081 bytes app/vendor/gemoji/images/1f3a6.png | Bin 0 -> 3573 bytes app/vendor/gemoji/images/1f3a7.png | Bin 0 -> 1910 bytes app/vendor/gemoji/images/1f3a8.png | Bin 0 -> 6744 bytes app/vendor/gemoji/images/1f3a9.png | Bin 0 -> 3009 bytes app/vendor/gemoji/images/1f3aa.png | Bin 0 -> 4683 bytes app/vendor/gemoji/images/1f3ab.png | Bin 0 -> 3091 bytes app/vendor/gemoji/images/1f3ac.png | Bin 0 -> 4192 bytes app/vendor/gemoji/images/1f3ad.png | Bin 0 -> 6287 bytes app/vendor/gemoji/images/1f3ae.png | Bin 0 -> 4957 bytes app/vendor/gemoji/images/1f3af.png | Bin 0 -> 5462 bytes app/vendor/gemoji/images/1f3b0.png | Bin 0 -> 4605 bytes app/vendor/gemoji/images/1f3b1.png | Bin 0 -> 4141 bytes app/vendor/gemoji/images/1f3b2.png | Bin 0 -> 2957 bytes app/vendor/gemoji/images/1f3b3.png | Bin 0 -> 4184 bytes app/vendor/gemoji/images/1f3b4.png | Bin 0 -> 3434 bytes app/vendor/gemoji/images/1f3b5.png | Bin 0 -> 3188 bytes app/vendor/gemoji/images/1f3b6.png | Bin 0 -> 1614 bytes app/vendor/gemoji/images/1f3b7.png | Bin 0 -> 4252 bytes app/vendor/gemoji/images/1f3b8.png | Bin 0 -> 4382 bytes app/vendor/gemoji/images/1f3b9.png | Bin 0 -> 1944 bytes app/vendor/gemoji/images/1f3ba.png | Bin 0 -> 4453 bytes app/vendor/gemoji/images/1f3bb.png | Bin 0 -> 5020 bytes app/vendor/gemoji/images/1f3bc.png | Bin 0 -> 1576 bytes app/vendor/gemoji/images/1f3bd.png | Bin 0 -> 5701 bytes app/vendor/gemoji/images/1f3be.png | Bin 0 -> 5976 bytes app/vendor/gemoji/images/1f3bf.png | Bin 0 -> 4247 bytes app/vendor/gemoji/images/1f3c0.png | Bin 0 -> 6386 bytes app/vendor/gemoji/images/1f3c1.png | Bin 0 -> 1675 bytes app/vendor/gemoji/images/1f3c2.png | Bin 0 -> 5356 bytes app/vendor/gemoji/images/1f3c3.png | Bin 0 -> 3214 bytes app/vendor/gemoji/images/1f3c4.png | Bin 0 -> 6259 bytes app/vendor/gemoji/images/1f3c6.png | Bin 0 -> 5520 bytes app/vendor/gemoji/images/1f3c7.png | Bin 0 -> 5905 bytes app/vendor/gemoji/images/1f3c8.png | Bin 0 -> 6712 bytes app/vendor/gemoji/images/1f3c9.png | Bin 0 -> 7781 bytes app/vendor/gemoji/images/1f3ca.png | Bin 0 -> 4378 bytes app/vendor/gemoji/images/1f3e0.png | Bin 0 -> 3510 bytes app/vendor/gemoji/images/1f3e1.png | Bin 0 -> 8536 bytes app/vendor/gemoji/images/1f3e2.png | Bin 0 -> 5171 bytes app/vendor/gemoji/images/1f3e3.png | Bin 0 -> 5136 bytes app/vendor/gemoji/images/1f3e4.png | Bin 0 -> 4816 bytes app/vendor/gemoji/images/1f3e5.png | Bin 0 -> 4887 bytes app/vendor/gemoji/images/1f3e6.png | Bin 0 -> 5583 bytes app/vendor/gemoji/images/1f3e7.png | Bin 0 -> 4072 bytes app/vendor/gemoji/images/1f3e8.png | Bin 0 -> 5123 bytes app/vendor/gemoji/images/1f3e9.png | Bin 0 -> 5941 bytes app/vendor/gemoji/images/1f3ea.png | Bin 0 -> 4073 bytes app/vendor/gemoji/images/1f3eb.png | Bin 0 -> 5446 bytes app/vendor/gemoji/images/1f3ec.png | Bin 0 -> 5159 bytes app/vendor/gemoji/images/1f3ed.png | Bin 0 -> 5558 bytes app/vendor/gemoji/images/1f3ee.png | Bin 0 -> 4064 bytes app/vendor/gemoji/images/1f3ef.png | Bin 0 -> 4939 bytes app/vendor/gemoji/images/1f3f0.png | Bin 0 -> 5427 bytes app/vendor/gemoji/images/1f400.png | Bin 0 -> 5441 bytes app/vendor/gemoji/images/1f401.png | Bin 0 -> 4087 bytes app/vendor/gemoji/images/1f402.png | Bin 0 -> 6079 bytes app/vendor/gemoji/images/1f403.png | Bin 0 -> 4774 bytes app/vendor/gemoji/images/1f404.png | Bin 0 -> 5303 bytes app/vendor/gemoji/images/1f405.png | Bin 0 -> 5744 bytes app/vendor/gemoji/images/1f406.png | Bin 0 -> 5384 bytes app/vendor/gemoji/images/1f407.png | Bin 0 -> 4517 bytes app/vendor/gemoji/images/1f408.png | Bin 0 -> 5723 bytes app/vendor/gemoji/images/1f409.png | Bin 0 -> 7828 bytes app/vendor/gemoji/images/1f40a.png | Bin 0 -> 6125 bytes app/vendor/gemoji/images/1f40b.png | Bin 0 -> 6032 bytes app/vendor/gemoji/images/1f40c.png | Bin 0 -> 6657 bytes app/vendor/gemoji/images/1f40d.png | Bin 0 -> 4069 bytes app/vendor/gemoji/images/1f40e.png | Bin 0 -> 4735 bytes app/vendor/gemoji/images/1f40f.png | Bin 0 -> 6531 bytes app/vendor/gemoji/images/1f410.png | Bin 0 -> 4889 bytes app/vendor/gemoji/images/1f411.png | Bin 0 -> 4732 bytes app/vendor/gemoji/images/1f412.png | Bin 0 -> 4973 bytes app/vendor/gemoji/images/1f413.png | Bin 0 -> 6168 bytes app/vendor/gemoji/images/1f414.png | Bin 0 -> 3988 bytes app/vendor/gemoji/images/1f415.png | Bin 0 -> 5931 bytes app/vendor/gemoji/images/1f416.png | Bin 0 -> 4797 bytes app/vendor/gemoji/images/1f417.png | Bin 0 -> 4840 bytes app/vendor/gemoji/images/1f418.png | Bin 0 -> 5086 bytes app/vendor/gemoji/images/1f419.png | Bin 0 -> 5779 bytes app/vendor/gemoji/images/1f41a.png | Bin 0 -> 5115 bytes app/vendor/gemoji/images/1f41b.png | Bin 0 -> 5945 bytes app/vendor/gemoji/images/1f41c.png | Bin 0 -> 2851 bytes app/vendor/gemoji/images/1f41d.png | Bin 0 -> 5851 bytes app/vendor/gemoji/images/1f41e.png | Bin 0 -> 5255 bytes app/vendor/gemoji/images/1f41f.png | Bin 0 -> 4743 bytes app/vendor/gemoji/images/1f420.png | Bin 0 -> 5846 bytes app/vendor/gemoji/images/1f421.png | Bin 0 -> 3751 bytes app/vendor/gemoji/images/1f422.png | Bin 0 -> 5336 bytes app/vendor/gemoji/images/1f423.png | Bin 0 -> 5928 bytes app/vendor/gemoji/images/1f424.png | Bin 0 -> 3961 bytes app/vendor/gemoji/images/1f425.png | Bin 0 -> 5646 bytes app/vendor/gemoji/images/1f426.png | Bin 0 -> 4878 bytes app/vendor/gemoji/images/1f427.png | Bin 0 -> 4746 bytes app/vendor/gemoji/images/1f428.png | Bin 0 -> 5687 bytes app/vendor/gemoji/images/1f429.png | Bin 0 -> 6852 bytes app/vendor/gemoji/images/1f42a.png | Bin 0 -> 5139 bytes app/vendor/gemoji/images/1f42b.png | Bin 0 -> 4485 bytes app/vendor/gemoji/images/1f42c.png | Bin 0 -> 4343 bytes app/vendor/gemoji/images/1f42d.png | Bin 0 -> 6625 bytes app/vendor/gemoji/images/1f42e.png | Bin 0 -> 5745 bytes app/vendor/gemoji/images/1f42f.png | Bin 0 -> 6051 bytes app/vendor/gemoji/images/1f430.png | Bin 0 -> 5677 bytes app/vendor/gemoji/images/1f431.png | Bin 0 -> 5987 bytes app/vendor/gemoji/images/1f432.png | Bin 0 -> 6737 bytes app/vendor/gemoji/images/1f433.png | Bin 0 -> 4940 bytes app/vendor/gemoji/images/1f434.png | Bin 0 -> 4582 bytes app/vendor/gemoji/images/1f435.png | Bin 0 -> 5348 bytes app/vendor/gemoji/images/1f436.png | Bin 0 -> 5945 bytes app/vendor/gemoji/images/1f437.png | Bin 0 -> 5996 bytes app/vendor/gemoji/images/1f438.png | Bin 0 -> 4823 bytes app/vendor/gemoji/images/1f439.png | Bin 0 -> 7371 bytes app/vendor/gemoji/images/1f43a.png | Bin 0 -> 4845 bytes app/vendor/gemoji/images/1f43b.png | Bin 0 -> 5561 bytes app/vendor/gemoji/images/1f43c.png | Bin 0 -> 4814 bytes app/vendor/gemoji/images/1f43d.png | Bin 0 -> 4761 bytes app/vendor/gemoji/images/1f43e.png | Bin 0 -> 2471 bytes app/vendor/gemoji/images/1f440.png | Bin 0 -> 4398 bytes app/vendor/gemoji/images/1f442.png | Bin 0 -> 4335 bytes app/vendor/gemoji/images/1f443.png | Bin 0 -> 3703 bytes app/vendor/gemoji/images/1f444.png | Bin 0 -> 3738 bytes app/vendor/gemoji/images/1f445.png | Bin 0 -> 3662 bytes app/vendor/gemoji/images/1f446.png | Bin 0 -> 3207 bytes app/vendor/gemoji/images/1f447.png | Bin 0 -> 3225 bytes app/vendor/gemoji/images/1f448.png | Bin 0 -> 3113 bytes app/vendor/gemoji/images/1f449.png | Bin 0 -> 3122 bytes app/vendor/gemoji/images/1f44a.png | Bin 0 -> 4873 bytes app/vendor/gemoji/images/1f44b.png | Bin 0 -> 5048 bytes app/vendor/gemoji/images/1f44c.png | Bin 0 -> 4696 bytes app/vendor/gemoji/images/1f44d.png | Bin 0 -> 5135 bytes app/vendor/gemoji/images/1f44e.png | Bin 0 -> 5129 bytes app/vendor/gemoji/images/1f44f.png | Bin 0 -> 7110 bytes app/vendor/gemoji/images/1f450.png | Bin 0 -> 4951 bytes app/vendor/gemoji/images/1f451.png | Bin 0 -> 5655 bytes app/vendor/gemoji/images/1f452.png | Bin 0 -> 8101 bytes app/vendor/gemoji/images/1f453.png | Bin 0 -> 4929 bytes app/vendor/gemoji/images/1f454.png | Bin 0 -> 6116 bytes app/vendor/gemoji/images/1f455.png | Bin 0 -> 4676 bytes app/vendor/gemoji/images/1f456.png | Bin 0 -> 3470 bytes app/vendor/gemoji/images/1f457.png | Bin 0 -> 3631 bytes app/vendor/gemoji/images/1f458.png | Bin 0 -> 4938 bytes app/vendor/gemoji/images/1f459.png | Bin 0 -> 3890 bytes app/vendor/gemoji/images/1f45a.png | Bin 0 -> 4075 bytes app/vendor/gemoji/images/1f45b.png | Bin 0 -> 5033 bytes app/vendor/gemoji/images/1f45c.png | Bin 0 -> 5449 bytes app/vendor/gemoji/images/1f45d.png | Bin 0 -> 4691 bytes app/vendor/gemoji/images/1f45e.png | Bin 0 -> 4749 bytes app/vendor/gemoji/images/1f45f.png | Bin 0 -> 4799 bytes app/vendor/gemoji/images/1f460.png | Bin 0 -> 4557 bytes app/vendor/gemoji/images/1f461.png | Bin 0 -> 4061 bytes app/vendor/gemoji/images/1f462.png | Bin 0 -> 3327 bytes app/vendor/gemoji/images/1f463.png | Bin 0 -> 1604 bytes app/vendor/gemoji/images/1f464.png | Bin 0 -> 2007 bytes app/vendor/gemoji/images/1f465.png | Bin 0 -> 3021 bytes app/vendor/gemoji/images/1f466.png | Bin 0 -> 5946 bytes app/vendor/gemoji/images/1f467.png | Bin 0 -> 6314 bytes app/vendor/gemoji/images/1f468.png | Bin 0 -> 6023 bytes app/vendor/gemoji/images/1f469.png | Bin 0 -> 6895 bytes app/vendor/gemoji/images/1f46a.png | Bin 0 -> 7211 bytes app/vendor/gemoji/images/1f46b.png | Bin 0 -> 7615 bytes app/vendor/gemoji/images/1f46c.png | Bin 0 -> 6994 bytes app/vendor/gemoji/images/1f46d.png | Bin 0 -> 7633 bytes app/vendor/gemoji/images/1f46e.png | Bin 0 -> 7141 bytes app/vendor/gemoji/images/1f46f.png | Bin 0 -> 7918 bytes app/vendor/gemoji/images/1f470.png | Bin 0 -> 8515 bytes app/vendor/gemoji/images/1f471.png | Bin 0 -> 6622 bytes app/vendor/gemoji/images/1f472.png | Bin 0 -> 5324 bytes app/vendor/gemoji/images/1f473.png | Bin 0 -> 6528 bytes app/vendor/gemoji/images/1f474.png | Bin 0 -> 6733 bytes app/vendor/gemoji/images/1f475.png | Bin 0 -> 5977 bytes app/vendor/gemoji/images/1f476.png | Bin 0 -> 5921 bytes app/vendor/gemoji/images/1f477.png | Bin 0 -> 6193 bytes app/vendor/gemoji/images/1f478.png | Bin 0 -> 7920 bytes app/vendor/gemoji/images/1f479.png | Bin 0 -> 7147 bytes app/vendor/gemoji/images/1f47a.png | Bin 0 -> 5159 bytes app/vendor/gemoji/images/1f47b.png | Bin 0 -> 4513 bytes app/vendor/gemoji/images/1f47c.png | Bin 0 -> 6672 bytes app/vendor/gemoji/images/1f47d.png | Bin 0 -> 5478 bytes app/vendor/gemoji/images/1f47e.png | Bin 0 -> 4353 bytes app/vendor/gemoji/images/1f47f.png | Bin 0 -> 6652 bytes app/vendor/gemoji/images/1f480.png | Bin 0 -> 2428 bytes app/vendor/gemoji/images/1f481.png | Bin 0 -> 6605 bytes app/vendor/gemoji/images/1f482.png | Bin 0 -> 3587 bytes app/vendor/gemoji/images/1f483.png | Bin 0 -> 3737 bytes app/vendor/gemoji/images/1f484.png | Bin 0 -> 3384 bytes app/vendor/gemoji/images/1f485.png | Bin 0 -> 5814 bytes app/vendor/gemoji/images/1f486.png | Bin 0 -> 6036 bytes app/vendor/gemoji/images/1f487.png | Bin 0 -> 7100 bytes app/vendor/gemoji/images/1f488.png | Bin 0 -> 4252 bytes app/vendor/gemoji/images/1f489.png | Bin 0 -> 3078 bytes app/vendor/gemoji/images/1f48a.png | Bin 0 -> 5022 bytes app/vendor/gemoji/images/1f48b.png | Bin 0 -> 6295 bytes app/vendor/gemoji/images/1f48c.png | Bin 0 -> 2467 bytes app/vendor/gemoji/images/1f48d.png | Bin 0 -> 5232 bytes app/vendor/gemoji/images/1f48e.png | Bin 0 -> 4855 bytes app/vendor/gemoji/images/1f48f.png | Bin 0 -> 7219 bytes app/vendor/gemoji/images/1f490.png | Bin 0 -> 6915 bytes app/vendor/gemoji/images/1f491.png | Bin 0 -> 7370 bytes app/vendor/gemoji/images/1f492.png | Bin 0 -> 5847 bytes app/vendor/gemoji/images/1f493.png | Bin 0 -> 4052 bytes app/vendor/gemoji/images/1f494.png | Bin 0 -> 4118 bytes app/vendor/gemoji/images/1f495.png | Bin 0 -> 3565 bytes app/vendor/gemoji/images/1f496.png | Bin 0 -> 8002 bytes app/vendor/gemoji/images/1f497.png | Bin 0 -> 6269 bytes app/vendor/gemoji/images/1f498.png | Bin 0 -> 5413 bytes app/vendor/gemoji/images/1f499.png | Bin 0 -> 4094 bytes app/vendor/gemoji/images/1f49a.png | Bin 0 -> 4432 bytes app/vendor/gemoji/images/1f49b.png | Bin 0 -> 4414 bytes app/vendor/gemoji/images/1f49c.png | Bin 0 -> 4295 bytes app/vendor/gemoji/images/1f49d.png | Bin 0 -> 6013 bytes app/vendor/gemoji/images/1f49e.png | Bin 0 -> 5472 bytes app/vendor/gemoji/images/1f49f.png | Bin 0 -> 3534 bytes app/vendor/gemoji/images/1f4a0.png | Bin 0 -> 5698 bytes app/vendor/gemoji/images/1f4a1.png | Bin 0 -> 4490 bytes app/vendor/gemoji/images/1f4a2.png | Bin 0 -> 3079 bytes app/vendor/gemoji/images/1f4a3.png | Bin 0 -> 5208 bytes app/vendor/gemoji/images/1f4a4.png | Bin 0 -> 2027 bytes app/vendor/gemoji/images/1f4a5.png | Bin 0 -> 3781 bytes app/vendor/gemoji/images/1f4a6.png | Bin 0 -> 4782 bytes app/vendor/gemoji/images/1f4a7.png | Bin 0 -> 3278 bytes app/vendor/gemoji/images/1f4a8.png | Bin 0 -> 5448 bytes app/vendor/gemoji/images/1f4a9.png | Bin 0 -> 4754 bytes app/vendor/gemoji/images/1f4aa.png | Bin 0 -> 4672 bytes app/vendor/gemoji/images/1f4ab.png | Bin 0 -> 3044 bytes app/vendor/gemoji/images/1f4ac.png | Bin 0 -> 2130 bytes app/vendor/gemoji/images/1f4ad.png | Bin 0 -> 2582 bytes app/vendor/gemoji/images/1f4ae.png | Bin 0 -> 4391 bytes app/vendor/gemoji/images/1f4af.png | Bin 0 -> 3302 bytes app/vendor/gemoji/images/1f4b0.png | Bin 0 -> 5500 bytes app/vendor/gemoji/images/1f4b1.png | Bin 0 -> 1981 bytes app/vendor/gemoji/images/1f4b2.png | Bin 0 -> 1416 bytes app/vendor/gemoji/images/1f4b3.png | Bin 0 -> 2648 bytes app/vendor/gemoji/images/1f4b4.png | Bin 0 -> 4989 bytes app/vendor/gemoji/images/1f4b5.png | Bin 0 -> 4622 bytes app/vendor/gemoji/images/1f4b6.png | Bin 0 -> 3942 bytes app/vendor/gemoji/images/1f4b7.png | Bin 0 -> 4235 bytes app/vendor/gemoji/images/1f4b8.png | Bin 0 -> 7586 bytes app/vendor/gemoji/images/1f4b9.png | Bin 0 -> 4331 bytes app/vendor/gemoji/images/1f4ba.png | Bin 0 -> 6059 bytes app/vendor/gemoji/images/1f4bb.png | Bin 0 -> 1705 bytes app/vendor/gemoji/images/1f4bc.png | Bin 0 -> 2698 bytes app/vendor/gemoji/images/1f4bd.png | Bin 0 -> 5594 bytes app/vendor/gemoji/images/1f4be.png | Bin 0 -> 3215 bytes app/vendor/gemoji/images/1f4bf.png | Bin 0 -> 6718 bytes app/vendor/gemoji/images/1f4c0.png | Bin 0 -> 6993 bytes app/vendor/gemoji/images/1f4c1.png | Bin 0 -> 4013 bytes app/vendor/gemoji/images/1f4c2.png | Bin 0 -> 4292 bytes app/vendor/gemoji/images/1f4c3.png | Bin 0 -> 3729 bytes app/vendor/gemoji/images/1f4c4.png | Bin 0 -> 2183 bytes app/vendor/gemoji/images/1f4c5.png | Bin 0 -> 2977 bytes app/vendor/gemoji/images/1f4c6.png | Bin 0 -> 2920 bytes app/vendor/gemoji/images/1f4c7.png | Bin 0 -> 3749 bytes app/vendor/gemoji/images/1f4c8.png | Bin 0 -> 2939 bytes app/vendor/gemoji/images/1f4c9.png | Bin 0 -> 2910 bytes app/vendor/gemoji/images/1f4ca.png | Bin 0 -> 2460 bytes app/vendor/gemoji/images/1f4cb.png | Bin 0 -> 4663 bytes app/vendor/gemoji/images/1f4cc.png | Bin 0 -> 3793 bytes app/vendor/gemoji/images/1f4cd.png | Bin 0 -> 1936 bytes app/vendor/gemoji/images/1f4ce.png | Bin 0 -> 2558 bytes app/vendor/gemoji/images/1f4cf.png | Bin 0 -> 3832 bytes app/vendor/gemoji/images/1f4d0.png | Bin 0 -> 2706 bytes app/vendor/gemoji/images/1f4d1.png | Bin 0 -> 3162 bytes app/vendor/gemoji/images/1f4d2.png | Bin 0 -> 5921 bytes app/vendor/gemoji/images/1f4d3.png | Bin 0 -> 6036 bytes app/vendor/gemoji/images/1f4d4.png | Bin 0 -> 5329 bytes app/vendor/gemoji/images/1f4d5.png | Bin 0 -> 4847 bytes app/vendor/gemoji/images/1f4d6.png | Bin 0 -> 6050 bytes app/vendor/gemoji/images/1f4d7.png | Bin 0 -> 5090 bytes app/vendor/gemoji/images/1f4d8.png | Bin 0 -> 5092 bytes app/vendor/gemoji/images/1f4d9.png | Bin 0 -> 5085 bytes app/vendor/gemoji/images/1f4da.png | Bin 0 -> 6539 bytes app/vendor/gemoji/images/1f4db.png | Bin 0 -> 3985 bytes app/vendor/gemoji/images/1f4dc.png | Bin 0 -> 6749 bytes app/vendor/gemoji/images/1f4dd.png | Bin 0 -> 4945 bytes app/vendor/gemoji/images/1f4de.png | Bin 0 -> 2001 bytes app/vendor/gemoji/images/1f4df.png | Bin 0 -> 4022 bytes app/vendor/gemoji/images/1f4e0.png | Bin 0 -> 4650 bytes app/vendor/gemoji/images/1f4e1.png | Bin 0 -> 4867 bytes app/vendor/gemoji/images/1f4e2.png | Bin 0 -> 6001 bytes app/vendor/gemoji/images/1f4e3.png | Bin 0 -> 4821 bytes app/vendor/gemoji/images/1f4e4.png | Bin 0 -> 3683 bytes app/vendor/gemoji/images/1f4e5.png | Bin 0 -> 3700 bytes app/vendor/gemoji/images/1f4e6.png | Bin 0 -> 8449 bytes app/vendor/gemoji/images/1f4e7.png | Bin 0 -> 2128 bytes app/vendor/gemoji/images/1f4e8.png | Bin 0 -> 2206 bytes app/vendor/gemoji/images/1f4e9.png | Bin 0 -> 2697 bytes app/vendor/gemoji/images/1f4ea.png | Bin 0 -> 4360 bytes app/vendor/gemoji/images/1f4eb.png | Bin 0 -> 4196 bytes app/vendor/gemoji/images/1f4ec.png | Bin 0 -> 4581 bytes app/vendor/gemoji/images/1f4ed.png | Bin 0 -> 3101 bytes app/vendor/gemoji/images/1f4ee.png | Bin 0 -> 3388 bytes app/vendor/gemoji/images/1f4ef.png | Bin 0 -> 4819 bytes app/vendor/gemoji/images/1f4f0.png | Bin 0 -> 5198 bytes app/vendor/gemoji/images/1f4f1.png | Bin 0 -> 3499 bytes app/vendor/gemoji/images/1f4f2.png | Bin 0 -> 4037 bytes app/vendor/gemoji/images/1f4f3.png | Bin 0 -> 3906 bytes app/vendor/gemoji/images/1f4f4.png | Bin 0 -> 3521 bytes app/vendor/gemoji/images/1f4f5.png | Bin 0 -> 5083 bytes app/vendor/gemoji/images/1f4f6.png | Bin 0 -> 3231 bytes app/vendor/gemoji/images/1f4f7.png | Bin 0 -> 4661 bytes app/vendor/gemoji/images/1f4f9.png | Bin 0 -> 5090 bytes app/vendor/gemoji/images/1f4fa.png | Bin 0 -> 5242 bytes app/vendor/gemoji/images/1f4fb.png | Bin 0 -> 6150 bytes app/vendor/gemoji/images/1f4fc.png | Bin 0 -> 3145 bytes app/vendor/gemoji/images/1f500.png | Bin 0 -> 4313 bytes app/vendor/gemoji/images/1f501.png | Bin 0 -> 4009 bytes app/vendor/gemoji/images/1f502.png | Bin 0 -> 4287 bytes app/vendor/gemoji/images/1f503.png | Bin 0 -> 1399 bytes app/vendor/gemoji/images/1f504.png | Bin 0 -> 4823 bytes app/vendor/gemoji/images/1f505.png | Bin 0 -> 2498 bytes app/vendor/gemoji/images/1f506.png | Bin 0 -> 4060 bytes app/vendor/gemoji/images/1f507.png | Bin 0 -> 6635 bytes app/vendor/gemoji/images/1f508.png | Bin 0 -> 5309 bytes app/vendor/gemoji/images/1f509.png | Bin 0 -> 5024 bytes app/vendor/gemoji/images/1f50a.png | Bin 0 -> 7814 bytes app/vendor/gemoji/images/1f50b.png | Bin 0 -> 3812 bytes app/vendor/gemoji/images/1f50c.png | Bin 0 -> 2819 bytes app/vendor/gemoji/images/1f50d.png | Bin 0 -> 3040 bytes app/vendor/gemoji/images/1f50e.png | Bin 0 -> 3629 bytes app/vendor/gemoji/images/1f50f.png | Bin 0 -> 4967 bytes app/vendor/gemoji/images/1f510.png | Bin 0 -> 5701 bytes app/vendor/gemoji/images/1f511.png | Bin 0 -> 3452 bytes app/vendor/gemoji/images/1f512.png | Bin 0 -> 3676 bytes app/vendor/gemoji/images/1f513.png | Bin 0 -> 3551 bytes app/vendor/gemoji/images/1f514.png | Bin 0 -> 4859 bytes app/vendor/gemoji/images/1f515.png | Bin 0 -> 5944 bytes app/vendor/gemoji/images/1f516.png | Bin 0 -> 4696 bytes app/vendor/gemoji/images/1f517.png | Bin 0 -> 2652 bytes app/vendor/gemoji/images/1f518.png | Bin 0 -> 2198 bytes app/vendor/gemoji/images/1f519.png | Bin 0 -> 5434 bytes app/vendor/gemoji/images/1f51a.png | Bin 0 -> 1475 bytes app/vendor/gemoji/images/1f51b.png | Bin 0 -> 1806 bytes app/vendor/gemoji/images/1f51c.png | Bin 0 -> 1911 bytes app/vendor/gemoji/images/1f51d.png | Bin 0 -> 3785 bytes app/vendor/gemoji/images/1f51e.png | Bin 0 -> 5722 bytes app/vendor/gemoji/images/1f51f.png | Bin 0 -> 4095 bytes app/vendor/gemoji/images/1f520.png | Bin 0 -> 5136 bytes app/vendor/gemoji/images/1f521.png | Bin 0 -> 4471 bytes app/vendor/gemoji/images/1f522.png | Bin 0 -> 4751 bytes app/vendor/gemoji/images/1f523.png | Bin 0 -> 5434 bytes app/vendor/gemoji/images/1f524.png | Bin 0 -> 4247 bytes app/vendor/gemoji/images/1f525.png | Bin 0 -> 3886 bytes app/vendor/gemoji/images/1f526.png | Bin 0 -> 5024 bytes app/vendor/gemoji/images/1f527.png | Bin 0 -> 2775 bytes app/vendor/gemoji/images/1f528.png | Bin 0 -> 3812 bytes app/vendor/gemoji/images/1f529.png | Bin 0 -> 2169 bytes app/vendor/gemoji/images/1f52a.png | Bin 0 -> 2506 bytes app/vendor/gemoji/images/1f52b.png | Bin 0 -> 3161 bytes app/vendor/gemoji/images/1f52c.png | Bin 0 -> 4141 bytes app/vendor/gemoji/images/1f52d.png | Bin 0 -> 3322 bytes app/vendor/gemoji/images/1f52e.png | Bin 0 -> 6236 bytes app/vendor/gemoji/images/1f52f.png | Bin 0 -> 4859 bytes app/vendor/gemoji/images/1f530.png | Bin 0 -> 2761 bytes app/vendor/gemoji/images/1f531.png | Bin 0 -> 4833 bytes app/vendor/gemoji/images/1f532.png | Bin 0 -> 3599 bytes app/vendor/gemoji/images/1f533.png | Bin 0 -> 4113 bytes app/vendor/gemoji/images/1f534.png | Bin 0 -> 3946 bytes app/vendor/gemoji/images/1f535.png | Bin 0 -> 4637 bytes app/vendor/gemoji/images/1f536.png | Bin 0 -> 3899 bytes app/vendor/gemoji/images/1f537.png | Bin 0 -> 3790 bytes app/vendor/gemoji/images/1f538.png | Bin 0 -> 1944 bytes app/vendor/gemoji/images/1f539.png | Bin 0 -> 1898 bytes app/vendor/gemoji/images/1f53a.png | Bin 0 -> 2054 bytes app/vendor/gemoji/images/1f53b.png | Bin 0 -> 2157 bytes app/vendor/gemoji/images/1f53c.png | Bin 0 -> 3198 bytes app/vendor/gemoji/images/1f53d.png | Bin 0 -> 2934 bytes app/vendor/gemoji/images/1f550.png | Bin 0 -> 2641 bytes app/vendor/gemoji/images/1f551.png | Bin 0 -> 2651 bytes app/vendor/gemoji/images/1f552.png | Bin 0 -> 2544 bytes app/vendor/gemoji/images/1f553.png | Bin 0 -> 2684 bytes app/vendor/gemoji/images/1f554.png | Bin 0 -> 2664 bytes app/vendor/gemoji/images/1f555.png | Bin 0 -> 2630 bytes app/vendor/gemoji/images/1f556.png | Bin 0 -> 2667 bytes app/vendor/gemoji/images/1f557.png | Bin 0 -> 2661 bytes app/vendor/gemoji/images/1f558.png | Bin 0 -> 2543 bytes app/vendor/gemoji/images/1f559.png | Bin 0 -> 2639 bytes app/vendor/gemoji/images/1f55a.png | Bin 0 -> 2633 bytes app/vendor/gemoji/images/1f55b.png | Bin 0 -> 2556 bytes app/vendor/gemoji/images/1f55c.png | Bin 0 -> 2842 bytes app/vendor/gemoji/images/1f55d.png | Bin 0 -> 2853 bytes app/vendor/gemoji/images/1f55e.png | Bin 0 -> 2739 bytes app/vendor/gemoji/images/1f55f.png | Bin 0 -> 2847 bytes app/vendor/gemoji/images/1f560.png | Bin 0 -> 2832 bytes app/vendor/gemoji/images/1f561.png | Bin 0 -> 2730 bytes app/vendor/gemoji/images/1f562.png | Bin 0 -> 2820 bytes app/vendor/gemoji/images/1f563.png | Bin 0 -> 2847 bytes app/vendor/gemoji/images/1f564.png | Bin 0 -> 2746 bytes app/vendor/gemoji/images/1f565.png | Bin 0 -> 2864 bytes app/vendor/gemoji/images/1f566.png | Bin 0 -> 2854 bytes app/vendor/gemoji/images/1f567.png | Bin 0 -> 2797 bytes app/vendor/gemoji/images/1f5fb.png | Bin 0 -> 5004 bytes app/vendor/gemoji/images/1f5fc.png | Bin 0 -> 4802 bytes app/vendor/gemoji/images/1f5fd.png | Bin 0 -> 6075 bytes app/vendor/gemoji/images/1f5fe.png | Bin 0 -> 4085 bytes app/vendor/gemoji/images/1f5ff.png | Bin 0 -> 2166 bytes app/vendor/gemoji/images/1f600.png | Bin 0 -> 8098 bytes app/vendor/gemoji/images/1f601.png | Bin 0 -> 5721 bytes app/vendor/gemoji/images/1f602.png | Bin 0 -> 6339 bytes app/vendor/gemoji/images/1f603.png | Bin 0 -> 5794 bytes app/vendor/gemoji/images/1f604.png | Bin 0 -> 5890 bytes app/vendor/gemoji/images/1f605.png | Bin 0 -> 6519 bytes app/vendor/gemoji/images/1f606.png | Bin 0 -> 6347 bytes app/vendor/gemoji/images/1f607.png | Bin 0 -> 7000 bytes app/vendor/gemoji/images/1f608.png | Bin 0 -> 7189 bytes app/vendor/gemoji/images/1f609.png | Bin 0 -> 5253 bytes app/vendor/gemoji/images/1f60a.png | Bin 0 -> 5284 bytes app/vendor/gemoji/images/1f60b.png | Bin 0 -> 5886 bytes app/vendor/gemoji/images/1f60c.png | Bin 0 -> 5440 bytes app/vendor/gemoji/images/1f60d.png | Bin 0 -> 5758 bytes app/vendor/gemoji/images/1f60e.png | Bin 0 -> 5749 bytes app/vendor/gemoji/images/1f60f.png | Bin 0 -> 5307 bytes app/vendor/gemoji/images/1f610.png | Bin 0 -> 4843 bytes app/vendor/gemoji/images/1f611.png | Bin 0 -> 6669 bytes app/vendor/gemoji/images/1f612.png | Bin 0 -> 5315 bytes app/vendor/gemoji/images/1f613.png | Bin 0 -> 5576 bytes app/vendor/gemoji/images/1f614.png | Bin 0 -> 5119 bytes app/vendor/gemoji/images/1f615.png | Bin 0 -> 7306 bytes app/vendor/gemoji/images/1f616.png | Bin 0 -> 5881 bytes app/vendor/gemoji/images/1f617.png | Bin 0 -> 7431 bytes app/vendor/gemoji/images/1f618.png | Bin 0 -> 5767 bytes app/vendor/gemoji/images/1f619.png | Bin 0 -> 7619 bytes app/vendor/gemoji/images/1f61a.png | Bin 0 -> 5563 bytes app/vendor/gemoji/images/1f61b.png | Bin 0 -> 7825 bytes app/vendor/gemoji/images/1f61c.png | Bin 0 -> 6007 bytes app/vendor/gemoji/images/1f61d.png | Bin 0 -> 5785 bytes app/vendor/gemoji/images/1f61e.png | Bin 0 -> 4764 bytes app/vendor/gemoji/images/1f61f.png | Bin 0 -> 8022 bytes app/vendor/gemoji/images/1f620.png | Bin 0 -> 5088 bytes app/vendor/gemoji/images/1f621.png | Bin 0 -> 5410 bytes app/vendor/gemoji/images/1f622.png | Bin 0 -> 5699 bytes app/vendor/gemoji/images/1f623.png | Bin 0 -> 5540 bytes app/vendor/gemoji/images/1f624.png | Bin 0 -> 6164 bytes app/vendor/gemoji/images/1f625.png | Bin 0 -> 5648 bytes app/vendor/gemoji/images/1f626.png | Bin 0 -> 7361 bytes app/vendor/gemoji/images/1f627.png | Bin 0 -> 7902 bytes app/vendor/gemoji/images/1f628.png | Bin 0 -> 5600 bytes app/vendor/gemoji/images/1f629.png | Bin 0 -> 6279 bytes app/vendor/gemoji/images/1f62a.png | Bin 0 -> 5837 bytes app/vendor/gemoji/images/1f62b.png | Bin 0 -> 6178 bytes app/vendor/gemoji/images/1f62c.png | Bin 0 -> 7928 bytes app/vendor/gemoji/images/1f62d.png | Bin 0 -> 5730 bytes app/vendor/gemoji/images/1f62e.png | Bin 0 -> 7121 bytes app/vendor/gemoji/images/1f62f.png | Bin 0 -> 7760 bytes app/vendor/gemoji/images/1f630.png | Bin 0 -> 5972 bytes app/vendor/gemoji/images/1f631.png | Bin 0 -> 6503 bytes app/vendor/gemoji/images/1f632.png | Bin 0 -> 6043 bytes app/vendor/gemoji/images/1f633.png | Bin 0 -> 5866 bytes app/vendor/gemoji/images/1f634.png | Bin 0 -> 8084 bytes app/vendor/gemoji/images/1f635.png | Bin 0 -> 6278 bytes app/vendor/gemoji/images/1f636.png | Bin 0 -> 4732 bytes app/vendor/gemoji/images/1f637.png | Bin 0 -> 5235 bytes app/vendor/gemoji/images/1f638.png | Bin 0 -> 6117 bytes app/vendor/gemoji/images/1f639.png | Bin 0 -> 7190 bytes app/vendor/gemoji/images/1f63a.png | Bin 0 -> 6083 bytes app/vendor/gemoji/images/1f63b.png | Bin 0 -> 6176 bytes app/vendor/gemoji/images/1f63c.png | Bin 0 -> 6062 bytes app/vendor/gemoji/images/1f63d.png | Bin 0 -> 6801 bytes app/vendor/gemoji/images/1f63e.png | Bin 0 -> 4918 bytes app/vendor/gemoji/images/1f63f.png | Bin 0 -> 6682 bytes app/vendor/gemoji/images/1f640.png | Bin 0 -> 6844 bytes app/vendor/gemoji/images/1f645.png | Bin 0 -> 7034 bytes app/vendor/gemoji/images/1f646.png | Bin 0 -> 7527 bytes app/vendor/gemoji/images/1f647.png | Bin 0 -> 5143 bytes app/vendor/gemoji/images/1f648.png | Bin 0 -> 6828 bytes app/vendor/gemoji/images/1f649.png | Bin 0 -> 6550 bytes app/vendor/gemoji/images/1f64a.png | Bin 0 -> 5977 bytes app/vendor/gemoji/images/1f64b.png | Bin 0 -> 6177 bytes app/vendor/gemoji/images/1f64c.png | Bin 0 -> 5375 bytes app/vendor/gemoji/images/1f64d.png | Bin 0 -> 4826 bytes app/vendor/gemoji/images/1f64e.png | Bin 0 -> 5428 bytes app/vendor/gemoji/images/1f64f.png | Bin 0 -> 6203 bytes app/vendor/gemoji/images/1f680.png | Bin 0 -> 5388 bytes app/vendor/gemoji/images/1f681.png | Bin 0 -> 4100 bytes app/vendor/gemoji/images/1f682.png | Bin 0 -> 5159 bytes app/vendor/gemoji/images/1f683.png | Bin 0 -> 3648 bytes app/vendor/gemoji/images/1f684.png | Bin 0 -> 3842 bytes app/vendor/gemoji/images/1f685.png | Bin 0 -> 4992 bytes app/vendor/gemoji/images/1f686.png | Bin 0 -> 4817 bytes app/vendor/gemoji/images/1f687.png | Bin 0 -> 3423 bytes app/vendor/gemoji/images/1f688.png | Bin 0 -> 3792 bytes app/vendor/gemoji/images/1f689.png | Bin 0 -> 4836 bytes app/vendor/gemoji/images/1f68a.png | Bin 0 -> 4869 bytes app/vendor/gemoji/images/1f68b.png | Bin 0 -> 2904 bytes app/vendor/gemoji/images/1f68c.png | Bin 0 -> 4065 bytes app/vendor/gemoji/images/1f68d.png | Bin 0 -> 5305 bytes app/vendor/gemoji/images/1f68e.png | Bin 0 -> 4431 bytes app/vendor/gemoji/images/1f68f.png | Bin 0 -> 1715 bytes app/vendor/gemoji/images/1f690.png | Bin 0 -> 3113 bytes app/vendor/gemoji/images/1f691.png | Bin 0 -> 3708 bytes app/vendor/gemoji/images/1f692.png | Bin 0 -> 4862 bytes app/vendor/gemoji/images/1f693.png | Bin 0 -> 3349 bytes app/vendor/gemoji/images/1f694.png | Bin 0 -> 5683 bytes app/vendor/gemoji/images/1f695.png | Bin 0 -> 3744 bytes app/vendor/gemoji/images/1f696.png | Bin 0 -> 6287 bytes app/vendor/gemoji/images/1f697.png | Bin 0 -> 4278 bytes app/vendor/gemoji/images/1f698.png | Bin 0 -> 7469 bytes app/vendor/gemoji/images/1f699.png | Bin 0 -> 4081 bytes app/vendor/gemoji/images/1f69a.png | Bin 0 -> 3721 bytes app/vendor/gemoji/images/1f69b.png | Bin 0 -> 2938 bytes app/vendor/gemoji/images/1f69c.png | Bin 0 -> 5671 bytes app/vendor/gemoji/images/1f69d.png | Bin 0 -> 4311 bytes app/vendor/gemoji/images/1f69e.png | Bin 0 -> 7448 bytes app/vendor/gemoji/images/1f69f.png | Bin 0 -> 3937 bytes app/vendor/gemoji/images/1f6a0.png | Bin 0 -> 4405 bytes app/vendor/gemoji/images/1f6a1.png | Bin 0 -> 3489 bytes app/vendor/gemoji/images/1f6a2.png | Bin 0 -> 4233 bytes app/vendor/gemoji/images/1f6a3.png | Bin 0 -> 5433 bytes app/vendor/gemoji/images/1f6a4.png | Bin 0 -> 3512 bytes app/vendor/gemoji/images/1f6a5.png | Bin 0 -> 3603 bytes app/vendor/gemoji/images/1f6a6.png | Bin 0 -> 3422 bytes app/vendor/gemoji/images/1f6a7.png | Bin 0 -> 3700 bytes app/vendor/gemoji/images/1f6a8.png | Bin 0 -> 6620 bytes app/vendor/gemoji/images/1f6a9.png | Bin 0 -> 1399 bytes app/vendor/gemoji/images/1f6aa.png | Bin 0 -> 3310 bytes app/vendor/gemoji/images/1f6ab.png | Bin 0 -> 3288 bytes app/vendor/gemoji/images/1f6ac.png | Bin 0 -> 2875 bytes app/vendor/gemoji/images/1f6ad.png | Bin 0 -> 4228 bytes app/vendor/gemoji/images/1f6ae.png | Bin 0 -> 4091 bytes app/vendor/gemoji/images/1f6af.png | Bin 0 -> 5277 bytes app/vendor/gemoji/images/1f6b0.png | Bin 0 -> 3934 bytes app/vendor/gemoji/images/1f6b1.png | Bin 0 -> 5202 bytes app/vendor/gemoji/images/1f6b2.png | Bin 0 -> 4722 bytes app/vendor/gemoji/images/1f6b3.png | Bin 0 -> 5661 bytes app/vendor/gemoji/images/1f6b4.png | Bin 0 -> 6484 bytes app/vendor/gemoji/images/1f6b5.png | Bin 0 -> 9511 bytes app/vendor/gemoji/images/1f6b6.png | Bin 0 -> 2519 bytes app/vendor/gemoji/images/1f6b7.png | Bin 0 -> 5487 bytes app/vendor/gemoji/images/1f6b8.png | Bin 0 -> 3460 bytes app/vendor/gemoji/images/1f6b9.png | Bin 0 -> 3368 bytes app/vendor/gemoji/images/1f6ba.png | Bin 0 -> 3908 bytes app/vendor/gemoji/images/1f6bb.png | Bin 0 -> 4162 bytes app/vendor/gemoji/images/1f6bc.png | Bin 0 -> 2967 bytes app/vendor/gemoji/images/1f6bd.png | Bin 0 -> 1733 bytes app/vendor/gemoji/images/1f6be.png | Bin 0 -> 4088 bytes app/vendor/gemoji/images/1f6bf.png | Bin 0 -> 7583 bytes app/vendor/gemoji/images/1f6c0.png | Bin 0 -> 3210 bytes app/vendor/gemoji/images/1f6c1.png | Bin 0 -> 2784 bytes app/vendor/gemoji/images/1f6c2.png | Bin 0 -> 4018 bytes app/vendor/gemoji/images/1f6c3.png | Bin 0 -> 3899 bytes app/vendor/gemoji/images/1f6c4.png | Bin 0 -> 3502 bytes app/vendor/gemoji/images/1f6c5.png | Bin 0 -> 4025 bytes app/vendor/gemoji/images/203c-fe0f.png | Bin 0 -> 1387 bytes app/vendor/gemoji/images/203c.png | Bin 0 -> 1387 bytes app/vendor/gemoji/images/2049-fe0f.png | Bin 0 -> 2875 bytes app/vendor/gemoji/images/2049.png | Bin 0 -> 2875 bytes app/vendor/gemoji/images/2122.png | Bin 0 -> 870 bytes app/vendor/gemoji/images/2139-fe0f.png | Bin 0 -> 3670 bytes app/vendor/gemoji/images/2139.png | Bin 0 -> 3670 bytes app/vendor/gemoji/images/2194-fe0f.png | Bin 0 -> 3413 bytes app/vendor/gemoji/images/2194.png | Bin 0 -> 3413 bytes app/vendor/gemoji/images/2195-fe0f.png | Bin 0 -> 3544 bytes app/vendor/gemoji/images/2195.png | Bin 0 -> 3544 bytes app/vendor/gemoji/images/2196-fe0f.png | Bin 0 -> 3240 bytes app/vendor/gemoji/images/2196.png | Bin 0 -> 3240 bytes app/vendor/gemoji/images/2197-fe0f.png | Bin 0 -> 3249 bytes app/vendor/gemoji/images/2197.png | Bin 0 -> 3249 bytes app/vendor/gemoji/images/2198-fe0f.png | Bin 0 -> 3351 bytes app/vendor/gemoji/images/2198.png | Bin 0 -> 3351 bytes app/vendor/gemoji/images/2199-fe0f.png | Bin 0 -> 3360 bytes app/vendor/gemoji/images/2199.png | Bin 0 -> 3360 bytes app/vendor/gemoji/images/21a9-fe0f.png | Bin 0 -> 3775 bytes app/vendor/gemoji/images/21a9.png | Bin 0 -> 3775 bytes app/vendor/gemoji/images/21aa-fe0f.png | Bin 0 -> 3712 bytes app/vendor/gemoji/images/21aa.png | Bin 0 -> 3712 bytes app/vendor/gemoji/images/231a-fe0f.png | Bin 0 -> 5189 bytes app/vendor/gemoji/images/231a.png | Bin 0 -> 5189 bytes app/vendor/gemoji/images/231b-fe0f.png | Bin 0 -> 4492 bytes app/vendor/gemoji/images/231b.png | Bin 0 -> 4492 bytes app/vendor/gemoji/images/23e9.png | Bin 0 -> 3124 bytes app/vendor/gemoji/images/23ea.png | Bin 0 -> 3068 bytes app/vendor/gemoji/images/23eb.png | Bin 0 -> 3613 bytes app/vendor/gemoji/images/23ec.png | Bin 0 -> 3179 bytes app/vendor/gemoji/images/23f0.png | Bin 0 -> 7062 bytes app/vendor/gemoji/images/23f3.png | Bin 0 -> 6765 bytes app/vendor/gemoji/images/24c2-fe0f.png | Bin 0 -> 4737 bytes app/vendor/gemoji/images/24c2.png | Bin 0 -> 4737 bytes app/vendor/gemoji/images/25aa-fe0f.png | Bin 0 -> 3061 bytes app/vendor/gemoji/images/25aa.png | Bin 0 -> 3061 bytes app/vendor/gemoji/images/25ab-fe0f.png | Bin 0 -> 3068 bytes app/vendor/gemoji/images/25ab.png | Bin 0 -> 3068 bytes app/vendor/gemoji/images/25b6-fe0f.png | Bin 0 -> 3201 bytes app/vendor/gemoji/images/25b6.png | Bin 0 -> 3201 bytes app/vendor/gemoji/images/25c0-fe0f.png | Bin 0 -> 3202 bytes app/vendor/gemoji/images/25c0.png | Bin 0 -> 3202 bytes app/vendor/gemoji/images/25fb-fe0f.png | Bin 0 -> 4192 bytes app/vendor/gemoji/images/25fb.png | Bin 0 -> 4192 bytes app/vendor/gemoji/images/25fc-fe0f.png | Bin 0 -> 4035 bytes app/vendor/gemoji/images/25fc.png | Bin 0 -> 4035 bytes app/vendor/gemoji/images/25fd-fe0f.png | Bin 0 -> 3598 bytes app/vendor/gemoji/images/25fd.png | Bin 0 -> 3598 bytes app/vendor/gemoji/images/25fe-fe0f.png | Bin 0 -> 3495 bytes app/vendor/gemoji/images/25fe.png | Bin 0 -> 3495 bytes app/vendor/gemoji/images/2600-fe0f.png | Bin 0 -> 3802 bytes app/vendor/gemoji/images/2600.png | Bin 0 -> 3802 bytes app/vendor/gemoji/images/2601-fe0f.png | Bin 0 -> 3860 bytes app/vendor/gemoji/images/2601.png | Bin 0 -> 3860 bytes app/vendor/gemoji/images/260e-fe0f.png | Bin 0 -> 5495 bytes app/vendor/gemoji/images/260e.png | Bin 0 -> 5495 bytes app/vendor/gemoji/images/2611-fe0f.png | Bin 0 -> 1829 bytes app/vendor/gemoji/images/2611.png | Bin 0 -> 1829 bytes app/vendor/gemoji/images/2614-fe0f.png | Bin 0 -> 4745 bytes app/vendor/gemoji/images/2614.png | Bin 0 -> 4745 bytes app/vendor/gemoji/images/2615-fe0f.png | Bin 0 -> 4306 bytes app/vendor/gemoji/images/2615.png | Bin 0 -> 4306 bytes app/vendor/gemoji/images/261d-fe0f.png | Bin 0 -> 3431 bytes app/vendor/gemoji/images/261d.png | Bin 0 -> 3431 bytes app/vendor/gemoji/images/263a-fe0f.png | Bin 0 -> 5455 bytes app/vendor/gemoji/images/263a.png | Bin 0 -> 5455 bytes app/vendor/gemoji/images/2648-fe0f.png | Bin 0 -> 4359 bytes app/vendor/gemoji/images/2648.png | Bin 0 -> 4359 bytes app/vendor/gemoji/images/2649-fe0f.png | Bin 0 -> 4733 bytes app/vendor/gemoji/images/2649.png | Bin 0 -> 4733 bytes app/vendor/gemoji/images/264a-fe0f.png | Bin 0 -> 4296 bytes app/vendor/gemoji/images/264a.png | Bin 0 -> 4296 bytes app/vendor/gemoji/images/264b-fe0f.png | Bin 0 -> 5384 bytes app/vendor/gemoji/images/264b.png | Bin 0 -> 5384 bytes app/vendor/gemoji/images/264c-fe0f.png | Bin 0 -> 4913 bytes app/vendor/gemoji/images/264c.png | Bin 0 -> 4913 bytes app/vendor/gemoji/images/264d-fe0f.png | Bin 0 -> 4869 bytes app/vendor/gemoji/images/264d.png | Bin 0 -> 4869 bytes app/vendor/gemoji/images/264e-fe0f.png | Bin 0 -> 4229 bytes app/vendor/gemoji/images/264e.png | Bin 0 -> 4229 bytes app/vendor/gemoji/images/264f-fe0f.png | Bin 0 -> 4566 bytes app/vendor/gemoji/images/264f.png | Bin 0 -> 4566 bytes app/vendor/gemoji/images/2650-fe0f.png | Bin 0 -> 4505 bytes app/vendor/gemoji/images/2650.png | Bin 0 -> 4505 bytes app/vendor/gemoji/images/2651-fe0f.png | Bin 0 -> 4670 bytes app/vendor/gemoji/images/2651.png | Bin 0 -> 4670 bytes app/vendor/gemoji/images/2652-fe0f.png | Bin 0 -> 5096 bytes app/vendor/gemoji/images/2652.png | Bin 0 -> 5096 bytes app/vendor/gemoji/images/2653-fe0f.png | Bin 0 -> 4458 bytes app/vendor/gemoji/images/2653.png | Bin 0 -> 4458 bytes app/vendor/gemoji/images/2660-fe0f.png | Bin 0 -> 1719 bytes app/vendor/gemoji/images/2660.png | Bin 0 -> 1719 bytes app/vendor/gemoji/images/2663-fe0f.png | Bin 0 -> 1685 bytes app/vendor/gemoji/images/2663.png | Bin 0 -> 1685 bytes app/vendor/gemoji/images/2665-fe0f.png | Bin 0 -> 2925 bytes app/vendor/gemoji/images/2665.png | Bin 0 -> 2925 bytes app/vendor/gemoji/images/2666-fe0f.png | Bin 0 -> 2785 bytes app/vendor/gemoji/images/2666.png | Bin 0 -> 2785 bytes app/vendor/gemoji/images/2668-fe0f.png | Bin 0 -> 3538 bytes app/vendor/gemoji/images/2668.png | Bin 0 -> 3538 bytes app/vendor/gemoji/images/267b-fe0f.png | Bin 0 -> 3704 bytes app/vendor/gemoji/images/267b.png | Bin 0 -> 3704 bytes app/vendor/gemoji/images/267f-fe0f.png | Bin 0 -> 4224 bytes app/vendor/gemoji/images/267f.png | Bin 0 -> 4224 bytes app/vendor/gemoji/images/2693-fe0f.png | Bin 0 -> 4479 bytes app/vendor/gemoji/images/2693.png | Bin 0 -> 4479 bytes app/vendor/gemoji/images/26a0-fe0f.png | Bin 0 -> 3177 bytes app/vendor/gemoji/images/26a0.png | Bin 0 -> 3177 bytes app/vendor/gemoji/images/26a1-fe0f.png | Bin 0 -> 2233 bytes app/vendor/gemoji/images/26a1.png | Bin 0 -> 2233 bytes app/vendor/gemoji/images/26aa-fe0f.png | Bin 0 -> 2506 bytes app/vendor/gemoji/images/26aa.png | Bin 0 -> 2506 bytes app/vendor/gemoji/images/26ab-fe0f.png | Bin 0 -> 2369 bytes app/vendor/gemoji/images/26ab.png | Bin 0 -> 2369 bytes app/vendor/gemoji/images/26bd-fe0f.png | Bin 0 -> 4878 bytes app/vendor/gemoji/images/26bd.png | Bin 0 -> 4878 bytes app/vendor/gemoji/images/26be-fe0f.png | Bin 0 -> 6032 bytes app/vendor/gemoji/images/26be.png | Bin 0 -> 6032 bytes app/vendor/gemoji/images/26c4-fe0f.png | Bin 0 -> 4658 bytes app/vendor/gemoji/images/26c4.png | Bin 0 -> 4658 bytes app/vendor/gemoji/images/26c5-fe0f.png | Bin 0 -> 5181 bytes app/vendor/gemoji/images/26c5.png | Bin 0 -> 5181 bytes app/vendor/gemoji/images/26ce.png | Bin 0 -> 4434 bytes app/vendor/gemoji/images/26d4-fe0f.png | Bin 0 -> 3514 bytes app/vendor/gemoji/images/26d4.png | Bin 0 -> 3514 bytes app/vendor/gemoji/images/26ea-fe0f.png | Bin 0 -> 4653 bytes app/vendor/gemoji/images/26ea.png | Bin 0 -> 4653 bytes app/vendor/gemoji/images/26f2-fe0f.png | Bin 0 -> 5087 bytes app/vendor/gemoji/images/26f2.png | Bin 0 -> 5087 bytes app/vendor/gemoji/images/26f3-fe0f.png | Bin 0 -> 3548 bytes app/vendor/gemoji/images/26f3.png | Bin 0 -> 3548 bytes app/vendor/gemoji/images/26f5-fe0f.png | Bin 0 -> 3833 bytes app/vendor/gemoji/images/26f5.png | Bin 0 -> 3833 bytes app/vendor/gemoji/images/26fa-fe0f.png | Bin 0 -> 4482 bytes app/vendor/gemoji/images/26fa.png | Bin 0 -> 4482 bytes app/vendor/gemoji/images/26fd-fe0f.png | Bin 0 -> 4296 bytes app/vendor/gemoji/images/26fd.png | Bin 0 -> 4296 bytes app/vendor/gemoji/images/2702-fe0f.png | Bin 0 -> 3900 bytes app/vendor/gemoji/images/2702.png | Bin 0 -> 3900 bytes app/vendor/gemoji/images/2705.png | Bin 0 -> 3445 bytes app/vendor/gemoji/images/2708-fe0f.png | Bin 0 -> 4740 bytes app/vendor/gemoji/images/2708.png | Bin 0 -> 4740 bytes app/vendor/gemoji/images/2709-fe0f.png | Bin 0 -> 1655 bytes app/vendor/gemoji/images/2709.png | Bin 0 -> 1655 bytes app/vendor/gemoji/images/270a.png | Bin 0 -> 5880 bytes app/vendor/gemoji/images/270b.png | Bin 0 -> 4161 bytes app/vendor/gemoji/images/270c-fe0f.png | Bin 0 -> 4669 bytes app/vendor/gemoji/images/270c.png | Bin 0 -> 4669 bytes app/vendor/gemoji/images/270f-fe0f.png | Bin 0 -> 4450 bytes app/vendor/gemoji/images/270f.png | Bin 0 -> 4450 bytes app/vendor/gemoji/images/2712-fe0f.png | Bin 0 -> 2352 bytes app/vendor/gemoji/images/2712.png | Bin 0 -> 2352 bytes app/vendor/gemoji/images/2714-fe0f.png | Bin 0 -> 1103 bytes app/vendor/gemoji/images/2714.png | Bin 0 -> 1103 bytes app/vendor/gemoji/images/2716-fe0f.png | Bin 0 -> 591 bytes app/vendor/gemoji/images/2716.png | Bin 0 -> 591 bytes app/vendor/gemoji/images/2728.png | Bin 0 -> 2212 bytes app/vendor/gemoji/images/2733-fe0f.png | Bin 0 -> 4012 bytes app/vendor/gemoji/images/2733.png | Bin 0 -> 4012 bytes app/vendor/gemoji/images/2734-fe0f.png | Bin 0 -> 3312 bytes app/vendor/gemoji/images/2734.png | Bin 0 -> 3312 bytes app/vendor/gemoji/images/2744-fe0f.png | Bin 0 -> 5637 bytes app/vendor/gemoji/images/2744.png | Bin 0 -> 5637 bytes app/vendor/gemoji/images/2747-fe0f.png | Bin 0 -> 8904 bytes app/vendor/gemoji/images/2747.png | Bin 0 -> 8904 bytes app/vendor/gemoji/images/274c.png | Bin 0 -> 2118 bytes app/vendor/gemoji/images/274e.png | Bin 0 -> 3853 bytes app/vendor/gemoji/images/2753.png | Bin 0 -> 1740 bytes app/vendor/gemoji/images/2754.png | Bin 0 -> 1078 bytes app/vendor/gemoji/images/2755.png | Bin 0 -> 1142 bytes app/vendor/gemoji/images/2757-fe0f.png | Bin 0 -> 1315 bytes app/vendor/gemoji/images/2757.png | Bin 0 -> 1315 bytes app/vendor/gemoji/images/2764-fe0f.png | Bin 0 -> 3302 bytes app/vendor/gemoji/images/2764.png | Bin 0 -> 3302 bytes app/vendor/gemoji/images/2795.png | Bin 0 -> 315 bytes app/vendor/gemoji/images/2796.png | Bin 0 -> 197 bytes app/vendor/gemoji/images/2797.png | Bin 0 -> 340 bytes app/vendor/gemoji/images/27a1-fe0f.png | Bin 0 -> 3034 bytes app/vendor/gemoji/images/27a1.png | Bin 0 -> 3034 bytes app/vendor/gemoji/images/27b0.png | Bin 0 -> 1264 bytes app/vendor/gemoji/images/27bf.png | Bin 0 -> 3417 bytes app/vendor/gemoji/images/2934-fe0f.png | Bin 0 -> 3520 bytes app/vendor/gemoji/images/2934.png | Bin 0 -> 3520 bytes app/vendor/gemoji/images/2935-fe0f.png | Bin 0 -> 3521 bytes app/vendor/gemoji/images/2935.png | Bin 0 -> 3521 bytes app/vendor/gemoji/images/2b05-fe0f.png | Bin 0 -> 3053 bytes app/vendor/gemoji/images/2b05.png | Bin 0 -> 3053 bytes app/vendor/gemoji/images/2b06-fe0f.png | Bin 0 -> 3093 bytes app/vendor/gemoji/images/2b06.png | Bin 0 -> 3093 bytes app/vendor/gemoji/images/2b07-fe0f.png | Bin 0 -> 3024 bytes app/vendor/gemoji/images/2b07.png | Bin 0 -> 3024 bytes app/vendor/gemoji/images/2b1b-fe0f.png | Bin 0 -> 1332 bytes app/vendor/gemoji/images/2b1b.png | Bin 0 -> 1332 bytes app/vendor/gemoji/images/2b1c-fe0f.png | Bin 0 -> 1411 bytes app/vendor/gemoji/images/2b1c.png | Bin 0 -> 1411 bytes app/vendor/gemoji/images/2b50-fe0f.png | Bin 0 -> 3628 bytes app/vendor/gemoji/images/2b50.png | Bin 0 -> 3628 bytes app/vendor/gemoji/images/2b55-fe0f.png | Bin 0 -> 2542 bytes app/vendor/gemoji/images/2b55.png | Bin 0 -> 2542 bytes app/vendor/gemoji/images/3030.png | Bin 0 -> 872 bytes app/vendor/gemoji/images/303d-fe0f.png | Bin 0 -> 2685 bytes app/vendor/gemoji/images/303d.png | Bin 0 -> 2685 bytes app/vendor/gemoji/images/3297-fe0f.png | Bin 0 -> 4883 bytes app/vendor/gemoji/images/3297.png | Bin 0 -> 4883 bytes app/vendor/gemoji/images/3299-fe0f.png | Bin 0 -> 5364 bytes app/vendor/gemoji/images/3299.png | Bin 0 -> 5364 bytes .../jquery.emojiarea/jquery.emojiarea-orig.js | 458 + .../jquery.emojiarea/jquery.emojiarea.js | 475 + .../jquery.nanoscroller/nanoscroller.css | 55 + .../jquery.nanoscroller/nanoscroller.js | 899 + app/vendor/jquery/jquery.min.js | 6 + app/vendor/jsbn/THIRDPARTY_LICENSE | 40 + app/vendor/jsbn/jsbn_combined.js | 1348 + app/vendor/ui-bootstrap/THIRDPARTY_LICENSE | 22 + .../ui-bootstrap/ui-bootstrap-custom-0.7.0.js | 332 + .../ui-bootstrap-custom-0.7.0.min.js | 1 + .../ui-bootstrap-custom-tpls-0.7.0.js | 344 + .../ui-bootstrap-custom-tpls-0.7.0.min.js | 1 + app/vendor/zlib/THIRDPARTY_LICENSE | 28 + app/vendor/zlib/gunzip.min.js | 27 + app/vendor/zlib/gzip.min.js | 32 + config/karma-e2e.conf.js | 37 + config/karma.conf.js | 37 + emoji_data/build.php | 59 + emoji_data/emoji.json | 1 + node_modules/.bin/karma | 30 + node_modules/.bin/r.js | 26059 ++++ node_modules/karma-chrome-launcher/LICENSE | 20 + node_modules/karma-chrome-launcher/README.md | 52 + node_modules/karma-chrome-launcher/index.js | 83 + .../karma-chrome-launcher/package.json | 55 + .../karma-coffee-preprocessor/LICENSE | 20 + .../karma-coffee-preprocessor/README.md | 56 + .../karma-coffee-preprocessor/index.js | 53 + .../node_modules/.bin/cake | 7 + .../node_modules/.bin/coffee | 7 + .../node_modules/coffee-script/.npmignore | 11 + .../node_modules/coffee-script/CNAME | 1 + .../coffee-script/CONTRIBUTING.md | 9 + .../node_modules/coffee-script/LICENSE | 22 + .../node_modules/coffee-script/README | 51 + .../node_modules/coffee-script/Rakefile | 79 + .../node_modules/coffee-script/bin/cake | 7 + .../node_modules/coffee-script/bin/coffee | 7 + .../lib/coffee-script/browser.js | 118 + .../coffee-script/lib/coffee-script/cake.js | 114 + .../lib/coffee-script/coffee-script.js | 358 + .../lib/coffee-script/command.js | 526 + .../lib/coffee-script/grammar.js | 625 + .../lib/coffee-script/helpers.js | 223 + .../coffee-script/lib/coffee-script/index.js | 11 + .../coffee-script/lib/coffee-script/lexer.js | 889 + .../coffee-script/lib/coffee-script/nodes.js | 3048 + .../lib/coffee-script/optparse.js | 139 + .../coffee-script/lib/coffee-script/parser.js | 610 + .../coffee-script/lib/coffee-script/repl.js | 159 + .../lib/coffee-script/rewriter.js | 485 + .../coffee-script/lib/coffee-script/scope.js | 146 + .../lib/coffee-script/sourcemap.js | 161 + .../node_modules/coffee-script/package.json | 50 + .../karma-coffee-preprocessor/package.json | 62 + node_modules/karma-firefox-launcher/LICENSE | 20 + node_modules/karma-firefox-launcher/README.md | 42 + node_modules/karma-firefox-launcher/index.js | 114 + .../karma-firefox-launcher/index.js.orig | 85 + .../karma-firefox-launcher/package.json | 75 + .../karma-html2js-preprocessor/LICENSE | 20 + .../karma-html2js-preprocessor/README.md | 65 + .../karma-html2js-preprocessor/lib/html2js.js | 27 + .../karma-html2js-preprocessor/lib/index.js | 4 + .../karma-html2js-preprocessor/package.json | 47 + node_modules/karma-jasmine/LICENSE | 20 + node_modules/karma-jasmine/README.md | 43 + node_modules/karma-jasmine/lib/adapter.js | 165 + node_modules/karma-jasmine/lib/index.js | 14 + node_modules/karma-jasmine/lib/jasmine.js | 2683 + node_modules/karma-jasmine/package.json | 51 + node_modules/karma-junit-reporter/LICENSE | 20 + node_modules/karma-junit-reporter/README.md | 48 + node_modules/karma-junit-reporter/index.js | 113 + .../node_modules/xmlbuilder/.npmignore | 8 + .../node_modules/xmlbuilder/README.md | 73 + .../node_modules/xmlbuilder/lib/XMLBuilder.js | 119 + .../xmlbuilder/lib/XMLFragment.js | 422 + .../node_modules/xmlbuilder/lib/index.js | 15 + .../node_modules/xmlbuilder/package.json | 45 + .../karma-junit-reporter/package.json | 57 + node_modules/karma-phantomjs-launcher/LICENSE | 20 + .../karma-phantomjs-launcher/README.md | 59 + .../karma-phantomjs-launcher/index.js | 51 + .../node_modules/.bin/phantomjs | 36 + .../node_modules/phantomjs/.jshintrc | 3 + .../node_modules/phantomjs/.npmignore | 5 + .../node_modules/phantomjs/.travis.yml | 5 + .../node_modules/phantomjs/LICENSE.txt | 194 + .../node_modules/phantomjs/README.md | 122 + .../node_modules/phantomjs/bin/phantomjs | 36 + .../node_modules/phantomjs/install.js | 298 + .../node_modules/phantomjs/lib/location.js | 1 + .../phantomjs/lib/phantom/ChangeLog | 346 + .../phantomjs/lib/phantom/LICENSE.BSD | 22 + .../phantomjs/lib/phantom/README.md | 45 + .../phantomjs/lib/phantom/bin/phantomjs | Bin 0 -> 9595511 bytes .../lib/phantom/examples/arguments.coffee | 7 + .../lib/phantom/examples/arguments.js | 9 + .../examples/child_process-examples.coffee | 20 + .../examples/child_process-examples.js | 27 + .../lib/phantom/examples/colorwheel.coffee | 46 + .../lib/phantom/examples/colorwheel.js | 51 + .../lib/phantom/examples/countdown.coffee | 8 + .../lib/phantom/examples/countdown.js | 9 + .../lib/phantom/examples/detectsniff.coffee | 42 + .../lib/phantom/examples/detectsniff.js | 59 + .../lib/phantom/examples/direction.coffee | 30 + .../lib/phantom/examples/direction.js | 35 + .../lib/phantom/examples/echoToFile.coffee | 19 + .../lib/phantom/examples/echoToFile.js | 23 + .../lib/phantom/examples/features.coffee | 23 + .../lib/phantom/examples/features.js | 30 + .../lib/phantom/examples/fibo.coffee | 8 + .../phantomjs/lib/phantom/examples/fibo.js | 9 + .../lib/phantom/examples/follow.coffee | 33 + .../phantomjs/lib/phantom/examples/follow.js | 38 + .../lib/phantom/examples/hello.coffee | 2 + .../phantomjs/lib/phantom/examples/hello.js | 2 + .../lib/phantom/examples/imagebin.coffee | 20 + .../lib/phantom/examples/imagebin.js | 23 + .../lib/phantom/examples/injectme.coffee | 23 + .../lib/phantom/examples/injectme.js | 25 + .../lib/phantom/examples/ipgeocode.coffee | 13 + .../lib/phantom/examples/ipgeocode.js | 14 + .../lib/phantom/examples/loadspeed.coffee | 18 + .../lib/phantom/examples/loadspeed.js | 23 + .../phantom/examples/loadurlwithoutcss.coffee | 20 + .../lib/phantom/examples/loadurlwithoutcss.js | 25 + .../lib/phantom/examples/modernizr.js | 1116 + .../lib/phantom/examples/module.coffee | 4 + .../phantomjs/lib/phantom/examples/module.js | 4 + .../lib/phantom/examples/movies.coffee | 13 + .../phantomjs/lib/phantom/examples/movies.js | 14 + .../lib/phantom/examples/netlog.coffee | 18 + .../phantomjs/lib/phantom/examples/netlog.js | 25 + .../lib/phantom/examples/netsniff.coffee | 114 + .../lib/phantom/examples/netsniff.js | 143 + .../phantom/examples/outputEncoding.coffee | 12 + .../lib/phantom/examples/outputEncoding.js | 16 + .../lib/phantom/examples/page_events.coffee | 132 + .../lib/phantom/examples/page_events.js | 142 + .../lib/phantom/examples/pagecallback.coffee | 16 + .../lib/phantom/examples/pagecallback.js | 17 + .../phantom/examples/phantomwebintro.coffee | 13 + .../lib/phantom/examples/phantomwebintro.js | 19 + .../lib/phantom/examples/pizza.coffee | 18 + .../phantomjs/lib/phantom/examples/pizza.js | 20 + .../lib/phantom/examples/post.coffee | 12 + .../phantomjs/lib/phantom/examples/post.js | 14 + .../lib/phantom/examples/postserver.coffee | 25 + .../lib/phantom/examples/postserver.js | 34 + .../lib/phantom/examples/printenv.coffee | 6 + .../lib/phantom/examples/printenv.js | 10 + .../phantom/examples/printheaderfooter.coffee | 88 + .../lib/phantom/examples/printheaderfooter.js | 89 + .../lib/phantom/examples/printmargins.coffee | 33 + .../lib/phantom/examples/printmargins.js | 35 + .../lib/phantom/examples/rasterize.coffee | 23 + .../lib/phantom/examples/rasterize.js | 32 + .../phantom/examples/render_multi_url.coffee | 60 + .../lib/phantom/examples/render_multi_url.js | 73 + .../lib/phantom/examples/run-jasmine.coffee | 61 + .../lib/phantom/examples/run-jasmine.js | 86 + .../lib/phantom/examples/run-qunit.coffee | 64 + .../lib/phantom/examples/run-qunit.js | 76 + .../lib/phantom/examples/scandir.coffee | 16 + .../phantomjs/lib/phantom/examples/scandir.js | 22 + .../lib/phantom/examples/seasonfood.coffee | 17 + .../lib/phantom/examples/seasonfood.js | 19 + .../lib/phantom/examples/server.coffee | 45 + .../phantomjs/lib/phantom/examples/server.js | 43 + .../phantom/examples/serverkeepalive.coffee | 32 + .../lib/phantom/examples/serverkeepalive.js | 34 + .../lib/phantom/examples/simpleserver.coffee | 38 + .../lib/phantom/examples/simpleserver.js | 42 + .../lib/phantom/examples/sleepsort.coffee | 20 + .../lib/phantom/examples/sleepsort.js | 25 + .../examples/stdin-stdout-stderr.coffee | 18 + .../phantom/examples/stdin-stdout-stderr.js | 18 + .../lib/phantom/examples/technews.coffee | 17 + .../lib/phantom/examples/technews.js | 16 + .../lib/phantom/examples/tweets.coffee | 31 + .../phantomjs/lib/phantom/examples/tweets.js | 37 + .../lib/phantom/examples/universe.js | 10 + .../lib/phantom/examples/unrandomize.coffee | 18 + .../lib/phantom/examples/unrandomize.js | 24 + .../lib/phantom/examples/useragent.coffee | 11 + .../lib/phantom/examples/useragent.js | 14 + .../lib/phantom/examples/version.coffee | 5 + .../phantomjs/lib/phantom/examples/version.js | 5 + .../lib/phantom/examples/waitfor.coffee | 48 + .../phantomjs/lib/phantom/examples/waitfor.js | 57 + .../examples/walk_through_frames.coffee | 66 + .../phantom/examples/walk_through_frames.js | 73 + .../lib/phantom/examples/weather.coffee | 29 + .../phantomjs/lib/phantom/examples/weather.js | 37 + .../phantomjs/lib/phantom/third-party.txt | 48 + .../node_modules/phantomjs/lib/phantomjs.js | 56 + .../phantomjs/node_modules/.bin/ncp | 48 + .../phantomjs/node_modules/.bin/rimraf | 33 + .../phantomjs/node_modules/.bin/which | 14 + .../node_modules/adm-zip/.travis.yml | 4 + .../node_modules/adm-zip/MIT-LICENSE.txt | 21 + .../phantomjs/node_modules/adm-zip/README.md | 64 + .../phantomjs/node_modules/adm-zip/adm-zip.js | 405 + .../adm-zip/headers/dataHeader.js | 133 + .../adm-zip/headers/entryHeader.js | 187 + .../node_modules/adm-zip/headers/index.js | 3 + .../adm-zip/headers/mainHeader.js | 80 + .../node_modules/adm-zip/methods/deflater.js | 1051 + .../node_modules/adm-zip/methods/index.js | 2 + .../node_modules/adm-zip/methods/inflater.js | 446 + .../node_modules/adm-zip/package.json | 39 + .../phantomjs/node_modules/adm-zip/sandbox.js | 0 .../node_modules/adm-zip/util/constants.js | 53 + .../node_modules/adm-zip/util/errors.js | 35 + .../node_modules/adm-zip/util/fattr.js | 84 + .../node_modules/adm-zip/util/index.js | 4 + .../node_modules/adm-zip/util/utils.js | 134 + .../node_modules/adm-zip/zipEntry.js | 245 + .../phantomjs/node_modules/adm-zip/zipFile.js | 214 + .../phantomjs/node_modules/kew/.npmignore | 15 + .../phantomjs/node_modules/kew/LICENSE.TXT | 194 + .../phantomjs/node_modules/kew/README.md | 249 + .../phantomjs/node_modules/kew/kew.js | 426 + .../phantomjs/node_modules/kew/package.json | 33 + .../phantomjs/node_modules/kew/test/chain.js | 337 + .../node_modules/kew/test/context.js | 89 + .../phantomjs/node_modules/kew/test/defer.js | 120 + .../phantomjs/node_modules/kew/test/static.js | 187 + .../phantomjs/node_modules/mkdirp/.npmignore | 2 + .../phantomjs/node_modules/mkdirp/.travis.yml | 5 + .../phantomjs/node_modules/mkdirp/LICENSE | 21 + .../node_modules/mkdirp/examples/pow.js | 6 + .../phantomjs/node_modules/mkdirp/index.js | 82 + .../node_modules/mkdirp/package.json | 34 + .../node_modules/mkdirp/readme.markdown | 63 + .../node_modules/mkdirp/test/chmod.js | 38 + .../node_modules/mkdirp/test/clobber.js | 37 + .../node_modules/mkdirp/test/mkdirp.js | 28 + .../node_modules/mkdirp/test/perm.js | 32 + .../node_modules/mkdirp/test/perm_sync.js | 39 + .../node_modules/mkdirp/test/race.js | 41 + .../phantomjs/node_modules/mkdirp/test/rel.js | 32 + .../node_modules/mkdirp/test/return.js | 25 + .../node_modules/mkdirp/test/return_sync.js | 24 + .../node_modules/mkdirp/test/root.js | 18 + .../node_modules/mkdirp/test/sync.js | 32 + .../node_modules/mkdirp/test/umask.js | 28 + .../node_modules/mkdirp/test/umask_sync.js | 32 + .../phantomjs/node_modules/ncp/.npmignore | 4 + .../phantomjs/node_modules/ncp/.travis.yml | 7 + .../phantomjs/node_modules/ncp/LICENSE.md | 21 + .../phantomjs/node_modules/ncp/README.md | 52 + .../phantomjs/node_modules/ncp/bin/ncp | 48 + .../phantomjs/node_modules/ncp/lib/ncp.js | 222 + .../phantomjs/node_modules/ncp/package.json | 41 + .../node_modules/ncp/test/fixtures/src/a | 1 + .../node_modules/ncp/test/fixtures/src/b | 1 + .../node_modules/ncp/test/fixtures/src/c | 0 .../node_modules/ncp/test/fixtures/src/d | 0 .../node_modules/ncp/test/fixtures/src/e | 0 .../node_modules/ncp/test/fixtures/src/f | 0 .../node_modules/ncp/test/fixtures/src/sub/a | 1 + .../node_modules/ncp/test/fixtures/src/sub/b | 0 .../node_modules/ncp/test/ncp-test.js | 86 + .../phantomjs/node_modules/npmconf/.npmignore | 1 + .../phantomjs/node_modules/npmconf/LICENSE | 27 + .../phantomjs/node_modules/npmconf/README.md | 33 + .../node_modules/npmconf/config-defs.js | 396 + .../npmconf/node_modules/.bin/nopt | 51 + .../npmconf/node_modules/.bin/semver | 72 + .../node_modules/config-chain/.npmignore | 3 + .../npmconf/node_modules/config-chain/LICENCE | 22 + .../node_modules/config-chain/index.js | 282 + .../node_modules/proto-list/LICENSE | 23 + .../node_modules/proto-list/README.md | 3 + .../node_modules/proto-list/package.json | 33 + .../node_modules/proto-list/proto-list.js | 81 + .../node_modules/proto-list/test/basic.js | 61 + .../node_modules/config-chain/package.json | 32 + .../node_modules/config-chain/readme.markdown | 228 + .../node_modules/config-chain/test/broken.js | 10 + .../config-chain/test/broken.json | 21 + .../config-chain/test/chain-class.js | 100 + .../node_modules/config-chain/test/env.js | 10 + .../config-chain/test/find-file.js | 13 + .../node_modules/config-chain/test/get.js | 15 + .../config-chain/test/ignore-unfound-file.js | 5 + .../node_modules/config-chain/test/ini.js | 18 + .../node_modules/config-chain/test/save.js | 59 + .../npmconf/node_modules/inherits/README.md | 51 + .../npmconf/node_modules/inherits/inherits.js | 29 + .../node_modules/inherits/package.json | 31 + .../npmconf/node_modules/ini/LICENSE | 23 + .../npmconf/node_modules/ini/README.md | 79 + .../npmconf/node_modules/ini/ini.js | 166 + .../npmconf/node_modules/ini/package.json | 33 + .../npmconf/node_modules/ini/test/bar.js | 23 + .../node_modules/ini/test/fixtures/foo.ini | 47 + .../npmconf/node_modules/ini/test/foo.js | 71 + .../npmconf/node_modules/nopt/.npmignore | 1 + .../npmconf/node_modules/nopt/LICENSE | 23 + .../npmconf/node_modules/nopt/README.md | 210 + .../npmconf/node_modules/nopt/bin/nopt.js | 51 + .../node_modules/nopt/examples/my-program.js | 30 + .../npmconf/node_modules/nopt/lib/nopt.js | 612 + .../nopt/node_modules/abbrev/LICENSE | 23 + .../nopt/node_modules/abbrev/README.md | 23 + .../nopt/node_modules/abbrev/lib/abbrev.js | 111 + .../nopt/node_modules/abbrev/package.json | 29 + .../npmconf/node_modules/nopt/package.json | 36 + .../npmconf/node_modules/once/LICENSE | 27 + .../npmconf/node_modules/once/README.md | 33 + .../npmconf/node_modules/once/once.js | 19 + .../npmconf/node_modules/once/package.json | 40 + .../npmconf/node_modules/once/test/once.js | 18 + .../npmconf/node_modules/osenv/LICENSE | 25 + .../npmconf/node_modules/osenv/README.md | 63 + .../npmconf/node_modules/osenv/osenv.js | 80 + .../npmconf/node_modules/osenv/package.json | 43 + .../npmconf/node_modules/osenv/test/unix.js | 76 + .../node_modules/osenv/test/windows.js | 82 + .../npmconf/node_modules/semver/LICENSE | 23 + .../npmconf/node_modules/semver/README.md | 119 + .../npmconf/node_modules/semver/bin/semver | 72 + .../npmconf/node_modules/semver/package.json | 31 + .../npmconf/node_modules/semver/semver.js | 306 + .../npmconf/node_modules/semver/test.js | 436 + .../phantomjs/node_modules/npmconf/npmconf.js | 338 + .../node_modules/npmconf/package.json | 48 + .../node_modules/npmconf/test/00-setup.js | 27 + .../node_modules/npmconf/test/basic.js | 73 + .../node_modules/npmconf/test/builtin.js | 72 + .../npmconf/test/fixtures/builtin | 1 + .../npmconf/test/fixtures/globalconfig | 1 + .../npmconf/test/fixtures/userconfig | 22 + .../node_modules/npmconf/test/save.js | 74 + .../phantomjs/node_modules/rimraf/AUTHORS | 6 + .../phantomjs/node_modules/rimraf/LICENSE | 23 + .../phantomjs/node_modules/rimraf/README.md | 30 + .../phantomjs/node_modules/rimraf/bin.js | 33 + .../node_modules/graceful-fs/.npmignore | 1 + .../rimraf/node_modules/graceful-fs/LICENSE | 27 + .../rimraf/node_modules/graceful-fs/README.md | 26 + .../node_modules/graceful-fs/graceful-fs.js | 159 + .../node_modules/graceful-fs/package.json | 49 + .../node_modules/graceful-fs/polyfills.js | 228 + .../node_modules/graceful-fs/test/open.js | 39 + .../node_modules/rimraf/package.json | 62 + .../node_modules/rimraf/package/package.json | 19 + .../phantomjs/node_modules/rimraf/rimraf.js | 185 + .../phantomjs/node_modules/rimraf/test/run.sh | 10 + .../node_modules/rimraf/test/setup.sh | 47 + .../node_modules/rimraf/test/test-async.js | 5 + .../node_modules/rimraf/test/test-sync.js | 3 + .../phantomjs/node_modules/which/LICENSE | 23 + .../phantomjs/node_modules/which/README.md | 5 + .../phantomjs/node_modules/which/bin/which | 14 + .../phantomjs/node_modules/which/package.json | 31 + .../phantomjs/node_modules/which/which.js | 104 + .../node_modules/phantomjs/package.json | 60 + .../node_modules/phantomjs/test/loadspeed.js | 25 + .../node_modules/phantomjs/test/tests.js | 57 + .../karma-phantomjs-launcher/package.json | 69 + node_modules/karma-requirejs/LICENSE | 20 + node_modules/karma-requirejs/README.md | 18 + node_modules/karma-requirejs/lib/adapter.js | 47 + node_modules/karma-requirejs/lib/index.js | 18 + node_modules/karma-requirejs/package.json | 58 + node_modules/karma-script-launcher/LICENSE | 20 + node_modules/karma-script-launcher/README.md | 47 + node_modules/karma-script-launcher/index.js | 17 + .../karma-script-launcher/package.json | 42 + node_modules/karma/CHANGELOG.md | 626 + node_modules/karma/LICENSE | 20 + node_modules/karma/README.md | 178 + node_modules/karma/bin/karma | 30 + node_modules/karma/config.tpl.coffee | 55 + node_modules/karma/config.tpl.js | 68 + node_modules/karma/karma-completion.sh | 50 + node_modules/karma/lib/browser.js | 299 + node_modules/karma/lib/cli.js | 221 + node_modules/karma/lib/completion.js | 162 + node_modules/karma/lib/config.js | 352 + node_modules/karma/lib/constants.js | 30 + node_modules/karma/lib/events.js | 80 + node_modules/karma/lib/executor.js | 56 + node_modules/karma/lib/file-list.js | 383 + node_modules/karma/lib/helper.js | 97 + node_modules/karma/lib/index.js | 6 + node_modules/karma/lib/init.js | 366 + node_modules/karma/lib/launcher.js | 96 + node_modules/karma/lib/launchers/Base.js | 215 + node_modules/karma/lib/logger.js | 79 + node_modules/karma/lib/middleware/common.js | 70 + node_modules/karma/lib/middleware/karma.js | 117 + node_modules/karma/lib/middleware/proxy.js | 100 + node_modules/karma/lib/middleware/runner.js | 92 + .../karma/lib/middleware/source-files.js | 60 + node_modules/karma/lib/plugin.js | 49 + node_modules/karma/lib/preprocessor.js | 73 + node_modules/karma/lib/reporter.js | 73 + node_modules/karma/lib/reporters/Base.js | 148 + node_modules/karma/lib/reporters/BaseColor.js | 25 + node_modules/karma/lib/reporters/Dots.js | 45 + node_modules/karma/lib/reporters/DotsColor.js | 12 + node_modules/karma/lib/reporters/Multi.js | 21 + node_modules/karma/lib/reporters/Progress.js | 57 + .../karma/lib/reporters/ProgressColor.js | 12 + node_modules/karma/lib/runner.js | 70 + node_modules/karma/lib/server.js | 206 + node_modules/karma/lib/watcher.js | 101 + node_modules/karma/lib/web-server.js | 70 + node_modules/karma/node_modules/.bin/cake | 7 + node_modules/karma/node_modules/.bin/coffee | 7 + .../karma/node_modules/.bin/node-http-proxy | 113 + .../karma/node_modules/chokidar/.npmignore | 35 + .../karma/node_modules/chokidar/CHANGELOG.md | 79 + .../karma/node_modules/chokidar/README.md | 109 + .../karma/node_modules/chokidar/lib/index.js | 270 + .../node_modules/chokidar/lib/is-binary.js | 27 + .../karma/node_modules/chokidar/package.json | 49 + .../karma/node_modules/chokidar/setup.js | 69 + .../node_modules/chokidar/src/index.coffee | 242 + .../chokidar/src/is-binary.coffee | 42 + .../chokidar/test/chokidar-test.coffee | 209 + .../node_modules/chokidar/test/common.js | 5 + .../chokidar/test/fixtures/binary.mp3 | 0 .../chokidar/test/fixtures/change.txt | 1 + .../chokidar/test/fixtures/unlink.txt | 1 + .../node_modules/coffee-script/.npmignore | 11 + .../karma/node_modules/coffee-script/CNAME | 1 + .../coffee-script/CONTRIBUTING.md | 9 + .../karma/node_modules/coffee-script/LICENSE | 22 + .../karma/node_modules/coffee-script/README | 51 + .../karma/node_modules/coffee-script/Rakefile | 79 + .../karma/node_modules/coffee-script/bin/cake | 7 + .../node_modules/coffee-script/bin/coffee | 7 + .../lib/coffee-script/browser.js | 118 + .../coffee-script/lib/coffee-script/cake.js | 114 + .../lib/coffee-script/coffee-script.js | 358 + .../lib/coffee-script/command.js | 526 + .../lib/coffee-script/grammar.js | 625 + .../lib/coffee-script/helpers.js | 223 + .../coffee-script/lib/coffee-script/index.js | 11 + .../coffee-script/lib/coffee-script/lexer.js | 889 + .../coffee-script/lib/coffee-script/nodes.js | 3048 + .../lib/coffee-script/optparse.js | 139 + .../coffee-script/lib/coffee-script/parser.js | 610 + .../coffee-script/lib/coffee-script/repl.js | 159 + .../lib/coffee-script/rewriter.js | 485 + .../coffee-script/lib/coffee-script/scope.js | 146 + .../lib/coffee-script/sourcemap.js | 161 + .../node_modules/coffee-script/package.json | 50 + .../karma/node_modules/colors/MIT-LICENSE.txt | 22 + .../karma/node_modules/colors/ReadMe.md | 77 + .../karma/node_modules/colors/colors.js | 269 + .../karma/node_modules/colors/example.html | 74 + .../karma/node_modules/colors/example.js | 65 + .../karma/node_modules/colors/package.json | 24 + .../karma/node_modules/colors/test.js | 65 + .../karma/node_modules/connect/.npmignore | 12 + .../karma/node_modules/connect/.travis.yml | 4 + .../karma/node_modules/connect/LICENSE | 24 + .../karma/node_modules/connect/Readme.md | 133 + .../karma/node_modules/connect/index.js | 4 + .../karma/node_modules/connect/lib/cache.js | 81 + .../karma/node_modules/connect/lib/connect.js | 92 + .../karma/node_modules/connect/lib/index.js | 50 + .../connect/lib/middleware/basicAuth.js | 103 + .../connect/lib/middleware/bodyParser.js | 61 + .../connect/lib/middleware/compress.js | 189 + .../connect/lib/middleware/cookieParser.js | 62 + .../connect/lib/middleware/cookieSession.js | 115 + .../connect/lib/middleware/csrf.js | 163 + .../connect/lib/middleware/directory.js | 229 + .../connect/lib/middleware/errorHandler.js | 86 + .../connect/lib/middleware/favicon.js | 80 + .../connect/lib/middleware/json.js | 89 + .../connect/lib/middleware/limit.js | 78 + .../connect/lib/middleware/logger.js | 339 + .../connect/lib/middleware/methodOverride.js | 59 + .../connect/lib/middleware/multipart.js | 134 + .../connect/lib/middleware/query.js | 46 + .../connect/lib/middleware/responseTime.js | 32 + .../connect/lib/middleware/session.js | 355 + .../connect/lib/middleware/session/cookie.js | 140 + .../connect/lib/middleware/session/memory.js | 129 + .../connect/lib/middleware/session/session.js | 116 + .../connect/lib/middleware/session/store.js | 84 + .../connect/lib/middleware/static.js | 95 + .../connect/lib/middleware/staticCache.js | 231 + .../connect/lib/middleware/timeout.js | 55 + .../connect/lib/middleware/urlencoded.js | 78 + .../connect/lib/middleware/vhost.js | 40 + .../karma/node_modules/connect/lib/patch.js | 79 + .../karma/node_modules/connect/lib/proto.js | 230 + .../connect/lib/public/directory.html | 81 + .../connect/lib/public/error.html | 14 + .../connect/lib/public/favicon.ico | Bin 0 -> 1406 bytes .../connect/lib/public/icons/page.png | Bin 0 -> 635 bytes .../connect/lib/public/icons/page_add.png | Bin 0 -> 739 bytes .../connect/lib/public/icons/page_attach.png | Bin 0 -> 794 bytes .../connect/lib/public/icons/page_code.png | Bin 0 -> 818 bytes .../connect/lib/public/icons/page_copy.png | Bin 0 -> 663 bytes .../connect/lib/public/icons/page_delete.png | Bin 0 -> 740 bytes .../connect/lib/public/icons/page_edit.png | Bin 0 -> 807 bytes .../connect/lib/public/icons/page_error.png | Bin 0 -> 793 bytes .../connect/lib/public/icons/page_excel.png | Bin 0 -> 817 bytes .../connect/lib/public/icons/page_find.png | Bin 0 -> 879 bytes .../connect/lib/public/icons/page_gear.png | Bin 0 -> 833 bytes .../connect/lib/public/icons/page_go.png | Bin 0 -> 779 bytes .../connect/lib/public/icons/page_green.png | Bin 0 -> 621 bytes .../connect/lib/public/icons/page_key.png | Bin 0 -> 801 bytes .../lib/public/icons/page_lightning.png | Bin 0 -> 839 bytes .../connect/lib/public/icons/page_link.png | Bin 0 -> 830 bytes .../lib/public/icons/page_paintbrush.png | Bin 0 -> 813 bytes .../connect/lib/public/icons/page_paste.png | Bin 0 -> 703 bytes .../connect/lib/public/icons/page_red.png | Bin 0 -> 641 bytes .../connect/lib/public/icons/page_refresh.png | Bin 0 -> 858 bytes .../connect/lib/public/icons/page_save.png | Bin 0 -> 774 bytes .../connect/lib/public/icons/page_white.png | Bin 0 -> 294 bytes .../lib/public/icons/page_white_acrobat.png | Bin 0 -> 591 bytes .../public/icons/page_white_actionscript.png | Bin 0 -> 664 bytes .../lib/public/icons/page_white_add.png | Bin 0 -> 512 bytes .../connect/lib/public/icons/page_white_c.png | Bin 0 -> 587 bytes .../lib/public/icons/page_white_camera.png | Bin 0 -> 656 bytes .../lib/public/icons/page_white_cd.png | Bin 0 -> 666 bytes .../lib/public/icons/page_white_code.png | Bin 0 -> 603 bytes .../lib/public/icons/page_white_code_red.png | Bin 0 -> 587 bytes .../public/icons/page_white_coldfusion.png | Bin 0 -> 592 bytes .../public/icons/page_white_compressed.png | Bin 0 -> 724 bytes .../lib/public/icons/page_white_copy.png | Bin 0 -> 309 bytes .../lib/public/icons/page_white_cplusplus.png | Bin 0 -> 621 bytes .../lib/public/icons/page_white_csharp.png | Bin 0 -> 700 bytes .../lib/public/icons/page_white_cup.png | Bin 0 -> 639 bytes .../lib/public/icons/page_white_database.png | Bin 0 -> 579 bytes .../lib/public/icons/page_white_delete.png | Bin 0 -> 536 bytes .../lib/public/icons/page_white_dvd.png | Bin 0 -> 638 bytes .../lib/public/icons/page_white_edit.png | Bin 0 -> 618 bytes .../lib/public/icons/page_white_error.png | Bin 0 -> 623 bytes .../lib/public/icons/page_white_excel.png | Bin 0 -> 663 bytes .../lib/public/icons/page_white_find.png | Bin 0 -> 676 bytes .../lib/public/icons/page_white_flash.png | Bin 0 -> 582 bytes .../lib/public/icons/page_white_freehand.png | Bin 0 -> 639 bytes .../lib/public/icons/page_white_gear.png | Bin 0 -> 402 bytes .../lib/public/icons/page_white_get.png | Bin 0 -> 516 bytes .../lib/public/icons/page_white_go.png | Bin 0 -> 612 bytes .../connect/lib/public/icons/page_white_h.png | Bin 0 -> 603 bytes .../public/icons/page_white_horizontal.png | Bin 0 -> 296 bytes .../lib/public/icons/page_white_key.png | Bin 0 -> 616 bytes .../lib/public/icons/page_white_lightning.png | Bin 0 -> 669 bytes .../lib/public/icons/page_white_link.png | Bin 0 -> 614 bytes .../lib/public/icons/page_white_magnify.png | Bin 0 -> 554 bytes .../lib/public/icons/page_white_medal.png | Bin 0 -> 706 bytes .../lib/public/icons/page_white_office.png | Bin 0 -> 779 bytes .../lib/public/icons/page_white_paint.png | Bin 0 -> 688 bytes .../public/icons/page_white_paintbrush.png | Bin 0 -> 618 bytes .../lib/public/icons/page_white_paste.png | Bin 0 -> 620 bytes .../lib/public/icons/page_white_php.png | Bin 0 -> 538 bytes .../lib/public/icons/page_white_picture.png | Bin 0 -> 650 bytes .../public/icons/page_white_powerpoint.png | Bin 0 -> 588 bytes .../lib/public/icons/page_white_put.png | Bin 0 -> 523 bytes .../lib/public/icons/page_white_ruby.png | Bin 0 -> 626 bytes .../lib/public/icons/page_white_stack.png | Bin 0 -> 317 bytes .../lib/public/icons/page_white_star.png | Bin 0 -> 565 bytes .../lib/public/icons/page_white_swoosh.png | Bin 0 -> 634 bytes .../lib/public/icons/page_white_text.png | Bin 0 -> 342 bytes .../public/icons/page_white_text_width.png | Bin 0 -> 315 bytes .../lib/public/icons/page_white_tux.png | Bin 0 -> 668 bytes .../lib/public/icons/page_white_vector.png | Bin 0 -> 644 bytes .../public/icons/page_white_visualstudio.png | Bin 0 -> 702 bytes .../lib/public/icons/page_white_width.png | Bin 0 -> 309 bytes .../lib/public/icons/page_white_word.png | Bin 0 -> 651 bytes .../lib/public/icons/page_white_world.png | Bin 0 -> 734 bytes .../lib/public/icons/page_white_wrench.png | Bin 0 -> 613 bytes .../lib/public/icons/page_white_zip.png | Bin 0 -> 386 bytes .../connect/lib/public/icons/page_word.png | Bin 0 -> 777 bytes .../connect/lib/public/icons/page_world.png | Bin 0 -> 903 bytes .../node_modules/connect/lib/public/style.css | 141 + .../karma/node_modules/connect/lib/utils.js | 386 + .../node_modules/buffer-crc32/.npmignore | 1 + .../node_modules/buffer-crc32/.travis.yml | 8 + .../node_modules/buffer-crc32/README.md | 47 + .../node_modules/buffer-crc32/index.js | 88 + .../node_modules/buffer-crc32/package.json | 39 + .../buffer-crc32/tests/crc.test.js | 89 + .../connect/node_modules/bytes/.npmignore | 1 + .../connect/node_modules/bytes/History.md | 10 + .../connect/node_modules/bytes/Makefile | 7 + .../connect/node_modules/bytes/Readme.md | 51 + .../connect/node_modules/bytes/component.json | 7 + .../connect/node_modules/bytes/index.js | 39 + .../connect/node_modules/bytes/package.json | 20 + .../node_modules/cookie-signature/.npmignore | 4 + .../node_modules/cookie-signature/History.md | 11 + .../node_modules/cookie-signature/Makefile | 7 + .../node_modules/cookie-signature/Readme.md | 42 + .../node_modules/cookie-signature/index.js | 42 + .../cookie-signature/package.json | 24 + .../connect/node_modules/cookie/.npmignore | 1 + .../connect/node_modules/cookie/.travis.yml | 5 + .../connect/node_modules/cookie/LICENSE | 9 + .../connect/node_modules/cookie/README.md | 44 + .../connect/node_modules/cookie/index.js | 70 + .../connect/node_modules/cookie/package.json | 37 + .../node_modules/cookie/test/mocha.opts | 1 + .../connect/node_modules/cookie/test/parse.js | 44 + .../node_modules/cookie/test/serialize.js | 64 + .../connect/node_modules/debug/Readme.md | 115 + .../connect/node_modules/debug/debug.js | 137 + .../connect/node_modules/debug/index.js | 5 + .../connect/node_modules/debug/lib/debug.js | 147 + .../connect/node_modules/debug/package.json | 46 + .../node_modules/formidable/.npmignore | 4 + .../node_modules/formidable/.travis.yml | 5 + .../connect/node_modules/formidable/LICENSE | 7 + .../connect/node_modules/formidable/Readme.md | 419 + .../benchmark/bench-multipart-parser.js | 71 + .../node_modules/formidable/example/json.js | 67 + .../node_modules/formidable/example/post.js | 43 + .../node_modules/formidable/example/upload.js | 48 + .../connect/node_modules/formidable/index.js | 1 + .../node_modules/formidable/lib/file.js | 72 + .../formidable/lib/incoming_form.js | 535 + .../node_modules/formidable/lib/index.js | 3 + .../formidable/lib/json_parser.js | 35 + .../formidable/lib/multipart_parser.js | 324 + .../formidable/lib/octet_parser.js | 20 + .../formidable/lib/querystring_parser.js | 27 + .../node_modules/formidable/package.json | 38 + .../node_modules/formidable/test/common.js | 18 + .../test/fixture/file/beta-sticker-1.png | Bin 0 -> 1660 bytes .../test/fixture/file/binaryfile.tar.gz | Bin 0 -> 301 bytes .../formidable/test/fixture/file/blank.gif | Bin 0 -> 49 bytes .../test/fixture/file/funkyfilename.txt | 1 + .../test/fixture/file/menu_separator.png | Bin 0 -> 931 bytes .../formidable/test/fixture/file/plain.txt | 1 + .../http/special-chars-in-filename/info.md | 3 + .../formidable/test/fixture/js/encoding.js | 24 + .../formidable/test/fixture/js/misc.js | 6 + .../formidable/test/fixture/js/no-filename.js | 9 + .../formidable/test/fixture/js/preamble.js | 9 + .../fixture/js/special-chars-in-filename.js | 21 + .../formidable/test/fixture/js/workarounds.js | 8 + .../formidable/test/fixture/multipart.js | 72 + .../test/integration/test-fixtures.js | 96 + .../formidable/test/integration/test-json.js | 38 + .../test/integration/test-octet-stream.js | 45 + .../formidable/test/legacy/common.js | 24 + .../integration/test-multipart-parser.js | 80 + .../test/legacy/simple/test-file.js | 104 + .../test/legacy/simple/test-incoming-form.js | 756 + .../legacy/simple/test-multipart-parser.js | 50 + .../legacy/simple/test-querystring-parser.js | 45 + .../legacy/system/test-multi-video-upload.js | 71 + .../node_modules/formidable/test/run.js | 1 + .../standalone/test-connection-aborted.js | 27 + .../test-content-transfer-encoding.js | 48 + .../test/standalone/test-issue-46.js | 49 + .../formidable/test/tools/base64.html | 67 + .../formidable/test/unit/test-file.js | 33 + .../test/unit/test-incoming-form.js | 63 + .../node_modules/formidable/tool/record.js | 47 + .../connect/node_modules/fresh/.npmignore | 1 + .../connect/node_modules/fresh/History.md | 5 + .../connect/node_modules/fresh/Makefile | 7 + .../connect/node_modules/fresh/Readme.md | 57 + .../connect/node_modules/fresh/index.js | 53 + .../connect/node_modules/fresh/package.json | 28 + .../connect/node_modules/methods/index.js | 26 + .../connect/node_modules/methods/package.json | 20 + .../connect/node_modules/pause/.npmignore | 4 + .../connect/node_modules/pause/History.md | 5 + .../connect/node_modules/pause/Makefile | 7 + .../connect/node_modules/pause/Readme.md | 29 + .../connect/node_modules/pause/index.js | 29 + .../connect/node_modules/pause/package.json | 20 + .../connect/node_modules/qs/.gitmodules | 6 + .../connect/node_modules/qs/.npmignore | 7 + .../connect/node_modules/qs/Readme.md | 58 + .../connect/node_modules/qs/index.js | 387 + .../connect/node_modules/qs/package.json | 38 + .../connect/node_modules/send/.npmignore | 4 + .../connect/node_modules/send/History.md | 40 + .../connect/node_modules/send/Makefile | 8 + .../connect/node_modules/send/Readme.md | 128 + .../connect/node_modules/send/index.js | 2 + .../connect/node_modules/send/lib/send.js | 474 + .../connect/node_modules/send/lib/utils.js | 47 + .../send/node_modules/range-parser/.npmignore | 1 + .../send/node_modules/range-parser/History.md | 15 + .../send/node_modules/range-parser/Makefile | 7 + .../send/node_modules/range-parser/Readme.md | 28 + .../send/node_modules/range-parser/index.js | 49 + .../node_modules/range-parser/package.json | 20 + .../connect/node_modules/send/package.json | 42 + .../connect/node_modules/uid2/index.js | 49 + .../connect/node_modules/uid2/package.json | 12 + .../karma/node_modules/connect/package.json | 62 + .../karma/node_modules/connect/test.js | 7 + node_modules/karma/node_modules/di/LICENSE | 20 + node_modules/karma/node_modules/di/README.md | 22 + .../karma/node_modules/di/lib/annotation.js | 37 + .../karma/node_modules/di/lib/index.js | 5 + .../karma/node_modules/di/lib/injector.js | 131 + .../karma/node_modules/di/lib/module.js | 24 + .../karma/node_modules/di/package.json | 40 + .../karma/node_modules/glob/.npmignore | 2 + .../karma/node_modules/glob/.travis.yml | 3 + node_modules/karma/node_modules/glob/LICENSE | 27 + .../karma/node_modules/glob/README.md | 233 + .../karma/node_modules/glob/examples/g.js | 9 + .../node_modules/glob/examples/usr-local.js | 9 + node_modules/karma/node_modules/glob/glob.js | 643 + .../glob/node_modules/inherits/README.md | 51 + .../glob/node_modules/inherits/inherits.js | 29 + .../glob/node_modules/inherits/package.json | 30 + .../karma/node_modules/glob/package.json | 40 + .../karma/node_modules/glob/test/00-setup.js | 176 + .../node_modules/glob/test/bash-comparison.js | 63 + .../node_modules/glob/test/bash-results.json | 348 + .../karma/node_modules/glob/test/cwd-test.js | 55 + .../karma/node_modules/glob/test/mark.js | 74 + .../node_modules/glob/test/nocase-nomagic.js | 113 + .../node_modules/glob/test/pause-resume.js | 73 + .../node_modules/glob/test/root-nomount.js | 39 + .../karma/node_modules/glob/test/root.js | 46 + .../node_modules/glob/test/zz-cleanup.js | 11 + .../karma/node_modules/graceful-fs/.npmignore | 1 + .../karma/node_modules/graceful-fs/LICENSE | 27 + .../karma/node_modules/graceful-fs/README.md | 33 + .../node_modules/graceful-fs/graceful-fs.js | 442 + .../node_modules/graceful-fs/package.json | 49 + .../node_modules/graceful-fs/test/open.js | 46 + .../node_modules/graceful-fs/test/ulimit.js | 158 + .../karma/node_modules/http-proxy/.npmignore | 3 + .../karma/node_modules/http-proxy/.travis.yml | 9 + .../node_modules/http-proxy/CHANGELOG.md | 97 + .../karma/node_modules/http-proxy/LICENSE | 23 + .../karma/node_modules/http-proxy/README.md | 629 + .../benchmark/websockets-throughput.js | 88 + .../http-proxy/bin/node-http-proxy | 113 + .../http-proxy/config.sample.json | 10 + .../simple-balancer-with-websockets.js | 58 + .../examples/balancer/simple-balancer.js | 36 + .../http-proxy/examples/helpers/store.js | 64 + .../http-proxy/examples/http/basic-proxy.js | 58 + .../examples/http/concurrent-proxy.js | 66 + .../examples/http/custom-proxy-error.js | 54 + .../http-proxy/examples/http/forward-proxy.js | 63 + .../http-proxy/examples/http/latent-proxy.js | 56 + .../examples/http/proxy-https-to-http.js | 51 + .../examples/http/proxy-https-to-https.js | 55 + .../http-proxy/examples/http/proxy-table.js | 51 + .../examples/http/standalone-proxy.js | 57 + .../middleware/bodyDecoder-middleware.js | 87 + .../middleware/gzip-middleware-proxytable.js | 54 + .../examples/middleware/gzip-middleware.js | 50 + .../examples/middleware/jsonp-middleware.js | 30 + .../middleware/modifyResponse-middleware.js | 57 + .../examples/middleware/url-middleware.js | 58 + .../examples/middleware/url-middleware2.js | 30 + .../http-proxy/examples/package.json | 12 + .../websocket/latent-websocket-proxy.js | 92 + .../websocket/standalone-websocket-proxy.js | 87 + .../examples/websocket/websocket-proxy.js | 69 + .../http-proxy/lib/node-http-proxy.js | 394 + .../lib/node-http-proxy/http-proxy.js | 952 + .../lib/node-http-proxy/proxy-table.js | 282 + .../lib/node-http-proxy/routing-proxy.js | 322 + .../node_modules/pkginfo/.npmignore | 2 + .../http-proxy/node_modules/pkginfo/README.md | 85 + .../node_modules/pkginfo/docs/docco.css | 194 + .../node_modules/pkginfo/docs/pkginfo.html | 101 + .../pkginfo/examples/all-properties.js | 19 + .../pkginfo/examples/array-argument.js | 20 + .../pkginfo/examples/multiple-properties.js | 19 + .../pkginfo/examples/object-argument.js | 22 + .../pkginfo/examples/package.json | 10 + .../pkginfo/examples/single-property.js | 19 + .../node_modules/pkginfo/lib/pkginfo.js | 132 + .../node_modules/pkginfo/package.json | 36 + .../node_modules/pkginfo/test/pkginfo-test.js | 69 + .../http-proxy/node_modules/utile/.npmignore | 4 + .../http-proxy/node_modules/utile/.travis.yml | 10 + .../node_modules/utile/CHANGELOG.md | 16 + .../http-proxy/node_modules/utile/LICENSE | 19 + .../http-proxy/node_modules/utile/README.md | 87 + .../http-proxy/node_modules/utile/lib/args.js | 46 + .../node_modules/utile/lib/base64.js | 44 + .../http-proxy/node_modules/utile/lib/file.js | 33 + .../node_modules/utile/lib/format.js | 25 + .../node_modules/utile/lib/index.js | 467 + .../node_modules/utile/node_modules/.bin/ncp | 48 + .../utile/node_modules/async/.gitmodules | 9 + .../utile/node_modules/async/.npmignore | 4 + .../utile/node_modules/async/LICENSE | 19 + .../utile/node_modules/async/Makefile | 25 + .../utile/node_modules/async/README.md | 1021 + .../utile/node_modules/async/index.js | 3 + .../utile/node_modules/async/lib/async.js | 692 + .../utile/node_modules/async/package.json | 32 + .../utile/node_modules/deep-equal/.travis.yml | 4 + .../node_modules/deep-equal/README.markdown | 61 + .../node_modules/deep-equal/example/cmp.js | 11 + .../utile/node_modules/deep-equal/index.js | 86 + .../node_modules/deep-equal/package.json | 67 + .../utile/node_modules/deep-equal/test/cmp.js | 32 + .../utile/node_modules/i/.npmignore | 3 + .../utile/node_modules/i/.travis.yml | 9 + .../node_modules/utile/node_modules/i/LICENSE | 18 + .../utile/node_modules/i/README.md | 174 + .../utile/node_modules/i/lib/defaults.js | 63 + .../utile/node_modules/i/lib/inflect.js | 11 + .../utile/node_modules/i/lib/inflections.js | 116 + .../utile/node_modules/i/lib/methods.js | 233 + .../utile/node_modules/i/lib/native.js | 26 + .../utile/node_modules/i/lib/util.js | 136 + .../utile/node_modules/i/package.json | 61 + .../node_modules/i/test/inflector/cases.js | 209 + .../i/test/inflector/inflections-test.js | 87 + .../i/test/inflector/methods-test.js | 342 + .../node_modules/i/test/utils/array-test.js | 39 + .../node_modules/i/test/utils/string-test.js | 88 + .../utile/node_modules/mkdirp/.npmignore | 2 + .../utile/node_modules/mkdirp/.travis.yml | 5 + .../utile/node_modules/mkdirp/LICENSE | 21 + .../utile/node_modules/mkdirp/examples/pow.js | 6 + .../utile/node_modules/mkdirp/index.js | 82 + .../utile/node_modules/mkdirp/package.json | 34 + .../utile/node_modules/mkdirp/readme.markdown | 63 + .../utile/node_modules/mkdirp/test/chmod.js | 38 + .../utile/node_modules/mkdirp/test/clobber.js | 37 + .../utile/node_modules/mkdirp/test/mkdirp.js | 28 + .../utile/node_modules/mkdirp/test/perm.js | 32 + .../node_modules/mkdirp/test/perm_sync.js | 39 + .../utile/node_modules/mkdirp/test/race.js | 41 + .../utile/node_modules/mkdirp/test/rel.js | 32 + .../utile/node_modules/mkdirp/test/return.js | 25 + .../node_modules/mkdirp/test/return_sync.js | 24 + .../utile/node_modules/mkdirp/test/root.js | 18 + .../utile/node_modules/mkdirp/test/sync.js | 32 + .../utile/node_modules/mkdirp/test/umask.js | 28 + .../node_modules/mkdirp/test/umask_sync.js | 32 + .../utile/node_modules/ncp/.npmignore | 4 + .../utile/node_modules/ncp/.travis.yml | 6 + .../utile/node_modules/ncp/LICENSE.md | 21 + .../utile/node_modules/ncp/README.md | 46 + .../utile/node_modules/ncp/bin/ncp | 48 + .../utile/node_modules/ncp/lib/ncp.js | 216 + .../utile/node_modules/ncp/package.json | 41 + .../node_modules/ncp/test/fixtures/src/a | 1 + .../node_modules/ncp/test/fixtures/src/b | 1 + .../node_modules/ncp/test/fixtures/src/c | 0 .../node_modules/ncp/test/fixtures/src/d | 0 .../node_modules/ncp/test/fixtures/src/e | 0 .../node_modules/ncp/test/fixtures/src/f | 0 .../node_modules/ncp/test/fixtures/src/sub/a | 1 + .../node_modules/ncp/test/fixtures/src/sub/b | 0 .../utile/node_modules/ncp/test/ncp-test.js | 74 + .../utile/node_modules/rimraf/AUTHORS | 5 + .../utile/node_modules/rimraf/LICENSE | 23 + .../utile/node_modules/rimraf/README.md | 32 + .../utile/node_modules/rimraf/fiber.js | 86 + .../utile/node_modules/rimraf/package.json | 49 + .../utile/node_modules/rimraf/rimraf.js | 145 + .../utile/node_modules/rimraf/test/run.sh | 10 + .../utile/node_modules/rimraf/test/setup.sh | 47 + .../node_modules/rimraf/test/test-async.js | 5 + .../node_modules/rimraf/test/test-fiber.js | 15 + .../node_modules/rimraf/test/test-sync.js | 3 + .../node_modules/utile/package.json | 45 + .../node_modules/utile/test/file-test.js | 31 + .../test/fixtures/read-json-file/config.json | 9 + .../require-directory/directory/index.js | 2 + .../fixtures/require-directory/helloWorld.js | 2 + .../node_modules/utile/test/format-test.js | 31 + .../utile/test/function-args-test.js | 104 + .../node_modules/utile/test/helpers/macros.js | 37 + .../utile/test/random-string-test.js | 39 + .../utile/test/require-directory-test.js | 35 + .../node_modules/utile/test/utile-test.js | 126 + .../node_modules/http-proxy/package.json | 63 + .../http-proxy/test/core/README.md | 10 + .../http-proxy/test/core/common.js | 190 + .../core/pummel/test-http-upload-timeout.js | 69 + .../node_modules/http-proxy/test/core/run | 90 + .../http-proxy/test/core/run-single | 70 + .../test/core/simple/test-http-chunked.js | 63 + .../core/simple/test-http-client-abort.js | 80 + .../core/simple/test-http-client-abort2.js | 41 + .../simple/test-http-client-upload-buf.js | 74 + .../core/simple/test-http-client-upload.js | 77 + .../core/simple/test-http-contentLength0.js | 42 + .../core/simple/test-http-eof-on-connect.js | 40 + .../core/simple/test-http-extra-response.js | 86 + .../core/simple/test-http-head-request.js | 56 + ...test-http-head-response-has-no-body-end.js | 61 + .../test-http-head-response-has-no-body.js | 58 + .../core/simple/test-http-host-headers.js | 101 + .../test-http-many-keep-alive-connections.js | 68 + .../simple/test-http-multi-line-headers.js | 59 + .../test/core/simple/test-http-proxy.js | 109 + .../core/simple/test-http-response-close.js | 55 + .../simple/test-http-server-multiheaders.js | 59 + .../test/core/simple/test-http-set-cookies.js | 84 + .../test/core/simple/test-http-status-code.js | 69 + .../core/simple/test-http-upgrade-server2.js | 72 + .../http-proxy/test/core/simple/test-http.js | 108 + .../http-proxy/test/examples-test.js | 26 + .../http-proxy/test/fixtures/agent2-cert.pem | 13 + .../http-proxy/test/fixtures/agent2-csr.pem | 10 + .../http-proxy/test/fixtures/agent2-key.pem | 9 + .../http-proxy/test/fixtures/agent2.cnf | 19 + .../http-proxy/test/helpers/http.js | 182 + .../http-proxy/test/helpers/index.js | 105 + .../http-proxy/test/helpers/ws.js | 112 + .../http-proxy/test/http/http-test.js | 102 + .../test/http/routing-table-test.js | 107 + .../http-proxy/test/macros/examples.js | 101 + .../http-proxy/test/macros/http.js | 531 + .../http-proxy/test/macros/index.js | 11 + .../node_modules/http-proxy/test/macros/ws.js | 232 + .../http-proxy/test/ws/routing-table-test.js | 25 + .../http-proxy/test/ws/socket.io-test.js | 20 + .../http-proxy/test/ws/ws-test.js | 23 + .../karma/node_modules/lodash/README.md | 178 + .../node_modules/lodash/dist/lodash.compat.js | 5438 + .../lodash/dist/lodash.compat.min.js | 46 + .../karma/node_modules/lodash/dist/lodash.js | 5217 + .../node_modules/lodash/dist/lodash.legacy.js | 5364 + .../lodash/dist/lodash.legacy.min.js | 45 + .../node_modules/lodash/dist/lodash.min.js | 42 + .../node_modules/lodash/dist/lodash.mobile.js | 5190 + .../lodash/dist/lodash.mobile.min.js | 43 + .../lodash/dist/lodash.underscore.js | 4355 + .../lodash/dist/lodash.underscore.min.js | 34 + .../karma/node_modules/lodash/package.json | 62 + .../karma/node_modules/log4js/.bob.json | 12 + .../node_modules/log4js/.bob/report/lint.out | 26 + .../karma/node_modules/log4js/.jshintrc | 15 + .../karma/node_modules/log4js/.npmignore | 2 + .../karma/node_modules/log4js/.travis.yml | 5 + .../karma/node_modules/log4js/README.md | 143 + .../log4js/examples/example-connect-logger.js | 46 + .../log4js/examples/example-socket.js | 45 + .../node_modules/log4js/examples/example.js | 58 + .../log4js/examples/fromreadme.js | 19 + .../log4js/examples/log-rolling.js | 27 + .../log4js/examples/memory-test.js | 37 + .../log4js/examples/patternLayout-tokens.js | 21 + .../log4js/examples/smtp-appender.js | 43 + .../log4js/lib/appenders/categoryFilter.js | 20 + .../log4js/lib/appenders/clustered.js | 126 + .../log4js/lib/appenders/console.js | 21 + .../log4js/lib/appenders/dateFile.js | 58 + .../node_modules/log4js/lib/appenders/file.js | 82 + .../node_modules/log4js/lib/appenders/gelf.js | 141 + .../log4js/lib/appenders/hookio.js | 76 + .../log4js/lib/appenders/logLevelFilter.js | 21 + .../log4js/lib/appenders/multiprocess.js | 134 + .../node_modules/log4js/lib/appenders/smtp.js | 82 + .../node_modules/log4js/lib/connect-logger.js | 194 + .../node_modules/log4js/lib/date_format.js | 66 + .../karma/node_modules/log4js/lib/debug.js | 15 + .../karma/node_modules/log4js/lib/layouts.js | 318 + .../karma/node_modules/log4js/lib/levels.js | 68 + .../karma/node_modules/log4js/lib/log4js.js | 327 + .../karma/node_modules/log4js/lib/log4js.json | 7 + .../karma/node_modules/log4js/lib/logger.js | 80 + .../lib/streams/BaseRollingFileStream.js | 84 + .../lib/streams/DateRollingFileStream.js | 88 + .../log4js/lib/streams/RollingFileStream.js | 89 + .../node_modules/log4js/lib/streams/index.js | 2 + .../log4js/node_modules/.bin/semver | 72 + .../log4js/node_modules/async/.gitmodules | 9 + .../log4js/node_modules/async/LICENSE | 19 + .../log4js/node_modules/async/Makefile | 21 + .../log4js/node_modules/async/README.md | 1009 + .../node_modules/async/deps/nodeunit.css | 70 + .../node_modules/async/deps/nodeunit.js | 1966 + .../node_modules/async/dist/async.min.js | 1 + .../log4js/node_modules/async/index.js | 3 + .../log4js/node_modules/async/lib/async.js | 690 + .../log4js/node_modules/async/nodelint.cfg | 4 + .../log4js/node_modules/async/package.json | 27 + .../node_modules/async/test/test-async.js | 1577 + .../log4js/node_modules/async/test/test.html | 24 + .../node_modules/readable-stream/LICENSE | 27 + .../node_modules/readable-stream/README.md | 768 + .../node_modules/readable-stream/duplex.js | 1 + .../readable-stream/examples/CAPSLOCKTYPER.JS | 32 + .../readable-stream/examples/typer-fsr.js | 15 + .../readable-stream/examples/typer.js | 17 + .../node_modules/readable-stream/float.patch | 68 + .../log4js/node_modules/readable-stream/fs.js | 1705 + .../readable-stream/lib/_stream_duplex.js | 69 + .../lib/_stream_passthrough.js | 41 + .../readable-stream/lib/_stream_readable.js | 927 + .../readable-stream/lib/_stream_transform.js | 205 + .../readable-stream/lib/_stream_writable.js | 367 + .../node_modules/readable-stream/package.json | 36 + .../readable-stream/passthrough.js | 1 + .../node_modules/readable-stream/readable.js | 6 + .../readable-stream/test/common.js | 191 + .../readable-stream/test/fixtures/x1024.txt | 1 + .../test/simple/test-stream2-basic.js | 475 + .../test/simple/test-stream2-compatibility.js | 50 + .../test/simple/test-stream2-finish-pipe.js | 41 + .../simple/test-stream2-large-read-stall.js | 82 + .../test/simple/test-stream2-objects.js | 348 + .../test-stream2-pipe-error-handling.js | 105 + .../test/simple/test-stream2-push.js | 138 + .../simple/test-stream2-read-sync-stack.js | 54 + ...st-stream2-readable-empty-buffer-no-eof.js | 119 + .../simple/test-stream2-readable-from-list.js | 120 + .../test-stream2-readable-legacy-drain.js | 75 + .../test-stream2-readable-non-empty-end.js | 78 + .../test/simple/test-stream2-set-encoding.js | 312 + .../test/simple/test-stream2-transform.js | 435 + .../test/simple/test-stream2-unpipe-drain.js | 76 + .../test/simple/test-stream2-unpipe-leak.js | 74 + .../test/simple/test-stream2-writable.js | 328 + .../node_modules/readable-stream/transform.js | 1 + .../node_modules/readable-stream/writable.js | 1 + .../node_modules/readable-stream/zlib.js | 452 + .../log4js/node_modules/semver/LICENSE | 23 + .../log4js/node_modules/semver/README.md | 119 + .../log4js/node_modules/semver/bin/semver | 72 + .../log4js/node_modules/semver/package.json | 31 + .../log4js/node_modules/semver/semver.js | 306 + .../log4js/node_modules/semver/test.js | 436 + .../karma/node_modules/log4js/package.json | 52 + .../log4js/test/categoryFilter-test.js | 83 + .../log4js/test/clusteredAppender-test.js | 125 + .../log4js/test/configuration-test.js | 134 + .../log4js/test/configureNoLevels-test.js | 173 + .../log4js/test/connect-logger-test.js | 226 + .../log4js/test/consoleAppender-test.js | 33 + .../node_modules/log4js/test/date-file-test | 1 + .../log4js/test/dateFileAppender-test.js | 218 + .../log4js/test/date_format-test.js | 51 + .../node_modules/log4js/test/debug-test.js | 72 + .../log4js/test/fileAppender-test.js | 280 + .../log4js/test/gelfAppender-test.js | 259 + .../log4js/test/global-log-level-test.js | 86 + .../log4js/test/hookioAppender-test.js | 176 + .../node_modules/log4js/test/layouts-test.js | 296 + .../node_modules/log4js/test/levels-test.js | 404 + .../log4js/test/log-abspath-test.js | 75 + .../node_modules/log4js/test/log4js.json | 16 + .../log4js/test/logLevelFilter-test.js | 78 + .../node_modules/log4js/test/logger-test.js | 57 + .../node_modules/log4js/test/logging-test.js | 512 + .../log4js/test/multiprocess-test.js | 311 + .../node_modules/log4js/test/nolog-test.js | 261 + .../log4js/test/reloadConfiguration-test.js | 340 + .../log4js/test/setLevel-asymmetry-test.js | 100 + .../log4js/test/smtpAppender-test.js | 233 + .../streams/BaseRollingFileStream-test.js | 93 + .../streams/DateRollingFileStream-test.js | 227 + .../test/streams/rollingFileStream-test.js | 210 + .../test/streams/test-rolling-file-stream | 0 .../test-rolling-file-stream-write-less | 1 + .../test-rolling-file-stream-write-more | 2 + .../test-rolling-file-stream-write-more.1 | 5 + .../test-rolling-stream-with-existing-files | 2 + .../test-rolling-stream-with-existing-files.0 | 1 + .../test-rolling-stream-with-existing-files.1 | 5 + ...test-rolling-stream-with-existing-files.11 | 1 + .../test-rolling-stream-with-existing-files.2 | 1 + ...test-rolling-stream-with-existing-files.20 | 1 + .../log4js/test/with-categoryFilter.json | 23 + .../log4js/test/with-dateFile.json | 17 + .../log4js/test/with-log-rolling.json | 10 + .../log4js/test/with-logLevelFilter.json | 28 + node_modules/karma/node_modules/log4js/test0 | 0 node_modules/karma/node_modules/log4js/test1 | 0 node_modules/karma/node_modules/log4js/test2 | 0 node_modules/karma/node_modules/log4js/test3 | 0 node_modules/karma/node_modules/log4js/test4 | 0 node_modules/karma/node_modules/mime/LICENSE | 19 + .../karma/node_modules/mime/README.md | 66 + node_modules/karma/node_modules/mime/mime.js | 114 + .../karma/node_modules/mime/package.json | 36 + node_modules/karma/node_modules/mime/test.js | 84 + .../karma/node_modules/mime/types/mime.types | 1588 + .../karma/node_modules/mime/types/node.types | 77 + .../karma/node_modules/minimatch/LICENSE | 23 + .../karma/node_modules/minimatch/README.md | 218 + .../karma/node_modules/minimatch/minimatch.js | 1079 + .../node_modules/lru-cache/.npmignore | 1 + .../node_modules/lru-cache/CONTRIBUTORS | 14 + .../minimatch/node_modules/lru-cache/LICENSE | 23 + .../node_modules/lru-cache/README.md | 97 + .../node_modules/lru-cache/lib/lru-cache.js | 252 + .../node_modules/lru-cache/package.json | 33 + .../node_modules/lru-cache/test/basic.js | 369 + .../node_modules/lru-cache/test/foreach.js | 52 + .../lru-cache/test/memory-leak.js | 50 + .../minimatch/node_modules/sigmund/LICENSE | 27 + .../minimatch/node_modules/sigmund/README.md | 53 + .../minimatch/node_modules/sigmund/bench.js | 283 + .../node_modules/sigmund/package.json | 42 + .../minimatch/node_modules/sigmund/sigmund.js | 39 + .../node_modules/sigmund/test/basic.js | 24 + .../karma/node_modules/minimatch/package.json | 40 + .../node_modules/minimatch/test/basic.js | 399 + .../minimatch/test/brace-expand.js | 33 + .../node_modules/minimatch/test/caching.js | 14 + .../node_modules/minimatch/test/defaults.js | 274 + .../karma/node_modules/optimist/.travis.yml | 4 + .../karma/node_modules/optimist/LICENSE | 21 + .../node_modules/optimist/example/bool.js | 10 + .../optimist/example/boolean_double.js | 7 + .../optimist/example/boolean_single.js | 7 + .../optimist/example/default_hash.js | 8 + .../optimist/example/default_singles.js | 7 + .../node_modules/optimist/example/divide.js | 8 + .../optimist/example/line_count.js | 20 + .../optimist/example/line_count_options.js | 29 + .../optimist/example/line_count_wrap.js | 29 + .../node_modules/optimist/example/nonopt.js | 4 + .../node_modules/optimist/example/reflect.js | 2 + .../node_modules/optimist/example/short.js | 3 + .../node_modules/optimist/example/string.js | 11 + .../optimist/example/usage-options.js | 19 + .../node_modules/optimist/example/xup.js | 10 + .../karma/node_modules/optimist/index.js | 478 + .../optimist/node_modules/wordwrap/.npmignore | 1 + .../node_modules/wordwrap/README.markdown | 70 + .../node_modules/wordwrap/example/center.js | 10 + .../node_modules/wordwrap/example/meat.js | 3 + .../optimist/node_modules/wordwrap/index.js | 76 + .../node_modules/wordwrap/package.json | 45 + .../node_modules/wordwrap/test/break.js | 30 + .../node_modules/wordwrap/test/idleness.txt | 63 + .../node_modules/wordwrap/test/wrap.js | 31 + .../karma/node_modules/optimist/package.json | 46 + .../node_modules/optimist/readme.markdown | 487 + .../karma/node_modules/optimist/test/_.js | 71 + .../node_modules/optimist/test/_/argv.js | 2 + .../karma/node_modules/optimist/test/_/bin.js | 3 + .../karma/node_modules/optimist/test/parse.js | 446 + .../karma/node_modules/optimist/test/usage.js | 292 + .../karma/node_modules/q/CONTRIBUTING.md | 40 + node_modules/karma/node_modules/q/LICENSE | 19 + node_modules/karma/node_modules/q/README.md | 813 + .../q/benchmark/compare-with-callbacks.js | 71 + .../node_modules/q/benchmark/scenarios.js | 36 + .../karma/node_modules/q/package.json | 93 + node_modules/karma/node_modules/q/q.js | 1937 + node_modules/karma/node_modules/q/queue.js | 35 + .../karma/node_modules/rimraf/AUTHORS | 6 + .../karma/node_modules/rimraf/LICENSE | 23 + .../karma/node_modules/rimraf/README.md | 21 + .../karma/node_modules/rimraf/package.json | 59 + .../karma/node_modules/rimraf/rimraf.js | 132 + .../karma/node_modules/rimraf/test/run.sh | 10 + .../karma/node_modules/rimraf/test/setup.sh | 47 + .../node_modules/rimraf/test/test-async.js | 5 + .../node_modules/rimraf/test/test-sync.js | 3 + .../karma/node_modules/socket.io/.npmignore | 3 + .../karma/node_modules/socket.io/.travis.yml | 6 + .../karma/node_modules/socket.io/History.md | 325 + .../karma/node_modules/socket.io/LICENSE | 22 + .../karma/node_modules/socket.io/Makefile | 31 + .../karma/node_modules/socket.io/Readme.md | 364 + .../socket.io/benchmarks/decode.bench.js | 64 + .../socket.io/benchmarks/encode.bench.js | 90 + .../socket.io/benchmarks/runner.js | 55 + .../karma/node_modules/socket.io/index.js | 8 + .../node_modules/socket.io/lib/logger.js | 97 + .../node_modules/socket.io/lib/manager.js | 1027 + .../node_modules/socket.io/lib/namespace.js | 355 + .../node_modules/socket.io/lib/parser.js | 249 + .../node_modules/socket.io/lib/socket.io.js | 143 + .../node_modules/socket.io/lib/socket.js | 369 + .../node_modules/socket.io/lib/static.js | 395 + .../karma/node_modules/socket.io/lib/store.js | 98 + .../socket.io/lib/stores/memory.js | 143 + .../socket.io/lib/stores/redis.js | 269 + .../node_modules/socket.io/lib/transport.js | 534 + .../socket.io/lib/transports/flashsocket.js | 129 + .../socket.io/lib/transports/htmlfile.js | 83 + .../socket.io/lib/transports/http-polling.js | 147 + .../socket.io/lib/transports/http.js | 121 + .../socket.io/lib/transports/index.js | 12 + .../socket.io/lib/transports/jsonp-polling.js | 97 + .../socket.io/lib/transports/websocket.js | 36 + .../lib/transports/websocket/default.js | 362 + .../lib/transports/websocket/hybi-07-12.js | 622 + .../lib/transports/websocket/hybi-16.js | 622 + .../lib/transports/websocket/index.js | 11 + .../socket.io/lib/transports/xhr-polling.js | 69 + .../karma/node_modules/socket.io/lib/util.js | 50 + .../node_modules/base64id/.npmignore | 3 + .../socket.io/node_modules/base64id/README.md | 18 + .../node_modules/base64id/lib/base64id.js | 103 + .../node_modules/base64id/package.json | 25 + .../node_modules/policyfile/.npmignore | 1 + .../socket.io/node_modules/policyfile/LICENSE | 19 + .../node_modules/policyfile/Makefile | 7 + .../node_modules/policyfile/README.md | 98 + .../node_modules/policyfile/doc/index.html | 375 + .../policyfile/examples/basic.fallback.js | 8 + .../node_modules/policyfile/examples/basic.js | 5 + .../node_modules/policyfile/index.js | 1 + .../node_modules/policyfile/lib/server.js | 289 + .../node_modules/policyfile/package.json | 52 + .../node_modules/policyfile/tests/ssl/ssl.crt | 21 + .../policyfile/tests/ssl/ssl.private.key | 27 + .../policyfile/tests/unit.test.js | 231 + .../socket.io/node_modules/redis/.npmignore | 1 + .../socket.io/node_modules/redis/README.md | 691 + .../redis/benches/buffer_bench.js | 89 + .../redis/benches/hiredis_parser.js | 38 + .../node_modules/redis/benches/re_sub_test.js | 14 + .../redis/benches/reconnect_test.js | 29 + .../redis/benches/stress/codec.js | 16 + .../redis/benches/stress/pubsub/pub.js | 38 + .../redis/benches/stress/pubsub/run | 10 + .../redis/benches/stress/pubsub/server.js | 23 + .../redis/benches/stress/rpushblpop/pub.js | 49 + .../redis/benches/stress/rpushblpop/run | 6 + .../redis/benches/stress/rpushblpop/server.js | 30 + .../redis/benches/stress/speed/00 | 13 + .../redis/benches/stress/speed/plot | 13 + .../redis/benches/stress/speed/size-rate.png | Bin 0 -> 6672 bytes .../redis/benches/stress/speed/speed.js | 84 + .../redis/benches/sub_quit_test.js | 18 + .../socket.io/node_modules/redis/changelog.md | 219 + .../redis/diff_multi_bench_output.js | 87 + .../node_modules/redis/examples/auth.js | 5 + .../redis/examples/backpressure_drain.js | 33 + .../node_modules/redis/examples/eval.js | 9 + .../node_modules/redis/examples/extend.js | 24 + .../node_modules/redis/examples/file.js | 32 + .../node_modules/redis/examples/mget.js | 5 + .../node_modules/redis/examples/monitor.js | 10 + .../node_modules/redis/examples/multi.js | 46 + .../node_modules/redis/examples/multi2.js | 29 + .../node_modules/redis/examples/psubscribe.js | 33 + .../node_modules/redis/examples/pub_sub.js | 41 + .../node_modules/redis/examples/simple.js | 24 + .../node_modules/redis/examples/sort.js | 17 + .../node_modules/redis/examples/subqueries.js | 15 + .../node_modules/redis/examples/subquery.js | 19 + .../redis/examples/unix_socket.js | 29 + .../node_modules/redis/examples/web_server.js | 31 + .../node_modules/redis/generate_commands.js | 39 + .../socket.io/node_modules/redis/index.js | 1113 + .../node_modules/redis/lib/commands.js | 147 + .../node_modules/redis/lib/parser/hiredis.js | 46 + .../redis/lib/parser/javascript.js | 317 + .../socket.io/node_modules/redis/lib/queue.js | 61 + .../node_modules/redis/lib/to_array.js | 12 + .../socket.io/node_modules/redis/lib/util.js | 11 + .../socket.io/node_modules/redis/mem.js | 11 + .../node_modules/redis/multi_bench.js | 225 + .../socket.io/node_modules/redis/package.json | 35 + .../socket.io/node_modules/redis/test.js | 1618 + .../node_modules/socket.io-client/.npmignore | 2 + .../node_modules/socket.io-client/History.md | 237 + .../node_modules/socket.io-client/Makefile | 20 + .../node_modules/socket.io-client/README.md | 246 + .../socket.io-client/bin/builder.js | 303 + .../components/component-bind/component.json | 14 + .../components/component-bind/index.js | 24 + .../component-emitter/component.json | 13 + .../components/component-emitter/index.js | 147 + .../component-json-fallback/component.json | 15 + .../component-json-fallback/index.js | 486 + .../components/component-json/component.json | 17 + .../components/component-json/index.js | 4 + .../component.json | 24 + .../lib/emitter.js | 52 + .../learnboost-engine.io-client/lib/index.js | 2 + .../learnboost-engine.io-client/lib/parser.js | 163 + .../learnboost-engine.io-client/lib/socket.js | 492 + .../lib/transport.js | 141 + .../lib/transports/flashsocket.js | 254 + .../lib/transports/index.js | 62 + .../lib/transports/polling-jsonp.js | 221 + .../lib/transports/polling-xhr.js | 288 + .../lib/transports/polling.js | 210 + .../lib/transports/websocket.js | 158 + .../learnboost-engine.io-client/lib/util.js | 265 + .../component.json | 12 + .../learnboost-socket.io-protocol/index.js | 177 + .../timoxley-to-array/component.json | 16 + .../components/timoxley-to-array/index.js | 27 + .../visionmedia-debug/component.json | 16 + .../components/visionmedia-debug/debug.js | 122 + .../components/visionmedia-debug/index.js | 5 + .../socket.io-client/dist/WebSocketMain.swf | Bin 0 -> 175830 bytes .../dist/WebSocketMainInsecure.swf | Bin 0 -> 175953 bytes .../socket.io-client/dist/socket.io.js | 3873 + .../socket.io-client/dist/socket.io.min.js | 2 + .../socket.io-client/lib/events.js | 182 + .../node_modules/socket.io-client/lib/io.js | 206 + .../node_modules/socket.io-client/lib/json.js | 322 + .../socket.io-client/lib/namespace.js | 242 + .../socket.io-client/lib/parser.js | 262 + .../socket.io-client/lib/socket.js | 579 + .../socket.io-client/lib/transport.js | 256 + .../lib/transports/flashsocket.js | 191 + .../lib/transports/htmlfile.js | 173 + .../lib/transports/jsonp-polling.js | 256 + .../lib/transports/websocket.js | 197 + .../lib/transports/xhr-polling.js | 177 + .../socket.io-client/lib/transports/xhr.js | 217 + .../node_modules/socket.io-client/lib/util.js | 365 + .../lib/vendor/web-socket-js/.npmignore | 1 + .../lib/vendor/web-socket-js/README.md | 157 + .../vendor/web-socket-js/WebSocketMain.swf | Bin 0 -> 175830 bytes .../web-socket-js/WebSocketMainInsecure.zip | Bin 0 -> 166610 bytes .../flash-src/IWebSocketLogger.as | 8 + .../web-socket-js/flash-src/WebSocket.as | 464 + .../web-socket-js/flash-src/WebSocketEvent.as | 33 + .../web-socket-js/flash-src/WebSocketMain.as | 150 + .../flash-src/WebSocketMainInsecure.as | 19 + .../vendor/web-socket-js/flash-src/build.sh | 10 + .../com/adobe/net/proxies/RFC2817Socket.as | 204 + .../flash-src/com/gsolo/encryption/MD5.as | 375 + .../flash-src/com/hurlant/crypto/Crypto.as | 287 + .../crypto/cert/MozillaRootCertificates.as | 3235 + .../hurlant/crypto/cert/X509Certificate.as | 218 + .../crypto/cert/X509CertificateCollection.as | 57 + .../flash-src/com/hurlant/crypto/hash/HMAC.as | 82 + .../com/hurlant/crypto/hash/IHMAC.as | 27 + .../com/hurlant/crypto/hash/IHash.as | 21 + .../flash-src/com/hurlant/crypto/hash/MAC.as | 137 + .../flash-src/com/hurlant/crypto/hash/MD2.as | 124 + .../flash-src/com/hurlant/crypto/hash/MD5.as | 204 + .../flash-src/com/hurlant/crypto/hash/SHA1.as | 106 + .../com/hurlant/crypto/hash/SHA224.as | 28 + .../com/hurlant/crypto/hash/SHA256.as | 115 + .../com/hurlant/crypto/hash/SHABase.as | 71 + .../flash-src/com/hurlant/crypto/prng/ARC4.as | 90 + .../com/hurlant/crypto/prng/IPRNG.as | 20 + .../com/hurlant/crypto/prng/Random.as | 119 + .../com/hurlant/crypto/prng/TLSPRF.as | 142 + .../com/hurlant/crypto/rsa/RSAKey.as | 339 + .../com/hurlant/crypto/symmetric/AESKey.as | 2797 + .../hurlant/crypto/symmetric/BlowFishKey.as | 375 + .../com/hurlant/crypto/symmetric/CBCMode.as | 55 + .../com/hurlant/crypto/symmetric/CFB8Mode.as | 61 + .../com/hurlant/crypto/symmetric/CFBMode.as | 64 + .../com/hurlant/crypto/symmetric/CTRMode.as | 58 + .../com/hurlant/crypto/symmetric/DESKey.as | 365 + .../com/hurlant/crypto/symmetric/ECBMode.as | 86 + .../com/hurlant/crypto/symmetric/ICipher.as | 21 + .../com/hurlant/crypto/symmetric/IMode.as | 15 + .../com/hurlant/crypto/symmetric/IPad.as | 32 + .../hurlant/crypto/symmetric/IStreamCipher.as | 21 + .../hurlant/crypto/symmetric/ISymmetricKey.as | 35 + .../com/hurlant/crypto/symmetric/IVMode.as | 110 + .../com/hurlant/crypto/symmetric/NullPad.as | 34 + .../com/hurlant/crypto/symmetric/OFBMode.as | 52 + .../com/hurlant/crypto/symmetric/PKCS5.as | 44 + .../com/hurlant/crypto/symmetric/SSLPad.as | 44 + .../hurlant/crypto/symmetric/SimpleIVMode.as | 60 + .../com/hurlant/crypto/symmetric/TLSPad.as | 42 + .../hurlant/crypto/symmetric/TripleDESKey.as | 88 + .../com/hurlant/crypto/symmetric/XTeaKey.as | 94 + .../com/hurlant/crypto/symmetric/aeskey.pl | 29 + .../com/hurlant/crypto/symmetric/dump.txt | 2304 + .../com/hurlant/crypto/tests/AESKeyTest.as | 1220 + .../com/hurlant/crypto/tests/ARC4Test.as | 58 + .../hurlant/crypto/tests/BigIntegerTest.as | 39 + .../hurlant/crypto/tests/BlowFishKeyTest.as | 148 + .../com/hurlant/crypto/tests/CBCModeTest.as | 160 + .../com/hurlant/crypto/tests/CFB8ModeTest.as | 71 + .../com/hurlant/crypto/tests/CFBModeTest.as | 98 + .../com/hurlant/crypto/tests/CTRModeTest.as | 109 + .../com/hurlant/crypto/tests/DESKeyTest.as | 112 + .../com/hurlant/crypto/tests/ECBModeTest.as | 151 + .../com/hurlant/crypto/tests/HMACTest.as | 184 + .../com/hurlant/crypto/tests/ITestHarness.as | 20 + .../com/hurlant/crypto/tests/MD2Test.as | 56 + .../com/hurlant/crypto/tests/MD5Test.as | 58 + .../com/hurlant/crypto/tests/OFBModeTest.as | 101 + .../com/hurlant/crypto/tests/RSAKeyTest.as | 92 + .../com/hurlant/crypto/tests/SHA1Test.as | 198 + .../com/hurlant/crypto/tests/SHA224Test.as | 58 + .../com/hurlant/crypto/tests/SHA256Test.as | 60 + .../com/hurlant/crypto/tests/TLSPRFTest.as | 51 + .../com/hurlant/crypto/tests/TestCase.as | 42 + .../hurlant/crypto/tests/TripleDESKeyTest.as | 59 + .../com/hurlant/crypto/tests/XTeaKeyTest.as | 66 + .../com/hurlant/crypto/tls/BulkCiphers.as | 102 + .../com/hurlant/crypto/tls/CipherSuites.as | 117 + .../hurlant/crypto/tls/IConnectionState.as | 14 + .../hurlant/crypto/tls/ISecurityParameters.as | 29 + .../com/hurlant/crypto/tls/KeyExchanges.as | 24 + .../flash-src/com/hurlant/crypto/tls/MACs.as | 38 + .../hurlant/crypto/tls/SSLConnectionState.as | 171 + .../com/hurlant/crypto/tls/SSLEvent.as | 26 + .../crypto/tls/SSLSecurityParameters.as | 340 + .../com/hurlant/crypto/tls/TLSConfig.as | 70 + .../hurlant/crypto/tls/TLSConnectionState.as | 151 + .../com/hurlant/crypto/tls/TLSEngine.as | 895 + .../com/hurlant/crypto/tls/TLSError.as | 39 + .../com/hurlant/crypto/tls/TLSEvent.as | 27 + .../crypto/tls/TLSSecurityParameters.as | 197 + .../com/hurlant/crypto/tls/TLSSocket.as | 370 + .../com/hurlant/crypto/tls/TLSSocketEvent.as | 26 + .../com/hurlant/crypto/tls/TLSTest.as | 180 + .../com/hurlant/math/BarrettReduction.as | 90 + .../flash-src/com/hurlant/math/BigInteger.as | 1543 + .../com/hurlant/math/ClassicReduction.as | 35 + .../flash-src/com/hurlant/math/IReduction.as | 11 + .../com/hurlant/math/MontgomeryReduction.as | 85 + .../com/hurlant/math/NullReduction.as | 34 + .../flash-src/com/hurlant/math/bi_internal.as | 11 + .../flash-src/com/hurlant/util/ArrayUtil.as | 25 + .../flash-src/com/hurlant/util/Base64.as | 189 + .../flash-src/com/hurlant/util/Hex.as | 66 + .../flash-src/com/hurlant/util/Memory.as | 28 + .../com/hurlant/util/der/ByteString.as | 43 + .../flash-src/com/hurlant/util/der/DER.as | 210 + .../com/hurlant/util/der/IAsn1Type.as | 21 + .../flash-src/com/hurlant/util/der/Integer.as | 44 + .../flash-src/com/hurlant/util/der/OID.as | 35 + .../com/hurlant/util/der/ObjectIdentifier.as | 112 + .../flash-src/com/hurlant/util/der/PEM.as | 118 + .../com/hurlant/util/der/PrintableString.as | 49 + .../com/hurlant/util/der/Sequence.as | 90 + .../flash-src/com/hurlant/util/der/Set.as | 27 + .../flash-src/com/hurlant/util/der/Type.as | 94 + .../flash-src/com/hurlant/util/der/UTCTime.as | 60 + .../lib/vendor/web-socket-js/sample.html | 75 + .../lib/vendor/web-socket-js/swfobject.js | 6 + .../lib/vendor/web-socket-js/web_socket.js | 349 + .../node_modules/.bin/uglifyjs | 323 + .../socket.io-client/node_modules/.bin/wscat | 190 + .../active-x-obfuscator/.npmignore | 2 + .../active-x-obfuscator/Readme.md | 33 + .../node_modules/active-x-obfuscator/index.js | 83 + .../node_modules/zeparser/.npmignore | 1 + .../node_modules/zeparser/LICENSE | 19 + .../node_modules/zeparser/README | 37 + .../node_modules/zeparser/Tokenizer.js | 646 + .../node_modules/zeparser/ZeParser.js | 2180 + .../node_modules/zeparser/benchmark.html | 111608 +++++++++++++++ .../node_modules/zeparser/index.js | 1 + .../node_modules/zeparser/package.json | 27 + .../node_modules/zeparser/test-parser.html | 26 + .../node_modules/zeparser/test-tokenizer.html | 23 + .../node_modules/zeparser/tests.js | 478 + .../zeparser/unicodecategories.js | 49 + .../active-x-obfuscator/package.json | 34 + .../node_modules/active-x-obfuscator/test.js | 53 + .../node_modules/uglify-js/.npmignore | 4 + .../node_modules/uglify-js/README.html | 981 + .../node_modules/uglify-js/README.org | 574 + .../node_modules/uglify-js/bin/uglifyjs | 323 + .../node_modules/uglify-js/docstyle.css | 75 + .../node_modules/uglify-js/lib/object-ast.js | 75 + .../node_modules/uglify-js/lib/parse-js.js | 1342 + .../node_modules/uglify-js/lib/process.js | 2011 + .../uglify-js/lib/squeeze-more.js | 69 + .../node_modules/uglify-js/package.json | 26 + .../node_modules/uglify-js/package.json~ | 24 + .../node_modules/uglify-js/test/beautify.js | 28 + .../node_modules/uglify-js/test/testparser.js | 403 + .../test/unit/compress/expected/array1.js | 1 + .../test/unit/compress/expected/array2.js | 1 + .../test/unit/compress/expected/array3.js | 1 + .../test/unit/compress/expected/array4.js | 1 + .../test/unit/compress/expected/assignment.js | 1 + .../unit/compress/expected/concatstring.js | 1 + .../test/unit/compress/expected/const.js | 1 + .../unit/compress/expected/empty-blocks.js | 1 + .../unit/compress/expected/forstatement.js | 1 + .../test/unit/compress/expected/if.js | 1 + .../test/unit/compress/expected/ifreturn.js | 1 + .../test/unit/compress/expected/ifreturn2.js | 1 + .../test/unit/compress/expected/issue10.js | 1 + .../test/unit/compress/expected/issue11.js | 1 + .../test/unit/compress/expected/issue13.js | 1 + .../test/unit/compress/expected/issue14.js | 1 + .../test/unit/compress/expected/issue16.js | 1 + .../test/unit/compress/expected/issue17.js | 1 + .../test/unit/compress/expected/issue20.js | 1 + .../test/unit/compress/expected/issue21.js | 1 + .../test/unit/compress/expected/issue25.js | 1 + .../test/unit/compress/expected/issue27.js | 1 + .../test/unit/compress/expected/issue278.js | 1 + .../test/unit/compress/expected/issue28.js | 1 + .../test/unit/compress/expected/issue29.js | 1 + .../test/unit/compress/expected/issue30.js | 1 + .../test/unit/compress/expected/issue34.js | 1 + .../test/unit/compress/expected/issue4.js | 1 + .../test/unit/compress/expected/issue48.js | 1 + .../test/unit/compress/expected/issue50.js | 1 + .../test/unit/compress/expected/issue53.js | 1 + .../test/unit/compress/expected/issue54.1.js | 1 + .../test/unit/compress/expected/issue68.js | 1 + .../test/unit/compress/expected/issue69.js | 1 + .../test/unit/compress/expected/issue9.js | 1 + .../test/unit/compress/expected/mangle.js | 1 + .../unit/compress/expected/null_string.js | 1 + .../unit/compress/expected/strict-equals.js | 1 + .../test/unit/compress/expected/var.js | 1 + .../test/unit/compress/expected/whitespace.js | 1 + .../test/unit/compress/expected/with.js | 1 + .../test/unit/compress/test/array1.js | 3 + .../test/unit/compress/test/array2.js | 4 + .../test/unit/compress/test/array3.js | 4 + .../test/unit/compress/test/array4.js | 6 + .../test/unit/compress/test/assignment.js | 20 + .../test/unit/compress/test/concatstring.js | 3 + .../test/unit/compress/test/const.js | 5 + .../test/unit/compress/test/empty-blocks.js | 4 + .../test/unit/compress/test/forstatement.js | 10 + .../uglify-js/test/unit/compress/test/if.js | 6 + .../test/unit/compress/test/ifreturn.js | 9 + .../test/unit/compress/test/ifreturn2.js | 16 + .../test/unit/compress/test/issue10.js | 1 + .../test/unit/compress/test/issue11.js | 3 + .../test/unit/compress/test/issue13.js | 1 + .../test/unit/compress/test/issue14.js | 1 + .../test/unit/compress/test/issue16.js | 1 + .../test/unit/compress/test/issue17.js | 4 + .../test/unit/compress/test/issue20.js | 1 + .../test/unit/compress/test/issue21.js | 6 + .../test/unit/compress/test/issue25.js | 7 + .../test/unit/compress/test/issue27.js | 1 + .../test/unit/compress/test/issue278.js | 1 + .../test/unit/compress/test/issue28.js | 3 + .../test/unit/compress/test/issue29.js | 1 + .../test/unit/compress/test/issue30.js | 3 + .../test/unit/compress/test/issue34.js | 3 + .../test/unit/compress/test/issue4.js | 3 + .../test/unit/compress/test/issue48.js | 1 + .../test/unit/compress/test/issue50.js | 9 + .../test/unit/compress/test/issue53.js | 1 + .../test/unit/compress/test/issue54.1.js | 3 + .../test/unit/compress/test/issue68.js | 5 + .../test/unit/compress/test/issue69.js | 1 + .../test/unit/compress/test/issue9.js | 4 + .../test/unit/compress/test/mangle.js | 5 + .../test/unit/compress/test/null_string.js | 1 + .../test/unit/compress/test/strict-equals.js | 3 + .../uglify-js/test/unit/compress/test/var.js | 3 + .../test/unit/compress/test/whitespace.js | 21 + .../uglify-js/test/unit/compress/test/with.js | 2 + .../uglify-js/test/unit/scripts.js | 55 + .../node_modules/uglify-js/tmp/269.js | 13 + .../node_modules/uglify-js/tmp/app.js | 22315 +++ .../uglify-js/tmp/embed-tokens.js | 15 + .../node_modules/uglify-js/tmp/goto.js | 26 + .../node_modules/uglify-js/tmp/goto2.js | 8 + .../node_modules/uglify-js/tmp/hoist.js | 33 + .../node_modules/uglify-js/tmp/instrument.js | 97 + .../node_modules/uglify-js/tmp/instrument2.js | 138 + .../node_modules/uglify-js/tmp/liftvars.js | 8 + .../node_modules/uglify-js/tmp/test.js | 30 + .../uglify-js/tmp/uglify-hangs.js | 3930 + .../uglify-js/tmp/uglify-hangs2.js | 166 + .../node_modules/uglify-js/uglify-js.js | 17 + .../node_modules/ws/.npmignore | 6 + .../node_modules/ws/.travis.yml | 6 + .../node_modules/ws/History.md | 312 + .../socket.io-client/node_modules/ws/Makefile | 40 + .../node_modules/ws/README.md | 171 + .../node_modules/ws/bench/parser.benchmark.js | 115 + .../node_modules/ws/bench/sender.benchmark.js | 66 + .../node_modules/ws/bench/speed.js | 105 + .../node_modules/ws/bench/util.js | 105 + .../node_modules/ws/bin/wscat | 190 + .../node_modules/ws/binding.gyp | 16 + .../node_modules/ws/build/Makefile | 359 + .../Release/.deps/Release/bufferutil.node.d | 1 + .../obj.target/bufferutil/src/bufferutil.o.d | 23 + .../obj.target/validation/src/validation.o.d | 23 + .../Release/.deps/Release/validation.node.d | 1 + .../ws/build/Release/bufferutil.node | Bin 0 -> 18372 bytes .../node_modules/ws/build/Release/linker.lock | 0 .../obj.target/bufferutil/src/bufferutil.o | Bin 0 -> 81384 bytes .../obj.target/validation/src/validation.o | Bin 0 -> 78072 bytes .../ws/build/Release/validation.node | Bin 0 -> 18644 bytes .../node_modules/ws/build/binding.Makefile | 6 + .../ws/build/bufferutil.target.mk | 158 + .../node_modules/ws/build/config.gypi | 112 + .../node_modules/ws/build/gyp-mac-tool | 224 + .../ws/build/validation.target.mk | 158 + .../node_modules/ws/builderror.log | 2 + .../node_modules/ws/doc/ws.md | 181 + .../ws/examples/fileapi/.npmignore | 1 + .../ws/examples/fileapi/package.json | 18 + .../ws/examples/fileapi/public/app.js | 39 + .../ws/examples/fileapi/public/index.html | 22 + .../ws/examples/fileapi/public/uploader.js | 55 + .../ws/examples/fileapi/server.js | 103 + .../serverstats-express_3/package.json | 17 + .../serverstats-express_3/public/index.html | 33 + .../examples/serverstats-express_3/server.js | 21 + .../ws/examples/serverstats/package.json | 17 + .../ws/examples/serverstats/public/index.html | 33 + .../ws/examples/serverstats/server.js | 19 + .../node_modules/ws/examples/ssl.js | 59 + .../socket.io-client/node_modules/ws/index.js | 26 + .../node_modules/ws/lib/BufferPool.js | 59 + .../ws/lib/BufferUtil.fallback.js | 47 + .../node_modules/ws/lib/BufferUtil.js | 16 + .../node_modules/ws/lib/ErrorCodes.js | 24 + .../node_modules/ws/lib/Receiver.hixie.js | 180 + .../node_modules/ws/lib/Receiver.js | 591 + .../node_modules/ws/lib/Sender.hixie.js | 123 + .../node_modules/ws/lib/Sender.js | 227 + .../ws/lib/Validation.fallback.js | 12 + .../node_modules/ws/lib/Validation.js | 16 + .../node_modules/ws/lib/WebSocket.js | 818 + .../node_modules/ws/lib/WebSocketServer.js | 460 + .../node_modules/ws/lib/browser.js | 43 + .../ws/node_modules/commander/.npmignore | 4 + .../ws/node_modules/commander/.travis.yml | 4 + .../ws/node_modules/commander/History.md | 107 + .../ws/node_modules/commander/Makefile | 7 + .../ws/node_modules/commander/Readme.md | 262 + .../ws/node_modules/commander/index.js | 2 + .../node_modules/commander/lib/commander.js | 1026 + .../ws/node_modules/commander/package.json | 39 + .../ws/node_modules/nan/.index.js | 1 + .../node_modules/ws/node_modules/nan/LICENSE | 43 + .../ws/node_modules/nan/README.md | 705 + .../node_modules/ws/node_modules/nan/nan.h | 884 + .../ws/node_modules/nan/package.json | 36 + .../ws/node_modules/options/.npmignore | 5 + .../ws/node_modules/options/Makefile | 12 + .../ws/node_modules/options/README.md | 28 + .../ws/node_modules/options/lib/options.js | 86 + .../ws/node_modules/options/package.json | 33 + .../options/test/fixtures/test.conf | 4 + .../node_modules/options/test/options.test.js | 140 + .../ws/node_modules/tinycolor/.npmignore | 5 + .../ws/node_modules/tinycolor/README.md | 3 + .../ws/node_modules/tinycolor/example.js | 3 + .../ws/node_modules/tinycolor/package.json | 28 + .../ws/node_modules/tinycolor/tinycolor.js | 31 + .../node_modules/ws/package.json | 61 + .../node_modules/ws/src/bufferutil.cc | 117 + .../node_modules/ws/src/validation.cc | 145 + .../node_modules/ws/test/BufferPool.test.js | 63 + .../ws/test/Receiver.hixie.test.js | 158 + .../node_modules/ws/test/Receiver.test.js | 255 + .../node_modules/ws/test/Sender.hixie.test.js | 134 + .../node_modules/ws/test/Sender.test.js | 24 + .../node_modules/ws/test/Validation.test.js | 23 + .../ws/test/WebSocket.integration.js | 44 + .../node_modules/ws/test/WebSocket.test.js | 1724 + .../ws/test/WebSocketServer.test.js | 1103 + .../node_modules/ws/test/autobahn-server.js | 29 + .../node_modules/ws/test/autobahn.js | 52 + .../ws/test/fixtures/agent1-cert.pem | 16 + .../ws/test/fixtures/agent1-key.pem | 15 + .../ws/test/fixtures/ca1-cert.pem | 15 + .../node_modules/ws/test/fixtures/ca1-key.pem | 17 + .../ws/test/fixtures/certificate.pem | 13 + .../node_modules/ws/test/fixtures/key.pem | 15 + .../node_modules/ws/test/fixtures/request.pem | 11 + .../node_modules/ws/test/fixtures/textfile | 9 + .../node_modules/ws/test/hybi-common.js | 99 + .../node_modules/ws/test/testserver.js | 180 + .../node_modules/xmlhttprequest/README.md | 53 + .../xmlhttprequest/autotest.watchr | 8 + .../xmlhttprequest/example/demo.js | 16 + .../xmlhttprequest/lib/XMLHttpRequest.js | 548 + .../node_modules/xmlhttprequest/package.json | 39 + .../xmlhttprequest/tests/test-constants.js | 13 + .../xmlhttprequest/tests/test-events.js | 50 + .../xmlhttprequest/tests/test-exceptions.js | 62 + .../xmlhttprequest/tests/test-headers.js | 61 + .../tests/test-request-methods.js | 62 + .../tests/test-request-protocols.js | 34 + .../xmlhttprequest/tests/testdata.txt | 1 + .../socket.io-client/package.json | 67 + .../socket.io-client/test/events.test.js | 120 + .../socket.io-client/test/io.test.js | 31 + .../test/node/builder.common.js | 102 + .../test/node/builder.test.js | 131 + .../socket.io-client/test/parser.test.js | 360 + .../socket.io-client/test/socket.test.js | 422 + .../socket.io-client/test/util.test.js | 156 + .../socket.io-client/test/worker.js | 20 + .../karma/node_modules/socket.io/package.json | 70 + .../karma/node_modules/useragent/.npmignore | 3 + .../karma/node_modules/useragent/.travis.yml | 4 + .../karma/node_modules/useragent/CHANGELOG.md | 63 + .../karma/node_modules/useragent/CREDITS | 16 + .../karma/node_modules/useragent/LICENSE | 19 + .../karma/node_modules/useragent/README.md | 393 + .../node_modules/useragent/bin/testfiles.js | 24 + .../node_modules/useragent/bin/update.js | 17 + .../node_modules/useragent/features/index.js | 19 + .../karma/node_modules/useragent/index.js | 598 + .../node_modules/useragent/lib/regexps.js | 2270 + .../node_modules/useragent/lib/update.js | 202 + .../node_modules/lru-cache/.npmignore | 1 + .../useragent/node_modules/lru-cache/AUTHORS | 8 + .../useragent/node_modules/lru-cache/LICENSE | 23 + .../node_modules/lru-cache/README.md | 88 + .../node_modules/lru-cache/lib/lru-cache.js | 242 + .../node_modules/lru-cache/package.json | 63 + .../useragent/node_modules/lru-cache/s.js | 25 + .../node_modules/lru-cache/test/basic.js | 317 + .../node_modules/lru-cache/test/foreach.js | 52 + .../lru-cache/test/memory-leak.js | 50 + .../karma/node_modules/useragent/package.json | 69 + .../useragent/static/user_agent.after.yaml | 14 + .../useragent/test/features.test.js | 16 + .../useragent/test/fixtures/firefoxes.yaml | 1386 + .../useragent/test/fixtures/pgts.yaml | 62356 ++++++++ .../test/fixtures/static.custom.yaml | 13 + .../useragent/test/fixtures/testcases.yaml | 389 + .../node_modules/useragent/test/mocha.opts | 4 + .../node_modules/useragent/test/parser.qa.js | 45 + .../useragent/test/parser.test.js | 214 + node_modules/karma/package.json | 392 + node_modules/karma/static/client.html | 115 + node_modules/karma/static/context.html | 30 + node_modules/karma/static/debug.html | 48 + node_modules/karma/static/karma.js | 294 + node_modules/karma/test-results.xml | 27 + node_modules/karma/thesis.pdf | Bin 0 -> 689519 bytes node_modules/requirejs/README.md | 9 + node_modules/requirejs/bin/r.js | 26059 ++++ node_modules/requirejs/package.json | 39 + node_modules/requirejs/require.js | 2054 + scripts/e2e-test.bat | 11 + scripts/e2e-test.sh | 10 + scripts/test.bat | 11 + scripts/test.sh | 10 + scripts/watchr.rb | 19 + scripts/web-server.js | 244 + test/e2e/runner.html | 11 + test/e2e/scenarios.js | 45 + test/lib/angular/angular-mocks.js | 2115 + test/lib/angular/angular-scenario.js | 32287 +++++ test/lib/angular/version.txt | 1 + test/unit/controllersSpec.js | 16 + test/unit/directivesSpec.js | 19 + test/unit/filtersSpec.js | 19 + test/unit/servicesSpec.js | 14 + update-angular.sh | 15 + 3063 files changed, 579021 insertions(+), 3 deletions(-) create mode 100644 app/css/app.css create mode 100755 app/img/Logo_1x.png create mode 100755 app/img/Logo_2x.png create mode 100644 app/img/bg_full.png create mode 100644 app/img/bg_tile.png create mode 100755 app/img/icons/Arrow_1x.png create mode 100755 app/img/icons/Arrow_2x.png create mode 100755 app/img/icons/Attach_1x.png create mode 100755 app/img/icons/Attach_2x.png create mode 100755 app/img/icons/Attach_pressed_1x.png create mode 100755 app/img/icons/Attach_pressed_2x.png create mode 100755 app/img/icons/CheckIn_Recent.png create mode 100755 app/img/icons/Checks1_1x.png create mode 100644 app/img/icons/Checks1_2x.png create mode 100755 app/img/icons/Checks2_1x.png create mode 100644 app/img/icons/Checks2_2x.png create mode 100755 app/img/icons/CloseHover_1x.png create mode 100755 app/img/icons/CloseHover_2x.png create mode 100755 app/img/icons/Close_1x.png create mode 100755 app/img/icons/Close_2x.png create mode 100644 app/img/icons/DialogListGroupChatIcon@2x.png create mode 100644 app/img/icons/DialogListGroupChatIcon_Highlighted@2x.png create mode 100755 app/img/icons/DocBlue_1x.png create mode 100755 app/img/icons/DocBlue_2x.png create mode 100755 app/img/icons/DocGrey_1x.png create mode 100755 app/img/icons/DocGrey_2x.png create mode 100755 app/img/icons/Location_Active.png create mode 100755 app/img/icons/Logo_1x.png create mode 100755 app/img/icons/Logo_2x.png create mode 100755 app/img/icons/NoResults.png create mode 100755 app/img/icons/Search_1x.png create mode 100755 app/img/icons/Search_2x.png create mode 100755 app/img/icons/Smile_1x.png create mode 100755 app/img/icons/Smile_2x.png create mode 100755 app/img/icons/Smile_pressed_1x.png create mode 100755 app/img/icons/Smile_pressed_2x.png create mode 100755 app/img/icons/VideoIcon.png create mode 100644 app/img/icons/icon128.png create mode 100644 app/img/icons/icon16.png create mode 100644 app/img/placeholders/DialogListAvatarSystem@2x.png create mode 100755 app/img/placeholders/GroupAvatar1@2x.png create mode 100755 app/img/placeholders/GroupAvatar2@2x.png create mode 100755 app/img/placeholders/GroupAvatar3@2x.png create mode 100755 app/img/placeholders/GroupAvatar4@2x.png create mode 100755 app/img/placeholders/UserAvatar1@2x.png create mode 100755 app/img/placeholders/UserAvatar2@2x.png create mode 100755 app/img/placeholders/UserAvatar3@2x.png create mode 100755 app/img/placeholders/UserAvatar4@2x.png create mode 100755 app/img/placeholders/UserAvatar5@2x.png create mode 100755 app/img/placeholders/UserAvatar6@2x.png create mode 100755 app/img/placeholders/UserAvatar7@2x.png create mode 100755 app/img/placeholders/UserAvatar8@2x.png create mode 100644 app/index.html create mode 100644 app/js/app.js create mode 100644 app/js/background.js create mode 100644 app/js/controllers.js create mode 100644 app/js/directives.js create mode 100644 app/js/filters.js create mode 100644 app/js/lib/aes_worker.js create mode 100644 app/js/lib/config.js create mode 100644 app/js/lib/mtproto.js create mode 100644 app/js/lib/pq_worker.js create mode 100644 app/js/lib/sha1_worker.js create mode 100644 app/js/services.js create mode 100644 app/js/util.js create mode 100644 app/manifest.json create mode 100644 app/partials/chat_modal.html create mode 100644 app/partials/dialog.html create mode 100644 app/partials/head.html create mode 100644 app/partials/im.html create mode 100644 app/partials/login.html create mode 100644 app/partials/message.html create mode 100644 app/partials/photo_modal.html create mode 100644 app/partials/user_modal.html create mode 100644 app/partials/video_modal.html create mode 100644 app/partials/welcome.html create mode 100644 app/vendor/README.md create mode 100644 app/vendor/angular/angular-animate.js create mode 100644 app/vendor/angular/angular-animate.min.js create mode 100644 app/vendor/angular/angular-animate.min.js.map create mode 100644 app/vendor/angular/angular-cookies.js create mode 100644 app/vendor/angular/angular-cookies.min.js create mode 100644 app/vendor/angular/angular-cookies.min.js.map create mode 100644 app/vendor/angular/angular-csp.css create mode 100644 app/vendor/angular/angular-loader.js create mode 100644 app/vendor/angular/angular-loader.min.js create mode 100644 app/vendor/angular/angular-loader.min.js.map create mode 100644 app/vendor/angular/angular-resource.js create mode 100644 app/vendor/angular/angular-resource.min.js create mode 100644 app/vendor/angular/angular-resource.min.js.map create mode 100644 app/vendor/angular/angular-route.js create mode 100644 app/vendor/angular/angular-route.min.js create mode 100644 app/vendor/angular/angular-route.min.js.map create mode 100644 app/vendor/angular/angular-sanitize.js create mode 100644 app/vendor/angular/angular-sanitize.min.js create mode 100644 app/vendor/angular/angular-sanitize.min.js.map create mode 100644 app/vendor/angular/angular-touch.js create mode 100644 app/vendor/angular/angular-touch.min.js create mode 100644 app/vendor/angular/angular-touch.min.js.map create mode 100644 app/vendor/angular/angular.js create mode 100644 app/vendor/angular/angular.min.js create mode 100644 app/vendor/angular/angular.min.js.map create mode 100644 app/vendor/angular/errors.json create mode 100644 app/vendor/angular/i18n/angular-locale_af-na.js create mode 100644 app/vendor/angular/i18n/angular-locale_af-za.js create mode 100644 app/vendor/angular/i18n/angular-locale_af.js create mode 100644 app/vendor/angular/i18n/angular-locale_am-et.js create mode 100644 app/vendor/angular/i18n/angular-locale_am.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-001.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-ae.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-bh.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-dz.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-eg.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-iq.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-jo.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-kw.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-lb.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-ly.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-ma.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-om.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-qa.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-sa.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-sd.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-sy.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-tn.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar-ye.js create mode 100644 app/vendor/angular/i18n/angular-locale_ar.js create mode 100644 app/vendor/angular/i18n/angular-locale_bg-bg.js create mode 100644 app/vendor/angular/i18n/angular-locale_bg.js create mode 100644 app/vendor/angular/i18n/angular-locale_bn-bd.js create mode 100644 app/vendor/angular/i18n/angular-locale_bn-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_bn.js create mode 100644 app/vendor/angular/i18n/angular-locale_ca-ad.js create mode 100644 app/vendor/angular/i18n/angular-locale_ca-es.js create mode 100644 app/vendor/angular/i18n/angular-locale_ca.js create mode 100644 app/vendor/angular/i18n/angular-locale_cs-cz.js create mode 100644 app/vendor/angular/i18n/angular-locale_cs.js create mode 100644 app/vendor/angular/i18n/angular-locale_da-dk.js create mode 100644 app/vendor/angular/i18n/angular-locale_da.js create mode 100644 app/vendor/angular/i18n/angular-locale_de-at.js create mode 100644 app/vendor/angular/i18n/angular-locale_de-be.js create mode 100644 app/vendor/angular/i18n/angular-locale_de-ch.js create mode 100644 app/vendor/angular/i18n/angular-locale_de-de.js create mode 100644 app/vendor/angular/i18n/angular-locale_de-li.js create mode 100644 app/vendor/angular/i18n/angular-locale_de-lu.js create mode 100644 app/vendor/angular/i18n/angular-locale_de.js create mode 100644 app/vendor/angular/i18n/angular-locale_el-cy.js create mode 100644 app/vendor/angular/i18n/angular-locale_el-gr.js create mode 100644 app/vendor/angular/i18n/angular-locale_el.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-as.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-au.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-bb.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-be.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-bm.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-bw.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-bz.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-ca.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-dsrt-us.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-dsrt.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-fm.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-gb.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-gu.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-gy.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-hk.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-ie.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-iso.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-jm.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-mh.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-mp.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-mt.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-mu.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-na.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-nz.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-ph.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-pk.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-pr.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-pw.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-sg.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-tc.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-tt.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-um.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-us.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-vg.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-vi.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-za.js create mode 100644 app/vendor/angular/i18n/angular-locale_en-zw.js create mode 100644 app/vendor/angular/i18n/angular-locale_en.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-419.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-ar.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-bo.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-cl.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-co.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-cr.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-do.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-ea.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-ec.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-es.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-gq.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-gt.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-hn.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-ic.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-mx.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-ni.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-pa.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-pe.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-pr.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-py.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-sv.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-us.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-uy.js create mode 100644 app/vendor/angular/i18n/angular-locale_es-ve.js create mode 100644 app/vendor/angular/i18n/angular-locale_es.js create mode 100644 app/vendor/angular/i18n/angular-locale_et-ee.js create mode 100644 app/vendor/angular/i18n/angular-locale_et.js create mode 100644 app/vendor/angular/i18n/angular-locale_eu-es.js create mode 100644 app/vendor/angular/i18n/angular-locale_eu.js create mode 100644 app/vendor/angular/i18n/angular-locale_fa-af.js create mode 100644 app/vendor/angular/i18n/angular-locale_fa-ir.js create mode 100644 app/vendor/angular/i18n/angular-locale_fa.js create mode 100644 app/vendor/angular/i18n/angular-locale_fi-fi.js create mode 100644 app/vendor/angular/i18n/angular-locale_fi.js create mode 100644 app/vendor/angular/i18n/angular-locale_fil-ph.js create mode 100644 app/vendor/angular/i18n/angular-locale_fil.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-be.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-bf.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-bi.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-bj.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-bl.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-ca.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-cd.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-cf.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-cg.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-ch.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-ci.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-cm.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-dj.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-fr.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-ga.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-gf.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-gn.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-gp.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-gq.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-km.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-lu.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-mc.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-mf.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-mg.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-ml.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-mq.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-ne.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-re.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr-yt.js create mode 100644 app/vendor/angular/i18n/angular-locale_fr.js create mode 100644 app/vendor/angular/i18n/angular-locale_gl-es.js create mode 100644 app/vendor/angular/i18n/angular-locale_gl.js create mode 100644 app/vendor/angular/i18n/angular-locale_gsw-ch.js create mode 100644 app/vendor/angular/i18n/angular-locale_gsw.js create mode 100644 app/vendor/angular/i18n/angular-locale_gu-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_gu.js create mode 100644 app/vendor/angular/i18n/angular-locale_he-il.js create mode 100644 app/vendor/angular/i18n/angular-locale_he.js create mode 100644 app/vendor/angular/i18n/angular-locale_hi-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_hi.js create mode 100644 app/vendor/angular/i18n/angular-locale_hr-hr.js create mode 100644 app/vendor/angular/i18n/angular-locale_hr.js create mode 100644 app/vendor/angular/i18n/angular-locale_hu-hu.js create mode 100644 app/vendor/angular/i18n/angular-locale_hu.js create mode 100644 app/vendor/angular/i18n/angular-locale_id-id.js create mode 100644 app/vendor/angular/i18n/angular-locale_id.js create mode 100644 app/vendor/angular/i18n/angular-locale_in.js create mode 100644 app/vendor/angular/i18n/angular-locale_is-is.js create mode 100644 app/vendor/angular/i18n/angular-locale_is.js create mode 100644 app/vendor/angular/i18n/angular-locale_it-it.js create mode 100644 app/vendor/angular/i18n/angular-locale_it-sm.js create mode 100644 app/vendor/angular/i18n/angular-locale_it.js create mode 100644 app/vendor/angular/i18n/angular-locale_iw.js create mode 100644 app/vendor/angular/i18n/angular-locale_ja-jp.js create mode 100644 app/vendor/angular/i18n/angular-locale_ja.js create mode 100644 app/vendor/angular/i18n/angular-locale_kn-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_kn.js create mode 100644 app/vendor/angular/i18n/angular-locale_ko-kr.js create mode 100644 app/vendor/angular/i18n/angular-locale_ko.js create mode 100644 app/vendor/angular/i18n/angular-locale_ln-cd.js create mode 100644 app/vendor/angular/i18n/angular-locale_ln.js create mode 100644 app/vendor/angular/i18n/angular-locale_lt-lt.js create mode 100644 app/vendor/angular/i18n/angular-locale_lt.js create mode 100644 app/vendor/angular/i18n/angular-locale_lv-lv.js create mode 100644 app/vendor/angular/i18n/angular-locale_lv.js create mode 100644 app/vendor/angular/i18n/angular-locale_ml-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_ml.js create mode 100644 app/vendor/angular/i18n/angular-locale_mr-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_mr.js create mode 100644 app/vendor/angular/i18n/angular-locale_ms-my.js create mode 100644 app/vendor/angular/i18n/angular-locale_ms.js create mode 100644 app/vendor/angular/i18n/angular-locale_mt-mt.js create mode 100644 app/vendor/angular/i18n/angular-locale_mt.js create mode 100644 app/vendor/angular/i18n/angular-locale_nl-cw.js create mode 100644 app/vendor/angular/i18n/angular-locale_nl-nl.js create mode 100644 app/vendor/angular/i18n/angular-locale_nl-sx.js create mode 100644 app/vendor/angular/i18n/angular-locale_nl.js create mode 100644 app/vendor/angular/i18n/angular-locale_no.js create mode 100644 app/vendor/angular/i18n/angular-locale_or-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_or.js create mode 100644 app/vendor/angular/i18n/angular-locale_pl-pl.js create mode 100644 app/vendor/angular/i18n/angular-locale_pl.js create mode 100644 app/vendor/angular/i18n/angular-locale_pt-br.js create mode 100644 app/vendor/angular/i18n/angular-locale_pt-pt.js create mode 100644 app/vendor/angular/i18n/angular-locale_pt.js create mode 100644 app/vendor/angular/i18n/angular-locale_ro-ro.js create mode 100644 app/vendor/angular/i18n/angular-locale_ro.js create mode 100644 app/vendor/angular/i18n/angular-locale_ru-ru.js create mode 100644 app/vendor/angular/i18n/angular-locale_ru.js create mode 100644 app/vendor/angular/i18n/angular-locale_sk-sk.js create mode 100644 app/vendor/angular/i18n/angular-locale_sk.js create mode 100644 app/vendor/angular/i18n/angular-locale_sl-si.js create mode 100644 app/vendor/angular/i18n/angular-locale_sl.js create mode 100644 app/vendor/angular/i18n/angular-locale_sq-al.js create mode 100644 app/vendor/angular/i18n/angular-locale_sq.js create mode 100644 app/vendor/angular/i18n/angular-locale_sr-cyrl-rs.js create mode 100644 app/vendor/angular/i18n/angular-locale_sr-latn-rs.js create mode 100644 app/vendor/angular/i18n/angular-locale_sr.js create mode 100644 app/vendor/angular/i18n/angular-locale_sv-se.js create mode 100644 app/vendor/angular/i18n/angular-locale_sv.js create mode 100644 app/vendor/angular/i18n/angular-locale_sw-tz.js create mode 100644 app/vendor/angular/i18n/angular-locale_sw.js create mode 100644 app/vendor/angular/i18n/angular-locale_ta-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_ta.js create mode 100644 app/vendor/angular/i18n/angular-locale_te-in.js create mode 100644 app/vendor/angular/i18n/angular-locale_te.js create mode 100644 app/vendor/angular/i18n/angular-locale_th-th.js create mode 100644 app/vendor/angular/i18n/angular-locale_th.js create mode 100644 app/vendor/angular/i18n/angular-locale_tl.js create mode 100644 app/vendor/angular/i18n/angular-locale_tr-tr.js create mode 100644 app/vendor/angular/i18n/angular-locale_tr.js create mode 100644 app/vendor/angular/i18n/angular-locale_uk-ua.js create mode 100644 app/vendor/angular/i18n/angular-locale_uk.js create mode 100644 app/vendor/angular/i18n/angular-locale_ur-pk.js create mode 100644 app/vendor/angular/i18n/angular-locale_ur.js create mode 100644 app/vendor/angular/i18n/angular-locale_vi-vn.js create mode 100644 app/vendor/angular/i18n/angular-locale_vi.js create mode 100644 app/vendor/angular/i18n/angular-locale_zh-cn.js create mode 100644 app/vendor/angular/i18n/angular-locale_zh-hans-cn.js create mode 100644 app/vendor/angular/i18n/angular-locale_zh-hk.js create mode 100644 app/vendor/angular/i18n/angular-locale_zh-tw.js create mode 100644 app/vendor/angular/i18n/angular-locale_zh.js create mode 100644 app/vendor/angular/i18n/angular-locale_zu-za.js create mode 100644 app/vendor/angular/i18n/angular-locale_zu.js create mode 100644 app/vendor/angular/version.json create mode 100644 app/vendor/angular/version.txt create mode 100644 app/vendor/bootstrap/css/bootstrap.css create mode 100644 app/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 app/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 app/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 app/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 app/vendor/bootstrap/js/bootstrap.js create mode 100644 app/vendor/cryptoJS/THIRDPARTY_LICENSE create mode 100644 app/vendor/cryptoJS/crypto.js create mode 100644 app/vendor/gemoji/THIRDPARTY_LICENSE create mode 100755 app/vendor/gemoji/images/0023-20e3.png create mode 100755 app/vendor/gemoji/images/0023-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0030-20e3.png create mode 100755 app/vendor/gemoji/images/0030-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0031-20e3.png create mode 100755 app/vendor/gemoji/images/0031-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0032-20e3.png create mode 100755 app/vendor/gemoji/images/0032-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0033-20e3.png create mode 100755 app/vendor/gemoji/images/0033-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0034-20e3.png create mode 100755 app/vendor/gemoji/images/0034-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0035-20e3.png create mode 100755 app/vendor/gemoji/images/0035-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0036-20e3.png create mode 100755 app/vendor/gemoji/images/0036-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0037-20e3.png create mode 100755 app/vendor/gemoji/images/0037-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0038-20e3.png create mode 100755 app/vendor/gemoji/images/0038-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/0039-20e3.png create mode 100755 app/vendor/gemoji/images/0039-fe0f-20e3.png create mode 100755 app/vendor/gemoji/images/00a9.png create mode 100755 app/vendor/gemoji/images/00ae.png create mode 100755 app/vendor/gemoji/images/1f004-fe0f.png create mode 100755 app/vendor/gemoji/images/1f004.png create mode 100755 app/vendor/gemoji/images/1f0cf.png create mode 100755 app/vendor/gemoji/images/1f170.png create mode 100755 app/vendor/gemoji/images/1f171.png create mode 100755 app/vendor/gemoji/images/1f17e.png create mode 100755 app/vendor/gemoji/images/1f17f-fe0f.png create mode 100755 app/vendor/gemoji/images/1f17f.png create mode 100755 app/vendor/gemoji/images/1f18e.png create mode 100755 app/vendor/gemoji/images/1f191.png create mode 100755 app/vendor/gemoji/images/1f192.png create mode 100755 app/vendor/gemoji/images/1f193.png create mode 100755 app/vendor/gemoji/images/1f194.png create mode 100755 app/vendor/gemoji/images/1f195.png create mode 100755 app/vendor/gemoji/images/1f196.png create mode 100755 app/vendor/gemoji/images/1f197.png create mode 100755 app/vendor/gemoji/images/1f198.png create mode 100755 app/vendor/gemoji/images/1f199.png create mode 100755 app/vendor/gemoji/images/1f19a.png create mode 100755 app/vendor/gemoji/images/1f1e8-1f1f3.png create mode 100755 app/vendor/gemoji/images/1f1e9-1f1ea.png create mode 100755 app/vendor/gemoji/images/1f1ea-1f1f8.png create mode 100755 app/vendor/gemoji/images/1f1eb-1f1f7.png create mode 100755 app/vendor/gemoji/images/1f1ec-1f1e7.png create mode 100755 app/vendor/gemoji/images/1f1ee-1f1f9.png create mode 100755 app/vendor/gemoji/images/1f1ef-1f1f5.png create mode 100755 app/vendor/gemoji/images/1f1f0-1f1f7.png create mode 100755 app/vendor/gemoji/images/1f1f7-1f1fa.png create mode 100755 app/vendor/gemoji/images/1f1fa-1f1f8.png create mode 100755 app/vendor/gemoji/images/1f201.png create mode 100755 app/vendor/gemoji/images/1f202.png create mode 100755 app/vendor/gemoji/images/1f21a-fe0f.png create mode 100755 app/vendor/gemoji/images/1f21a.png create mode 100755 app/vendor/gemoji/images/1f22f-fe0f.png create mode 100755 app/vendor/gemoji/images/1f22f.png create mode 100755 app/vendor/gemoji/images/1f232.png create mode 100755 app/vendor/gemoji/images/1f233.png create mode 100755 app/vendor/gemoji/images/1f234.png create mode 100755 app/vendor/gemoji/images/1f235.png create mode 100755 app/vendor/gemoji/images/1f236.png create mode 100755 app/vendor/gemoji/images/1f237.png create mode 100755 app/vendor/gemoji/images/1f238.png create mode 100755 app/vendor/gemoji/images/1f239.png create mode 100755 app/vendor/gemoji/images/1f23a.png create mode 100755 app/vendor/gemoji/images/1f250.png create mode 100755 app/vendor/gemoji/images/1f251.png create mode 100755 app/vendor/gemoji/images/1f300.png create mode 100755 app/vendor/gemoji/images/1f301.png create mode 100755 app/vendor/gemoji/images/1f302.png create mode 100755 app/vendor/gemoji/images/1f303.png create mode 100755 app/vendor/gemoji/images/1f304.png create mode 100755 app/vendor/gemoji/images/1f305.png create mode 100755 app/vendor/gemoji/images/1f306.png create mode 100755 app/vendor/gemoji/images/1f307.png create mode 100755 app/vendor/gemoji/images/1f308.png create mode 100755 app/vendor/gemoji/images/1f309.png create mode 100755 app/vendor/gemoji/images/1f30a.png create mode 100755 app/vendor/gemoji/images/1f30b.png create mode 100755 app/vendor/gemoji/images/1f30c.png create mode 100755 app/vendor/gemoji/images/1f30d.png create mode 100755 app/vendor/gemoji/images/1f30e.png create mode 100755 app/vendor/gemoji/images/1f30f.png create mode 100755 app/vendor/gemoji/images/1f310.png create mode 100755 app/vendor/gemoji/images/1f311.png create mode 100755 app/vendor/gemoji/images/1f312.png create mode 100755 app/vendor/gemoji/images/1f313.png create mode 100755 app/vendor/gemoji/images/1f314.png create mode 100755 app/vendor/gemoji/images/1f315.png create mode 100755 app/vendor/gemoji/images/1f316.png create mode 100755 app/vendor/gemoji/images/1f317.png create mode 100755 app/vendor/gemoji/images/1f318.png create mode 100755 app/vendor/gemoji/images/1f319.png create mode 100755 app/vendor/gemoji/images/1f31a.png create mode 100755 app/vendor/gemoji/images/1f31b.png create mode 100755 app/vendor/gemoji/images/1f31c.png create mode 100755 app/vendor/gemoji/images/1f31d.png create mode 100755 app/vendor/gemoji/images/1f31e.png create mode 100755 app/vendor/gemoji/images/1f31f.png create mode 100755 app/vendor/gemoji/images/1f320.png create mode 100755 app/vendor/gemoji/images/1f330.png create mode 100755 app/vendor/gemoji/images/1f331.png create mode 100755 app/vendor/gemoji/images/1f332.png create mode 100755 app/vendor/gemoji/images/1f333.png create mode 100755 app/vendor/gemoji/images/1f334.png create mode 100755 app/vendor/gemoji/images/1f335.png create mode 100755 app/vendor/gemoji/images/1f337.png create mode 100755 app/vendor/gemoji/images/1f338.png create mode 100755 app/vendor/gemoji/images/1f339.png create mode 100755 app/vendor/gemoji/images/1f33a.png create mode 100755 app/vendor/gemoji/images/1f33b.png create mode 100755 app/vendor/gemoji/images/1f33c.png create mode 100755 app/vendor/gemoji/images/1f33d.png create mode 100755 app/vendor/gemoji/images/1f33e.png create mode 100755 app/vendor/gemoji/images/1f33f.png create mode 100755 app/vendor/gemoji/images/1f340.png create mode 100755 app/vendor/gemoji/images/1f341.png create mode 100755 app/vendor/gemoji/images/1f342.png create mode 100755 app/vendor/gemoji/images/1f343.png create mode 100755 app/vendor/gemoji/images/1f344.png create mode 100755 app/vendor/gemoji/images/1f345.png create mode 100755 app/vendor/gemoji/images/1f346.png create mode 100755 app/vendor/gemoji/images/1f347.png create mode 100755 app/vendor/gemoji/images/1f348.png create mode 100755 app/vendor/gemoji/images/1f349.png create mode 100755 app/vendor/gemoji/images/1f34a.png create mode 100755 app/vendor/gemoji/images/1f34b.png create mode 100755 app/vendor/gemoji/images/1f34c.png create mode 100755 app/vendor/gemoji/images/1f34d.png create mode 100755 app/vendor/gemoji/images/1f34e.png create mode 100755 app/vendor/gemoji/images/1f34f.png create mode 100755 app/vendor/gemoji/images/1f350.png create mode 100755 app/vendor/gemoji/images/1f351.png create mode 100755 app/vendor/gemoji/images/1f352.png create mode 100755 app/vendor/gemoji/images/1f353.png create mode 100755 app/vendor/gemoji/images/1f354.png create mode 100755 app/vendor/gemoji/images/1f355.png create mode 100755 app/vendor/gemoji/images/1f356.png create mode 100755 app/vendor/gemoji/images/1f357.png create mode 100755 app/vendor/gemoji/images/1f358.png create mode 100755 app/vendor/gemoji/images/1f359.png create mode 100755 app/vendor/gemoji/images/1f35a.png create mode 100755 app/vendor/gemoji/images/1f35b.png create mode 100755 app/vendor/gemoji/images/1f35c.png create mode 100755 app/vendor/gemoji/images/1f35d.png create mode 100755 app/vendor/gemoji/images/1f35e.png create mode 100755 app/vendor/gemoji/images/1f35f.png create mode 100755 app/vendor/gemoji/images/1f360.png create mode 100755 app/vendor/gemoji/images/1f361.png create mode 100755 app/vendor/gemoji/images/1f362.png create mode 100755 app/vendor/gemoji/images/1f363.png create mode 100755 app/vendor/gemoji/images/1f364.png create mode 100755 app/vendor/gemoji/images/1f365.png create mode 100755 app/vendor/gemoji/images/1f366.png create mode 100755 app/vendor/gemoji/images/1f367.png create mode 100755 app/vendor/gemoji/images/1f368.png create mode 100755 app/vendor/gemoji/images/1f369.png create mode 100755 app/vendor/gemoji/images/1f36a.png create mode 100755 app/vendor/gemoji/images/1f36b.png create mode 100755 app/vendor/gemoji/images/1f36c.png create mode 100755 app/vendor/gemoji/images/1f36d.png create mode 100755 app/vendor/gemoji/images/1f36e.png create mode 100755 app/vendor/gemoji/images/1f36f.png create mode 100755 app/vendor/gemoji/images/1f370.png create mode 100755 app/vendor/gemoji/images/1f371.png create mode 100755 app/vendor/gemoji/images/1f372.png create mode 100755 app/vendor/gemoji/images/1f373.png create mode 100755 app/vendor/gemoji/images/1f374.png create mode 100755 app/vendor/gemoji/images/1f375.png create mode 100755 app/vendor/gemoji/images/1f376.png create mode 100755 app/vendor/gemoji/images/1f377.png create mode 100755 app/vendor/gemoji/images/1f378.png create mode 100755 app/vendor/gemoji/images/1f379.png create mode 100755 app/vendor/gemoji/images/1f37a.png create mode 100755 app/vendor/gemoji/images/1f37b.png create mode 100755 app/vendor/gemoji/images/1f37c.png create mode 100755 app/vendor/gemoji/images/1f380.png create mode 100755 app/vendor/gemoji/images/1f381.png create mode 100755 app/vendor/gemoji/images/1f382.png create mode 100755 app/vendor/gemoji/images/1f383.png create mode 100755 app/vendor/gemoji/images/1f384.png create mode 100755 app/vendor/gemoji/images/1f385.png create mode 100755 app/vendor/gemoji/images/1f386.png create mode 100755 app/vendor/gemoji/images/1f387.png create mode 100755 app/vendor/gemoji/images/1f388.png create mode 100755 app/vendor/gemoji/images/1f389.png create mode 100755 app/vendor/gemoji/images/1f38a.png create mode 100755 app/vendor/gemoji/images/1f38b.png create mode 100755 app/vendor/gemoji/images/1f38c.png create mode 100755 app/vendor/gemoji/images/1f38d.png create mode 100755 app/vendor/gemoji/images/1f38e.png create mode 100755 app/vendor/gemoji/images/1f38f.png create mode 100755 app/vendor/gemoji/images/1f390.png create mode 100755 app/vendor/gemoji/images/1f391.png create mode 100755 app/vendor/gemoji/images/1f392.png create mode 100755 app/vendor/gemoji/images/1f393.png create mode 100755 app/vendor/gemoji/images/1f3a0.png create mode 100755 app/vendor/gemoji/images/1f3a1.png create mode 100755 app/vendor/gemoji/images/1f3a2.png create mode 100755 app/vendor/gemoji/images/1f3a3.png create mode 100755 app/vendor/gemoji/images/1f3a4.png create mode 100755 app/vendor/gemoji/images/1f3a5.png create mode 100755 app/vendor/gemoji/images/1f3a6.png create mode 100755 app/vendor/gemoji/images/1f3a7.png create mode 100755 app/vendor/gemoji/images/1f3a8.png create mode 100755 app/vendor/gemoji/images/1f3a9.png create mode 100755 app/vendor/gemoji/images/1f3aa.png create mode 100755 app/vendor/gemoji/images/1f3ab.png create mode 100755 app/vendor/gemoji/images/1f3ac.png create mode 100755 app/vendor/gemoji/images/1f3ad.png create mode 100755 app/vendor/gemoji/images/1f3ae.png create mode 100755 app/vendor/gemoji/images/1f3af.png create mode 100755 app/vendor/gemoji/images/1f3b0.png create mode 100755 app/vendor/gemoji/images/1f3b1.png create mode 100755 app/vendor/gemoji/images/1f3b2.png create mode 100755 app/vendor/gemoji/images/1f3b3.png create mode 100755 app/vendor/gemoji/images/1f3b4.png create mode 100755 app/vendor/gemoji/images/1f3b5.png create mode 100755 app/vendor/gemoji/images/1f3b6.png create mode 100755 app/vendor/gemoji/images/1f3b7.png create mode 100755 app/vendor/gemoji/images/1f3b8.png create mode 100755 app/vendor/gemoji/images/1f3b9.png create mode 100755 app/vendor/gemoji/images/1f3ba.png create mode 100755 app/vendor/gemoji/images/1f3bb.png create mode 100755 app/vendor/gemoji/images/1f3bc.png create mode 100755 app/vendor/gemoji/images/1f3bd.png create mode 100755 app/vendor/gemoji/images/1f3be.png create mode 100755 app/vendor/gemoji/images/1f3bf.png create mode 100755 app/vendor/gemoji/images/1f3c0.png create mode 100755 app/vendor/gemoji/images/1f3c1.png create mode 100755 app/vendor/gemoji/images/1f3c2.png create mode 100755 app/vendor/gemoji/images/1f3c3.png create mode 100755 app/vendor/gemoji/images/1f3c4.png create mode 100755 app/vendor/gemoji/images/1f3c6.png create mode 100755 app/vendor/gemoji/images/1f3c7.png create mode 100755 app/vendor/gemoji/images/1f3c8.png create mode 100755 app/vendor/gemoji/images/1f3c9.png create mode 100755 app/vendor/gemoji/images/1f3ca.png create mode 100755 app/vendor/gemoji/images/1f3e0.png create mode 100755 app/vendor/gemoji/images/1f3e1.png create mode 100755 app/vendor/gemoji/images/1f3e2.png create mode 100755 app/vendor/gemoji/images/1f3e3.png create mode 100755 app/vendor/gemoji/images/1f3e4.png create mode 100755 app/vendor/gemoji/images/1f3e5.png create mode 100755 app/vendor/gemoji/images/1f3e6.png create mode 100755 app/vendor/gemoji/images/1f3e7.png create mode 100755 app/vendor/gemoji/images/1f3e8.png create mode 100755 app/vendor/gemoji/images/1f3e9.png create mode 100755 app/vendor/gemoji/images/1f3ea.png create mode 100755 app/vendor/gemoji/images/1f3eb.png create mode 100755 app/vendor/gemoji/images/1f3ec.png create mode 100755 app/vendor/gemoji/images/1f3ed.png create mode 100755 app/vendor/gemoji/images/1f3ee.png create mode 100755 app/vendor/gemoji/images/1f3ef.png create mode 100755 app/vendor/gemoji/images/1f3f0.png create mode 100755 app/vendor/gemoji/images/1f400.png create mode 100755 app/vendor/gemoji/images/1f401.png create mode 100755 app/vendor/gemoji/images/1f402.png create mode 100755 app/vendor/gemoji/images/1f403.png create mode 100755 app/vendor/gemoji/images/1f404.png create mode 100755 app/vendor/gemoji/images/1f405.png create mode 100755 app/vendor/gemoji/images/1f406.png create mode 100755 app/vendor/gemoji/images/1f407.png create mode 100755 app/vendor/gemoji/images/1f408.png create mode 100755 app/vendor/gemoji/images/1f409.png create mode 100755 app/vendor/gemoji/images/1f40a.png create mode 100755 app/vendor/gemoji/images/1f40b.png create mode 100755 app/vendor/gemoji/images/1f40c.png create mode 100755 app/vendor/gemoji/images/1f40d.png create mode 100755 app/vendor/gemoji/images/1f40e.png create mode 100755 app/vendor/gemoji/images/1f40f.png create mode 100755 app/vendor/gemoji/images/1f410.png create mode 100755 app/vendor/gemoji/images/1f411.png create mode 100755 app/vendor/gemoji/images/1f412.png create mode 100755 app/vendor/gemoji/images/1f413.png create mode 100755 app/vendor/gemoji/images/1f414.png create mode 100755 app/vendor/gemoji/images/1f415.png create mode 100755 app/vendor/gemoji/images/1f416.png create mode 100755 app/vendor/gemoji/images/1f417.png create mode 100755 app/vendor/gemoji/images/1f418.png create mode 100755 app/vendor/gemoji/images/1f419.png create mode 100755 app/vendor/gemoji/images/1f41a.png create mode 100755 app/vendor/gemoji/images/1f41b.png create mode 100755 app/vendor/gemoji/images/1f41c.png create mode 100755 app/vendor/gemoji/images/1f41d.png create mode 100755 app/vendor/gemoji/images/1f41e.png create mode 100755 app/vendor/gemoji/images/1f41f.png create mode 100755 app/vendor/gemoji/images/1f420.png create mode 100755 app/vendor/gemoji/images/1f421.png create mode 100755 app/vendor/gemoji/images/1f422.png create mode 100755 app/vendor/gemoji/images/1f423.png create mode 100755 app/vendor/gemoji/images/1f424.png create mode 100755 app/vendor/gemoji/images/1f425.png create mode 100755 app/vendor/gemoji/images/1f426.png create mode 100755 app/vendor/gemoji/images/1f427.png create mode 100755 app/vendor/gemoji/images/1f428.png create mode 100755 app/vendor/gemoji/images/1f429.png create mode 100755 app/vendor/gemoji/images/1f42a.png create mode 100755 app/vendor/gemoji/images/1f42b.png create mode 100755 app/vendor/gemoji/images/1f42c.png create mode 100755 app/vendor/gemoji/images/1f42d.png create mode 100755 app/vendor/gemoji/images/1f42e.png create mode 100755 app/vendor/gemoji/images/1f42f.png create mode 100755 app/vendor/gemoji/images/1f430.png create mode 100755 app/vendor/gemoji/images/1f431.png create mode 100755 app/vendor/gemoji/images/1f432.png create mode 100755 app/vendor/gemoji/images/1f433.png create mode 100755 app/vendor/gemoji/images/1f434.png create mode 100755 app/vendor/gemoji/images/1f435.png create mode 100755 app/vendor/gemoji/images/1f436.png create mode 100755 app/vendor/gemoji/images/1f437.png create mode 100755 app/vendor/gemoji/images/1f438.png create mode 100755 app/vendor/gemoji/images/1f439.png create mode 100755 app/vendor/gemoji/images/1f43a.png create mode 100755 app/vendor/gemoji/images/1f43b.png create mode 100755 app/vendor/gemoji/images/1f43c.png create mode 100755 app/vendor/gemoji/images/1f43d.png create mode 100755 app/vendor/gemoji/images/1f43e.png create mode 100755 app/vendor/gemoji/images/1f440.png create mode 100755 app/vendor/gemoji/images/1f442.png create mode 100755 app/vendor/gemoji/images/1f443.png create mode 100755 app/vendor/gemoji/images/1f444.png create mode 100755 app/vendor/gemoji/images/1f445.png create mode 100755 app/vendor/gemoji/images/1f446.png create mode 100755 app/vendor/gemoji/images/1f447.png create mode 100755 app/vendor/gemoji/images/1f448.png create mode 100755 app/vendor/gemoji/images/1f449.png create mode 100755 app/vendor/gemoji/images/1f44a.png create mode 100755 app/vendor/gemoji/images/1f44b.png create mode 100755 app/vendor/gemoji/images/1f44c.png create mode 100755 app/vendor/gemoji/images/1f44d.png create mode 100755 app/vendor/gemoji/images/1f44e.png create mode 100755 app/vendor/gemoji/images/1f44f.png create mode 100755 app/vendor/gemoji/images/1f450.png create mode 100755 app/vendor/gemoji/images/1f451.png create mode 100755 app/vendor/gemoji/images/1f452.png create mode 100755 app/vendor/gemoji/images/1f453.png create mode 100755 app/vendor/gemoji/images/1f454.png create mode 100755 app/vendor/gemoji/images/1f455.png create mode 100755 app/vendor/gemoji/images/1f456.png create mode 100755 app/vendor/gemoji/images/1f457.png create mode 100755 app/vendor/gemoji/images/1f458.png create mode 100755 app/vendor/gemoji/images/1f459.png create mode 100755 app/vendor/gemoji/images/1f45a.png create mode 100755 app/vendor/gemoji/images/1f45b.png create mode 100755 app/vendor/gemoji/images/1f45c.png create mode 100755 app/vendor/gemoji/images/1f45d.png create mode 100755 app/vendor/gemoji/images/1f45e.png create mode 100755 app/vendor/gemoji/images/1f45f.png create mode 100755 app/vendor/gemoji/images/1f460.png create mode 100755 app/vendor/gemoji/images/1f461.png create mode 100755 app/vendor/gemoji/images/1f462.png create mode 100755 app/vendor/gemoji/images/1f463.png create mode 100755 app/vendor/gemoji/images/1f464.png create mode 100755 app/vendor/gemoji/images/1f465.png create mode 100755 app/vendor/gemoji/images/1f466.png create mode 100755 app/vendor/gemoji/images/1f467.png create mode 100755 app/vendor/gemoji/images/1f468.png create mode 100755 app/vendor/gemoji/images/1f469.png create mode 100755 app/vendor/gemoji/images/1f46a.png create mode 100755 app/vendor/gemoji/images/1f46b.png create mode 100755 app/vendor/gemoji/images/1f46c.png create mode 100755 app/vendor/gemoji/images/1f46d.png create mode 100755 app/vendor/gemoji/images/1f46e.png create mode 100755 app/vendor/gemoji/images/1f46f.png create mode 100755 app/vendor/gemoji/images/1f470.png create mode 100755 app/vendor/gemoji/images/1f471.png create mode 100755 app/vendor/gemoji/images/1f472.png create mode 100755 app/vendor/gemoji/images/1f473.png create mode 100755 app/vendor/gemoji/images/1f474.png create mode 100755 app/vendor/gemoji/images/1f475.png create mode 100755 app/vendor/gemoji/images/1f476.png create mode 100755 app/vendor/gemoji/images/1f477.png create mode 100755 app/vendor/gemoji/images/1f478.png create mode 100755 app/vendor/gemoji/images/1f479.png create mode 100755 app/vendor/gemoji/images/1f47a.png create mode 100755 app/vendor/gemoji/images/1f47b.png create mode 100755 app/vendor/gemoji/images/1f47c.png create mode 100755 app/vendor/gemoji/images/1f47d.png create mode 100755 app/vendor/gemoji/images/1f47e.png create mode 100755 app/vendor/gemoji/images/1f47f.png create mode 100755 app/vendor/gemoji/images/1f480.png create mode 100755 app/vendor/gemoji/images/1f481.png create mode 100755 app/vendor/gemoji/images/1f482.png create mode 100755 app/vendor/gemoji/images/1f483.png create mode 100755 app/vendor/gemoji/images/1f484.png create mode 100755 app/vendor/gemoji/images/1f485.png create mode 100755 app/vendor/gemoji/images/1f486.png create mode 100755 app/vendor/gemoji/images/1f487.png create mode 100755 app/vendor/gemoji/images/1f488.png create mode 100755 app/vendor/gemoji/images/1f489.png create mode 100755 app/vendor/gemoji/images/1f48a.png create mode 100755 app/vendor/gemoji/images/1f48b.png create mode 100755 app/vendor/gemoji/images/1f48c.png create mode 100755 app/vendor/gemoji/images/1f48d.png create mode 100755 app/vendor/gemoji/images/1f48e.png create mode 100755 app/vendor/gemoji/images/1f48f.png create mode 100755 app/vendor/gemoji/images/1f490.png create mode 100755 app/vendor/gemoji/images/1f491.png create mode 100755 app/vendor/gemoji/images/1f492.png create mode 100755 app/vendor/gemoji/images/1f493.png create mode 100755 app/vendor/gemoji/images/1f494.png create mode 100755 app/vendor/gemoji/images/1f495.png create mode 100755 app/vendor/gemoji/images/1f496.png create mode 100755 app/vendor/gemoji/images/1f497.png create mode 100755 app/vendor/gemoji/images/1f498.png create mode 100755 app/vendor/gemoji/images/1f499.png create mode 100755 app/vendor/gemoji/images/1f49a.png create mode 100755 app/vendor/gemoji/images/1f49b.png create mode 100755 app/vendor/gemoji/images/1f49c.png create mode 100755 app/vendor/gemoji/images/1f49d.png create mode 100755 app/vendor/gemoji/images/1f49e.png create mode 100755 app/vendor/gemoji/images/1f49f.png create mode 100755 app/vendor/gemoji/images/1f4a0.png create mode 100755 app/vendor/gemoji/images/1f4a1.png create mode 100755 app/vendor/gemoji/images/1f4a2.png create mode 100755 app/vendor/gemoji/images/1f4a3.png create mode 100755 app/vendor/gemoji/images/1f4a4.png create mode 100755 app/vendor/gemoji/images/1f4a5.png create mode 100755 app/vendor/gemoji/images/1f4a6.png create mode 100755 app/vendor/gemoji/images/1f4a7.png create mode 100755 app/vendor/gemoji/images/1f4a8.png create mode 100755 app/vendor/gemoji/images/1f4a9.png create mode 100755 app/vendor/gemoji/images/1f4aa.png create mode 100755 app/vendor/gemoji/images/1f4ab.png create mode 100755 app/vendor/gemoji/images/1f4ac.png create mode 100755 app/vendor/gemoji/images/1f4ad.png create mode 100755 app/vendor/gemoji/images/1f4ae.png create mode 100755 app/vendor/gemoji/images/1f4af.png create mode 100755 app/vendor/gemoji/images/1f4b0.png create mode 100755 app/vendor/gemoji/images/1f4b1.png create mode 100755 app/vendor/gemoji/images/1f4b2.png create mode 100755 app/vendor/gemoji/images/1f4b3.png create mode 100755 app/vendor/gemoji/images/1f4b4.png create mode 100755 app/vendor/gemoji/images/1f4b5.png create mode 100755 app/vendor/gemoji/images/1f4b6.png create mode 100755 app/vendor/gemoji/images/1f4b7.png create mode 100755 app/vendor/gemoji/images/1f4b8.png create mode 100755 app/vendor/gemoji/images/1f4b9.png create mode 100755 app/vendor/gemoji/images/1f4ba.png create mode 100755 app/vendor/gemoji/images/1f4bb.png create mode 100755 app/vendor/gemoji/images/1f4bc.png create mode 100755 app/vendor/gemoji/images/1f4bd.png create mode 100755 app/vendor/gemoji/images/1f4be.png create mode 100755 app/vendor/gemoji/images/1f4bf.png create mode 100755 app/vendor/gemoji/images/1f4c0.png create mode 100755 app/vendor/gemoji/images/1f4c1.png create mode 100755 app/vendor/gemoji/images/1f4c2.png create mode 100755 app/vendor/gemoji/images/1f4c3.png create mode 100755 app/vendor/gemoji/images/1f4c4.png create mode 100755 app/vendor/gemoji/images/1f4c5.png create mode 100755 app/vendor/gemoji/images/1f4c6.png create mode 100755 app/vendor/gemoji/images/1f4c7.png create mode 100755 app/vendor/gemoji/images/1f4c8.png create mode 100755 app/vendor/gemoji/images/1f4c9.png create mode 100755 app/vendor/gemoji/images/1f4ca.png create mode 100755 app/vendor/gemoji/images/1f4cb.png create mode 100755 app/vendor/gemoji/images/1f4cc.png create mode 100755 app/vendor/gemoji/images/1f4cd.png create mode 100755 app/vendor/gemoji/images/1f4ce.png create mode 100755 app/vendor/gemoji/images/1f4cf.png create mode 100755 app/vendor/gemoji/images/1f4d0.png create mode 100755 app/vendor/gemoji/images/1f4d1.png create mode 100755 app/vendor/gemoji/images/1f4d2.png create mode 100755 app/vendor/gemoji/images/1f4d3.png create mode 100755 app/vendor/gemoji/images/1f4d4.png create mode 100755 app/vendor/gemoji/images/1f4d5.png create mode 100755 app/vendor/gemoji/images/1f4d6.png create mode 100755 app/vendor/gemoji/images/1f4d7.png create mode 100755 app/vendor/gemoji/images/1f4d8.png create mode 100755 app/vendor/gemoji/images/1f4d9.png create mode 100755 app/vendor/gemoji/images/1f4da.png create mode 100755 app/vendor/gemoji/images/1f4db.png create mode 100755 app/vendor/gemoji/images/1f4dc.png create mode 100755 app/vendor/gemoji/images/1f4dd.png create mode 100755 app/vendor/gemoji/images/1f4de.png create mode 100755 app/vendor/gemoji/images/1f4df.png create mode 100755 app/vendor/gemoji/images/1f4e0.png create mode 100755 app/vendor/gemoji/images/1f4e1.png create mode 100755 app/vendor/gemoji/images/1f4e2.png create mode 100755 app/vendor/gemoji/images/1f4e3.png create mode 100755 app/vendor/gemoji/images/1f4e4.png create mode 100755 app/vendor/gemoji/images/1f4e5.png create mode 100755 app/vendor/gemoji/images/1f4e6.png create mode 100755 app/vendor/gemoji/images/1f4e7.png create mode 100755 app/vendor/gemoji/images/1f4e8.png create mode 100755 app/vendor/gemoji/images/1f4e9.png create mode 100755 app/vendor/gemoji/images/1f4ea.png create mode 100755 app/vendor/gemoji/images/1f4eb.png create mode 100755 app/vendor/gemoji/images/1f4ec.png create mode 100755 app/vendor/gemoji/images/1f4ed.png create mode 100755 app/vendor/gemoji/images/1f4ee.png create mode 100755 app/vendor/gemoji/images/1f4ef.png create mode 100755 app/vendor/gemoji/images/1f4f0.png create mode 100755 app/vendor/gemoji/images/1f4f1.png create mode 100755 app/vendor/gemoji/images/1f4f2.png create mode 100755 app/vendor/gemoji/images/1f4f3.png create mode 100755 app/vendor/gemoji/images/1f4f4.png create mode 100755 app/vendor/gemoji/images/1f4f5.png create mode 100755 app/vendor/gemoji/images/1f4f6.png create mode 100755 app/vendor/gemoji/images/1f4f7.png create mode 100755 app/vendor/gemoji/images/1f4f9.png create mode 100755 app/vendor/gemoji/images/1f4fa.png create mode 100755 app/vendor/gemoji/images/1f4fb.png create mode 100755 app/vendor/gemoji/images/1f4fc.png create mode 100755 app/vendor/gemoji/images/1f500.png create mode 100755 app/vendor/gemoji/images/1f501.png create mode 100755 app/vendor/gemoji/images/1f502.png create mode 100755 app/vendor/gemoji/images/1f503.png create mode 100755 app/vendor/gemoji/images/1f504.png create mode 100755 app/vendor/gemoji/images/1f505.png create mode 100755 app/vendor/gemoji/images/1f506.png create mode 100755 app/vendor/gemoji/images/1f507.png create mode 100755 app/vendor/gemoji/images/1f508.png create mode 100755 app/vendor/gemoji/images/1f509.png create mode 100755 app/vendor/gemoji/images/1f50a.png create mode 100755 app/vendor/gemoji/images/1f50b.png create mode 100755 app/vendor/gemoji/images/1f50c.png create mode 100755 app/vendor/gemoji/images/1f50d.png create mode 100755 app/vendor/gemoji/images/1f50e.png create mode 100755 app/vendor/gemoji/images/1f50f.png create mode 100755 app/vendor/gemoji/images/1f510.png create mode 100755 app/vendor/gemoji/images/1f511.png create mode 100755 app/vendor/gemoji/images/1f512.png create mode 100755 app/vendor/gemoji/images/1f513.png create mode 100755 app/vendor/gemoji/images/1f514.png create mode 100755 app/vendor/gemoji/images/1f515.png create mode 100755 app/vendor/gemoji/images/1f516.png create mode 100755 app/vendor/gemoji/images/1f517.png create mode 100755 app/vendor/gemoji/images/1f518.png create mode 100755 app/vendor/gemoji/images/1f519.png create mode 100755 app/vendor/gemoji/images/1f51a.png create mode 100755 app/vendor/gemoji/images/1f51b.png create mode 100755 app/vendor/gemoji/images/1f51c.png create mode 100755 app/vendor/gemoji/images/1f51d.png create mode 100755 app/vendor/gemoji/images/1f51e.png create mode 100755 app/vendor/gemoji/images/1f51f.png create mode 100755 app/vendor/gemoji/images/1f520.png create mode 100755 app/vendor/gemoji/images/1f521.png create mode 100755 app/vendor/gemoji/images/1f522.png create mode 100755 app/vendor/gemoji/images/1f523.png create mode 100755 app/vendor/gemoji/images/1f524.png create mode 100755 app/vendor/gemoji/images/1f525.png create mode 100755 app/vendor/gemoji/images/1f526.png create mode 100755 app/vendor/gemoji/images/1f527.png create mode 100755 app/vendor/gemoji/images/1f528.png create mode 100755 app/vendor/gemoji/images/1f529.png create mode 100755 app/vendor/gemoji/images/1f52a.png create mode 100755 app/vendor/gemoji/images/1f52b.png create mode 100755 app/vendor/gemoji/images/1f52c.png create mode 100755 app/vendor/gemoji/images/1f52d.png create mode 100755 app/vendor/gemoji/images/1f52e.png create mode 100755 app/vendor/gemoji/images/1f52f.png create mode 100755 app/vendor/gemoji/images/1f530.png create mode 100755 app/vendor/gemoji/images/1f531.png create mode 100755 app/vendor/gemoji/images/1f532.png create mode 100755 app/vendor/gemoji/images/1f533.png create mode 100755 app/vendor/gemoji/images/1f534.png create mode 100755 app/vendor/gemoji/images/1f535.png create mode 100755 app/vendor/gemoji/images/1f536.png create mode 100755 app/vendor/gemoji/images/1f537.png create mode 100755 app/vendor/gemoji/images/1f538.png create mode 100755 app/vendor/gemoji/images/1f539.png create mode 100755 app/vendor/gemoji/images/1f53a.png create mode 100755 app/vendor/gemoji/images/1f53b.png create mode 100755 app/vendor/gemoji/images/1f53c.png create mode 100755 app/vendor/gemoji/images/1f53d.png create mode 100755 app/vendor/gemoji/images/1f550.png create mode 100755 app/vendor/gemoji/images/1f551.png create mode 100755 app/vendor/gemoji/images/1f552.png create mode 100755 app/vendor/gemoji/images/1f553.png create mode 100755 app/vendor/gemoji/images/1f554.png create mode 100755 app/vendor/gemoji/images/1f555.png create mode 100755 app/vendor/gemoji/images/1f556.png create mode 100755 app/vendor/gemoji/images/1f557.png create mode 100755 app/vendor/gemoji/images/1f558.png create mode 100755 app/vendor/gemoji/images/1f559.png create mode 100755 app/vendor/gemoji/images/1f55a.png create mode 100755 app/vendor/gemoji/images/1f55b.png create mode 100755 app/vendor/gemoji/images/1f55c.png create mode 100755 app/vendor/gemoji/images/1f55d.png create mode 100755 app/vendor/gemoji/images/1f55e.png create mode 100755 app/vendor/gemoji/images/1f55f.png create mode 100755 app/vendor/gemoji/images/1f560.png create mode 100755 app/vendor/gemoji/images/1f561.png create mode 100755 app/vendor/gemoji/images/1f562.png create mode 100755 app/vendor/gemoji/images/1f563.png create mode 100755 app/vendor/gemoji/images/1f564.png create mode 100755 app/vendor/gemoji/images/1f565.png create mode 100755 app/vendor/gemoji/images/1f566.png create mode 100755 app/vendor/gemoji/images/1f567.png create mode 100755 app/vendor/gemoji/images/1f5fb.png create mode 100755 app/vendor/gemoji/images/1f5fc.png create mode 100755 app/vendor/gemoji/images/1f5fd.png create mode 100755 app/vendor/gemoji/images/1f5fe.png create mode 100755 app/vendor/gemoji/images/1f5ff.png create mode 100755 app/vendor/gemoji/images/1f600.png create mode 100755 app/vendor/gemoji/images/1f601.png create mode 100755 app/vendor/gemoji/images/1f602.png create mode 100755 app/vendor/gemoji/images/1f603.png create mode 100755 app/vendor/gemoji/images/1f604.png create mode 100755 app/vendor/gemoji/images/1f605.png create mode 100755 app/vendor/gemoji/images/1f606.png create mode 100755 app/vendor/gemoji/images/1f607.png create mode 100755 app/vendor/gemoji/images/1f608.png create mode 100755 app/vendor/gemoji/images/1f609.png create mode 100755 app/vendor/gemoji/images/1f60a.png create mode 100755 app/vendor/gemoji/images/1f60b.png create mode 100755 app/vendor/gemoji/images/1f60c.png create mode 100755 app/vendor/gemoji/images/1f60d.png create mode 100755 app/vendor/gemoji/images/1f60e.png create mode 100755 app/vendor/gemoji/images/1f60f.png create mode 100755 app/vendor/gemoji/images/1f610.png create mode 100755 app/vendor/gemoji/images/1f611.png create mode 100755 app/vendor/gemoji/images/1f612.png create mode 100755 app/vendor/gemoji/images/1f613.png create mode 100755 app/vendor/gemoji/images/1f614.png create mode 100755 app/vendor/gemoji/images/1f615.png create mode 100755 app/vendor/gemoji/images/1f616.png create mode 100755 app/vendor/gemoji/images/1f617.png create mode 100755 app/vendor/gemoji/images/1f618.png create mode 100755 app/vendor/gemoji/images/1f619.png create mode 100755 app/vendor/gemoji/images/1f61a.png create mode 100755 app/vendor/gemoji/images/1f61b.png create mode 100755 app/vendor/gemoji/images/1f61c.png create mode 100755 app/vendor/gemoji/images/1f61d.png create mode 100755 app/vendor/gemoji/images/1f61e.png create mode 100755 app/vendor/gemoji/images/1f61f.png create mode 100755 app/vendor/gemoji/images/1f620.png create mode 100755 app/vendor/gemoji/images/1f621.png create mode 100755 app/vendor/gemoji/images/1f622.png create mode 100755 app/vendor/gemoji/images/1f623.png create mode 100755 app/vendor/gemoji/images/1f624.png create mode 100755 app/vendor/gemoji/images/1f625.png create mode 100755 app/vendor/gemoji/images/1f626.png create mode 100755 app/vendor/gemoji/images/1f627.png create mode 100755 app/vendor/gemoji/images/1f628.png create mode 100755 app/vendor/gemoji/images/1f629.png create mode 100755 app/vendor/gemoji/images/1f62a.png create mode 100755 app/vendor/gemoji/images/1f62b.png create mode 100755 app/vendor/gemoji/images/1f62c.png create mode 100755 app/vendor/gemoji/images/1f62d.png create mode 100755 app/vendor/gemoji/images/1f62e.png create mode 100755 app/vendor/gemoji/images/1f62f.png create mode 100755 app/vendor/gemoji/images/1f630.png create mode 100755 app/vendor/gemoji/images/1f631.png create mode 100755 app/vendor/gemoji/images/1f632.png create mode 100755 app/vendor/gemoji/images/1f633.png create mode 100755 app/vendor/gemoji/images/1f634.png create mode 100755 app/vendor/gemoji/images/1f635.png create mode 100755 app/vendor/gemoji/images/1f636.png create mode 100755 app/vendor/gemoji/images/1f637.png create mode 100755 app/vendor/gemoji/images/1f638.png create mode 100755 app/vendor/gemoji/images/1f639.png create mode 100755 app/vendor/gemoji/images/1f63a.png create mode 100755 app/vendor/gemoji/images/1f63b.png create mode 100755 app/vendor/gemoji/images/1f63c.png create mode 100755 app/vendor/gemoji/images/1f63d.png create mode 100755 app/vendor/gemoji/images/1f63e.png create mode 100755 app/vendor/gemoji/images/1f63f.png create mode 100755 app/vendor/gemoji/images/1f640.png create mode 100755 app/vendor/gemoji/images/1f645.png create mode 100755 app/vendor/gemoji/images/1f646.png create mode 100755 app/vendor/gemoji/images/1f647.png create mode 100755 app/vendor/gemoji/images/1f648.png create mode 100755 app/vendor/gemoji/images/1f649.png create mode 100755 app/vendor/gemoji/images/1f64a.png create mode 100755 app/vendor/gemoji/images/1f64b.png create mode 100755 app/vendor/gemoji/images/1f64c.png create mode 100755 app/vendor/gemoji/images/1f64d.png create mode 100755 app/vendor/gemoji/images/1f64e.png create mode 100755 app/vendor/gemoji/images/1f64f.png create mode 100755 app/vendor/gemoji/images/1f680.png create mode 100755 app/vendor/gemoji/images/1f681.png create mode 100755 app/vendor/gemoji/images/1f682.png create mode 100755 app/vendor/gemoji/images/1f683.png create mode 100755 app/vendor/gemoji/images/1f684.png create mode 100755 app/vendor/gemoji/images/1f685.png create mode 100755 app/vendor/gemoji/images/1f686.png create mode 100755 app/vendor/gemoji/images/1f687.png create mode 100755 app/vendor/gemoji/images/1f688.png create mode 100755 app/vendor/gemoji/images/1f689.png create mode 100755 app/vendor/gemoji/images/1f68a.png create mode 100755 app/vendor/gemoji/images/1f68b.png create mode 100755 app/vendor/gemoji/images/1f68c.png create mode 100755 app/vendor/gemoji/images/1f68d.png create mode 100755 app/vendor/gemoji/images/1f68e.png create mode 100755 app/vendor/gemoji/images/1f68f.png create mode 100755 app/vendor/gemoji/images/1f690.png create mode 100755 app/vendor/gemoji/images/1f691.png create mode 100755 app/vendor/gemoji/images/1f692.png create mode 100755 app/vendor/gemoji/images/1f693.png create mode 100755 app/vendor/gemoji/images/1f694.png create mode 100755 app/vendor/gemoji/images/1f695.png create mode 100755 app/vendor/gemoji/images/1f696.png create mode 100755 app/vendor/gemoji/images/1f697.png create mode 100755 app/vendor/gemoji/images/1f698.png create mode 100755 app/vendor/gemoji/images/1f699.png create mode 100755 app/vendor/gemoji/images/1f69a.png create mode 100755 app/vendor/gemoji/images/1f69b.png create mode 100755 app/vendor/gemoji/images/1f69c.png create mode 100755 app/vendor/gemoji/images/1f69d.png create mode 100755 app/vendor/gemoji/images/1f69e.png create mode 100755 app/vendor/gemoji/images/1f69f.png create mode 100755 app/vendor/gemoji/images/1f6a0.png create mode 100755 app/vendor/gemoji/images/1f6a1.png create mode 100755 app/vendor/gemoji/images/1f6a2.png create mode 100755 app/vendor/gemoji/images/1f6a3.png create mode 100755 app/vendor/gemoji/images/1f6a4.png create mode 100755 app/vendor/gemoji/images/1f6a5.png create mode 100755 app/vendor/gemoji/images/1f6a6.png create mode 100755 app/vendor/gemoji/images/1f6a7.png create mode 100755 app/vendor/gemoji/images/1f6a8.png create mode 100755 app/vendor/gemoji/images/1f6a9.png create mode 100755 app/vendor/gemoji/images/1f6aa.png create mode 100755 app/vendor/gemoji/images/1f6ab.png create mode 100755 app/vendor/gemoji/images/1f6ac.png create mode 100755 app/vendor/gemoji/images/1f6ad.png create mode 100755 app/vendor/gemoji/images/1f6ae.png create mode 100755 app/vendor/gemoji/images/1f6af.png create mode 100755 app/vendor/gemoji/images/1f6b0.png create mode 100755 app/vendor/gemoji/images/1f6b1.png create mode 100755 app/vendor/gemoji/images/1f6b2.png create mode 100755 app/vendor/gemoji/images/1f6b3.png create mode 100755 app/vendor/gemoji/images/1f6b4.png create mode 100755 app/vendor/gemoji/images/1f6b5.png create mode 100755 app/vendor/gemoji/images/1f6b6.png create mode 100755 app/vendor/gemoji/images/1f6b7.png create mode 100755 app/vendor/gemoji/images/1f6b8.png create mode 100755 app/vendor/gemoji/images/1f6b9.png create mode 100755 app/vendor/gemoji/images/1f6ba.png create mode 100755 app/vendor/gemoji/images/1f6bb.png create mode 100755 app/vendor/gemoji/images/1f6bc.png create mode 100755 app/vendor/gemoji/images/1f6bd.png create mode 100755 app/vendor/gemoji/images/1f6be.png create mode 100755 app/vendor/gemoji/images/1f6bf.png create mode 100755 app/vendor/gemoji/images/1f6c0.png create mode 100755 app/vendor/gemoji/images/1f6c1.png create mode 100755 app/vendor/gemoji/images/1f6c2.png create mode 100755 app/vendor/gemoji/images/1f6c3.png create mode 100755 app/vendor/gemoji/images/1f6c4.png create mode 100755 app/vendor/gemoji/images/1f6c5.png create mode 100755 app/vendor/gemoji/images/203c-fe0f.png create mode 100755 app/vendor/gemoji/images/203c.png create mode 100755 app/vendor/gemoji/images/2049-fe0f.png create mode 100755 app/vendor/gemoji/images/2049.png create mode 100755 app/vendor/gemoji/images/2122.png create mode 100755 app/vendor/gemoji/images/2139-fe0f.png create mode 100755 app/vendor/gemoji/images/2139.png create mode 100755 app/vendor/gemoji/images/2194-fe0f.png create mode 100755 app/vendor/gemoji/images/2194.png create mode 100755 app/vendor/gemoji/images/2195-fe0f.png create mode 100755 app/vendor/gemoji/images/2195.png create mode 100755 app/vendor/gemoji/images/2196-fe0f.png create mode 100755 app/vendor/gemoji/images/2196.png create mode 100755 app/vendor/gemoji/images/2197-fe0f.png create mode 100755 app/vendor/gemoji/images/2197.png create mode 100755 app/vendor/gemoji/images/2198-fe0f.png create mode 100755 app/vendor/gemoji/images/2198.png create mode 100755 app/vendor/gemoji/images/2199-fe0f.png create mode 100755 app/vendor/gemoji/images/2199.png create mode 100755 app/vendor/gemoji/images/21a9-fe0f.png create mode 100755 app/vendor/gemoji/images/21a9.png create mode 100755 app/vendor/gemoji/images/21aa-fe0f.png create mode 100755 app/vendor/gemoji/images/21aa.png create mode 100755 app/vendor/gemoji/images/231a-fe0f.png create mode 100755 app/vendor/gemoji/images/231a.png create mode 100755 app/vendor/gemoji/images/231b-fe0f.png create mode 100755 app/vendor/gemoji/images/231b.png create mode 100755 app/vendor/gemoji/images/23e9.png create mode 100755 app/vendor/gemoji/images/23ea.png create mode 100755 app/vendor/gemoji/images/23eb.png create mode 100755 app/vendor/gemoji/images/23ec.png create mode 100755 app/vendor/gemoji/images/23f0.png create mode 100755 app/vendor/gemoji/images/23f3.png create mode 100755 app/vendor/gemoji/images/24c2-fe0f.png create mode 100755 app/vendor/gemoji/images/24c2.png create mode 100755 app/vendor/gemoji/images/25aa-fe0f.png create mode 100755 app/vendor/gemoji/images/25aa.png create mode 100755 app/vendor/gemoji/images/25ab-fe0f.png create mode 100755 app/vendor/gemoji/images/25ab.png create mode 100755 app/vendor/gemoji/images/25b6-fe0f.png create mode 100755 app/vendor/gemoji/images/25b6.png create mode 100755 app/vendor/gemoji/images/25c0-fe0f.png create mode 100755 app/vendor/gemoji/images/25c0.png create mode 100755 app/vendor/gemoji/images/25fb-fe0f.png create mode 100755 app/vendor/gemoji/images/25fb.png create mode 100755 app/vendor/gemoji/images/25fc-fe0f.png create mode 100755 app/vendor/gemoji/images/25fc.png create mode 100755 app/vendor/gemoji/images/25fd-fe0f.png create mode 100755 app/vendor/gemoji/images/25fd.png create mode 100755 app/vendor/gemoji/images/25fe-fe0f.png create mode 100755 app/vendor/gemoji/images/25fe.png create mode 100755 app/vendor/gemoji/images/2600-fe0f.png create mode 100755 app/vendor/gemoji/images/2600.png create mode 100755 app/vendor/gemoji/images/2601-fe0f.png create mode 100755 app/vendor/gemoji/images/2601.png create mode 100755 app/vendor/gemoji/images/260e-fe0f.png create mode 100755 app/vendor/gemoji/images/260e.png create mode 100755 app/vendor/gemoji/images/2611-fe0f.png create mode 100755 app/vendor/gemoji/images/2611.png create mode 100755 app/vendor/gemoji/images/2614-fe0f.png create mode 100755 app/vendor/gemoji/images/2614.png create mode 100755 app/vendor/gemoji/images/2615-fe0f.png create mode 100755 app/vendor/gemoji/images/2615.png create mode 100755 app/vendor/gemoji/images/261d-fe0f.png create mode 100755 app/vendor/gemoji/images/261d.png create mode 100755 app/vendor/gemoji/images/263a-fe0f.png create mode 100755 app/vendor/gemoji/images/263a.png create mode 100755 app/vendor/gemoji/images/2648-fe0f.png create mode 100755 app/vendor/gemoji/images/2648.png create mode 100755 app/vendor/gemoji/images/2649-fe0f.png create mode 100755 app/vendor/gemoji/images/2649.png create mode 100755 app/vendor/gemoji/images/264a-fe0f.png create mode 100755 app/vendor/gemoji/images/264a.png create mode 100755 app/vendor/gemoji/images/264b-fe0f.png create mode 100755 app/vendor/gemoji/images/264b.png create mode 100755 app/vendor/gemoji/images/264c-fe0f.png create mode 100755 app/vendor/gemoji/images/264c.png create mode 100755 app/vendor/gemoji/images/264d-fe0f.png create mode 100755 app/vendor/gemoji/images/264d.png create mode 100755 app/vendor/gemoji/images/264e-fe0f.png create mode 100755 app/vendor/gemoji/images/264e.png create mode 100755 app/vendor/gemoji/images/264f-fe0f.png create mode 100755 app/vendor/gemoji/images/264f.png create mode 100755 app/vendor/gemoji/images/2650-fe0f.png create mode 100755 app/vendor/gemoji/images/2650.png create mode 100755 app/vendor/gemoji/images/2651-fe0f.png create mode 100755 app/vendor/gemoji/images/2651.png create mode 100755 app/vendor/gemoji/images/2652-fe0f.png create mode 100755 app/vendor/gemoji/images/2652.png create mode 100755 app/vendor/gemoji/images/2653-fe0f.png create mode 100755 app/vendor/gemoji/images/2653.png create mode 100755 app/vendor/gemoji/images/2660-fe0f.png create mode 100755 app/vendor/gemoji/images/2660.png create mode 100755 app/vendor/gemoji/images/2663-fe0f.png create mode 100755 app/vendor/gemoji/images/2663.png create mode 100755 app/vendor/gemoji/images/2665-fe0f.png create mode 100755 app/vendor/gemoji/images/2665.png create mode 100755 app/vendor/gemoji/images/2666-fe0f.png create mode 100755 app/vendor/gemoji/images/2666.png create mode 100755 app/vendor/gemoji/images/2668-fe0f.png create mode 100755 app/vendor/gemoji/images/2668.png create mode 100755 app/vendor/gemoji/images/267b-fe0f.png create mode 100755 app/vendor/gemoji/images/267b.png create mode 100755 app/vendor/gemoji/images/267f-fe0f.png create mode 100755 app/vendor/gemoji/images/267f.png create mode 100755 app/vendor/gemoji/images/2693-fe0f.png create mode 100755 app/vendor/gemoji/images/2693.png create mode 100755 app/vendor/gemoji/images/26a0-fe0f.png create mode 100755 app/vendor/gemoji/images/26a0.png create mode 100755 app/vendor/gemoji/images/26a1-fe0f.png create mode 100755 app/vendor/gemoji/images/26a1.png create mode 100755 app/vendor/gemoji/images/26aa-fe0f.png create mode 100755 app/vendor/gemoji/images/26aa.png create mode 100755 app/vendor/gemoji/images/26ab-fe0f.png create mode 100755 app/vendor/gemoji/images/26ab.png create mode 100755 app/vendor/gemoji/images/26bd-fe0f.png create mode 100755 app/vendor/gemoji/images/26bd.png create mode 100755 app/vendor/gemoji/images/26be-fe0f.png create mode 100755 app/vendor/gemoji/images/26be.png create mode 100755 app/vendor/gemoji/images/26c4-fe0f.png create mode 100755 app/vendor/gemoji/images/26c4.png create mode 100755 app/vendor/gemoji/images/26c5-fe0f.png create mode 100755 app/vendor/gemoji/images/26c5.png create mode 100755 app/vendor/gemoji/images/26ce.png create mode 100755 app/vendor/gemoji/images/26d4-fe0f.png create mode 100755 app/vendor/gemoji/images/26d4.png create mode 100755 app/vendor/gemoji/images/26ea-fe0f.png create mode 100755 app/vendor/gemoji/images/26ea.png create mode 100755 app/vendor/gemoji/images/26f2-fe0f.png create mode 100755 app/vendor/gemoji/images/26f2.png create mode 100755 app/vendor/gemoji/images/26f3-fe0f.png create mode 100755 app/vendor/gemoji/images/26f3.png create mode 100755 app/vendor/gemoji/images/26f5-fe0f.png create mode 100755 app/vendor/gemoji/images/26f5.png create mode 100755 app/vendor/gemoji/images/26fa-fe0f.png create mode 100755 app/vendor/gemoji/images/26fa.png create mode 100755 app/vendor/gemoji/images/26fd-fe0f.png create mode 100755 app/vendor/gemoji/images/26fd.png create mode 100755 app/vendor/gemoji/images/2702-fe0f.png create mode 100755 app/vendor/gemoji/images/2702.png create mode 100755 app/vendor/gemoji/images/2705.png create mode 100755 app/vendor/gemoji/images/2708-fe0f.png create mode 100755 app/vendor/gemoji/images/2708.png create mode 100755 app/vendor/gemoji/images/2709-fe0f.png create mode 100755 app/vendor/gemoji/images/2709.png create mode 100755 app/vendor/gemoji/images/270a.png create mode 100755 app/vendor/gemoji/images/270b.png create mode 100755 app/vendor/gemoji/images/270c-fe0f.png create mode 100755 app/vendor/gemoji/images/270c.png create mode 100755 app/vendor/gemoji/images/270f-fe0f.png create mode 100755 app/vendor/gemoji/images/270f.png create mode 100755 app/vendor/gemoji/images/2712-fe0f.png create mode 100755 app/vendor/gemoji/images/2712.png create mode 100755 app/vendor/gemoji/images/2714-fe0f.png create mode 100755 app/vendor/gemoji/images/2714.png create mode 100755 app/vendor/gemoji/images/2716-fe0f.png create mode 100755 app/vendor/gemoji/images/2716.png create mode 100755 app/vendor/gemoji/images/2728.png create mode 100755 app/vendor/gemoji/images/2733-fe0f.png create mode 100755 app/vendor/gemoji/images/2733.png create mode 100755 app/vendor/gemoji/images/2734-fe0f.png create mode 100755 app/vendor/gemoji/images/2734.png create mode 100755 app/vendor/gemoji/images/2744-fe0f.png create mode 100755 app/vendor/gemoji/images/2744.png create mode 100755 app/vendor/gemoji/images/2747-fe0f.png create mode 100755 app/vendor/gemoji/images/2747.png create mode 100755 app/vendor/gemoji/images/274c.png create mode 100755 app/vendor/gemoji/images/274e.png create mode 100755 app/vendor/gemoji/images/2753.png create mode 100755 app/vendor/gemoji/images/2754.png create mode 100755 app/vendor/gemoji/images/2755.png create mode 100755 app/vendor/gemoji/images/2757-fe0f.png create mode 100755 app/vendor/gemoji/images/2757.png create mode 100755 app/vendor/gemoji/images/2764-fe0f.png create mode 100755 app/vendor/gemoji/images/2764.png create mode 100755 app/vendor/gemoji/images/2795.png create mode 100755 app/vendor/gemoji/images/2796.png create mode 100755 app/vendor/gemoji/images/2797.png create mode 100755 app/vendor/gemoji/images/27a1-fe0f.png create mode 100755 app/vendor/gemoji/images/27a1.png create mode 100755 app/vendor/gemoji/images/27b0.png create mode 100755 app/vendor/gemoji/images/27bf.png create mode 100755 app/vendor/gemoji/images/2934-fe0f.png create mode 100755 app/vendor/gemoji/images/2934.png create mode 100755 app/vendor/gemoji/images/2935-fe0f.png create mode 100755 app/vendor/gemoji/images/2935.png create mode 100755 app/vendor/gemoji/images/2b05-fe0f.png create mode 100755 app/vendor/gemoji/images/2b05.png create mode 100755 app/vendor/gemoji/images/2b06-fe0f.png create mode 100755 app/vendor/gemoji/images/2b06.png create mode 100755 app/vendor/gemoji/images/2b07-fe0f.png create mode 100755 app/vendor/gemoji/images/2b07.png create mode 100755 app/vendor/gemoji/images/2b1b-fe0f.png create mode 100755 app/vendor/gemoji/images/2b1b.png create mode 100755 app/vendor/gemoji/images/2b1c-fe0f.png create mode 100755 app/vendor/gemoji/images/2b1c.png create mode 100755 app/vendor/gemoji/images/2b50-fe0f.png create mode 100755 app/vendor/gemoji/images/2b50.png create mode 100755 app/vendor/gemoji/images/2b55-fe0f.png create mode 100755 app/vendor/gemoji/images/2b55.png create mode 100755 app/vendor/gemoji/images/3030.png create mode 100755 app/vendor/gemoji/images/303d-fe0f.png create mode 100755 app/vendor/gemoji/images/303d.png create mode 100755 app/vendor/gemoji/images/3297-fe0f.png create mode 100755 app/vendor/gemoji/images/3297.png create mode 100755 app/vendor/gemoji/images/3299-fe0f.png create mode 100755 app/vendor/gemoji/images/3299.png create mode 100644 app/vendor/jquery.emojiarea/jquery.emojiarea-orig.js create mode 100644 app/vendor/jquery.emojiarea/jquery.emojiarea.js create mode 100644 app/vendor/jquery.nanoscroller/nanoscroller.css create mode 100644 app/vendor/jquery.nanoscroller/nanoscroller.js create mode 100644 app/vendor/jquery/jquery.min.js create mode 100644 app/vendor/jsbn/THIRDPARTY_LICENSE create mode 100644 app/vendor/jsbn/jsbn_combined.js create mode 100644 app/vendor/ui-bootstrap/THIRDPARTY_LICENSE create mode 100644 app/vendor/ui-bootstrap/ui-bootstrap-custom-0.7.0.js create mode 100644 app/vendor/ui-bootstrap/ui-bootstrap-custom-0.7.0.min.js create mode 100644 app/vendor/ui-bootstrap/ui-bootstrap-custom-tpls-0.7.0.js create mode 100644 app/vendor/ui-bootstrap/ui-bootstrap-custom-tpls-0.7.0.min.js create mode 100644 app/vendor/zlib/THIRDPARTY_LICENSE create mode 100644 app/vendor/zlib/gunzip.min.js create mode 100644 app/vendor/zlib/gzip.min.js create mode 100644 config/karma-e2e.conf.js create mode 100644 config/karma.conf.js create mode 100644 emoji_data/build.php create mode 100644 emoji_data/emoji.json create mode 100755 node_modules/.bin/karma create mode 100755 node_modules/.bin/r.js create mode 100644 node_modules/karma-chrome-launcher/LICENSE create mode 100644 node_modules/karma-chrome-launcher/README.md create mode 100644 node_modules/karma-chrome-launcher/index.js create mode 100644 node_modules/karma-chrome-launcher/package.json create mode 100644 node_modules/karma-coffee-preprocessor/LICENSE create mode 100644 node_modules/karma-coffee-preprocessor/README.md create mode 100644 node_modules/karma-coffee-preprocessor/index.js create mode 100755 node_modules/karma-coffee-preprocessor/node_modules/.bin/cake create mode 100755 node_modules/karma-coffee-preprocessor/node_modules/.bin/coffee create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/.npmignore create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/CNAME create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/CONTRIBUTING.md create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/LICENSE create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/README create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/Rakefile create mode 100755 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/bin/cake create mode 100755 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/bin/coffee create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/browser.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/cake.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/coffee-script.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/command.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/grammar.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/helpers.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/index.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/lexer.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/nodes.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/optparse.js create mode 100755 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/parser.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/repl.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/rewriter.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/scope.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/lib/coffee-script/sourcemap.js create mode 100644 node_modules/karma-coffee-preprocessor/node_modules/coffee-script/package.json create mode 100644 node_modules/karma-coffee-preprocessor/package.json create mode 100644 node_modules/karma-firefox-launcher/LICENSE create mode 100644 node_modules/karma-firefox-launcher/README.md create mode 100644 node_modules/karma-firefox-launcher/index.js create mode 100644 node_modules/karma-firefox-launcher/index.js.orig create mode 100644 node_modules/karma-firefox-launcher/package.json create mode 100644 node_modules/karma-html2js-preprocessor/LICENSE create mode 100644 node_modules/karma-html2js-preprocessor/README.md create mode 100644 node_modules/karma-html2js-preprocessor/lib/html2js.js create mode 100644 node_modules/karma-html2js-preprocessor/lib/index.js create mode 100644 node_modules/karma-html2js-preprocessor/package.json create mode 100644 node_modules/karma-jasmine/LICENSE create mode 100644 node_modules/karma-jasmine/README.md create mode 100644 node_modules/karma-jasmine/lib/adapter.js create mode 100644 node_modules/karma-jasmine/lib/index.js create mode 100644 node_modules/karma-jasmine/lib/jasmine.js create mode 100644 node_modules/karma-jasmine/package.json create mode 100644 node_modules/karma-junit-reporter/LICENSE create mode 100644 node_modules/karma-junit-reporter/README.md create mode 100644 node_modules/karma-junit-reporter/index.js create mode 100644 node_modules/karma-junit-reporter/node_modules/xmlbuilder/.npmignore create mode 100644 node_modules/karma-junit-reporter/node_modules/xmlbuilder/README.md create mode 100644 node_modules/karma-junit-reporter/node_modules/xmlbuilder/lib/XMLBuilder.js create mode 100644 node_modules/karma-junit-reporter/node_modules/xmlbuilder/lib/XMLFragment.js create mode 100644 node_modules/karma-junit-reporter/node_modules/xmlbuilder/lib/index.js create mode 100644 node_modules/karma-junit-reporter/node_modules/xmlbuilder/package.json create mode 100644 node_modules/karma-junit-reporter/package.json create mode 100644 node_modules/karma-phantomjs-launcher/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/README.md create mode 100644 node_modules/karma-phantomjs-launcher/index.js create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/.bin/phantomjs create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/.jshintrc create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/.npmignore create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/.travis.yml create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/LICENSE.txt create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/README.md create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/bin/phantomjs create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/install.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/location.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/ChangeLog create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/LICENSE.BSD create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/bin/phantomjs create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/arguments.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/arguments.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/child_process-examples.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/child_process-examples.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/colorwheel.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/colorwheel.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/countdown.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/countdown.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/detectsniff.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/detectsniff.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/direction.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/direction.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/echoToFile.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/echoToFile.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/features.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/features.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/fibo.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/fibo.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/follow.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/follow.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/hello.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/hello.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/imagebin.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/imagebin.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/injectme.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/injectme.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/ipgeocode.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/ipgeocode.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/loadspeed.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/loadspeed.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/loadurlwithoutcss.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/loadurlwithoutcss.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/modernizr.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/module.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/module.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/movies.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/movies.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/netlog.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/netlog.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/netsniff.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/netsniff.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/outputEncoding.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/outputEncoding.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/page_events.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/page_events.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/pagecallback.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/pagecallback.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/phantomwebintro.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/phantomwebintro.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/pizza.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/pizza.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/post.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/post.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/postserver.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/postserver.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/printenv.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/printenv.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/printheaderfooter.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/printheaderfooter.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/printmargins.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/printmargins.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/rasterize.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/rasterize.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/render_multi_url.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/render_multi_url.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/run-jasmine.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/run-jasmine.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/run-qunit.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/run-qunit.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/scandir.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/scandir.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/seasonfood.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/seasonfood.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/server.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/server.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/serverkeepalive.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/serverkeepalive.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/simpleserver.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/simpleserver.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/sleepsort.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/sleepsort.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/stdin-stdout-stderr.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/stdin-stdout-stderr.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/technews.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/technews.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/tweets.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/tweets.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/universe.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/unrandomize.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/unrandomize.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/useragent.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/useragent.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/version.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/version.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/waitfor.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/waitfor.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/walk_through_frames.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/walk_through_frames.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/weather.coffee create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/examples/weather.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/third-party.txt create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantomjs.js create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/.bin/ncp create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/.bin/rimraf create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/.bin/which create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/.travis.yml create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/MIT-LICENSE.txt create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/adm-zip.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/headers/dataHeader.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/headers/entryHeader.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/headers/index.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/headers/mainHeader.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/methods/deflater.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/methods/index.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/methods/inflater.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/sandbox.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/util/constants.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/util/errors.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/util/fattr.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/util/index.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/util/utils.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/zipEntry.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/adm-zip/zipFile.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/.npmignore create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/LICENSE.TXT create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/kew.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/test/chain.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/test/context.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/test/defer.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/kew/test/static.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/.npmignore create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/.travis.yml create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/examples/pow.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/index.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/readme.markdown create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/chmod.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/clobber.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/mkdirp.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/perm.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/perm_sync.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/race.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/rel.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/return.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/return_sync.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/root.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/sync.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/umask.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/mkdirp/test/umask_sync.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/.npmignore create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/.travis.yml create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/LICENSE.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/README.md create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/bin/ncp create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/lib/ncp.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/fixtures/src/a create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/fixtures/src/b create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/fixtures/src/c create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/fixtures/src/d create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/fixtures/src/e create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/fixtures/src/f create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/fixtures/src/sub/a create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/fixtures/src/sub/b create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/ncp/test/ncp-test.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/.npmignore create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/config-defs.js create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/.bin/nopt create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/.bin/semver create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/.npmignore create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/LICENCE create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/index.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/proto-list.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/test/basic.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/readme.markdown create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/broken.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/broken.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/chain-class.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/env.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/find-file.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/get.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/ignore-unfound-file.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/ini.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/config-chain/test/save.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/inherits/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/inherits/inherits.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/inherits/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/ini/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/ini/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/ini/ini.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/ini/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/ini/test/bar.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/ini/test/fixtures/foo.ini create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/ini/test/foo.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/.npmignore create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/README.md create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/bin/nopt.js create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/examples/my-program.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/lib/nopt.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/node_modules/abbrev/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/node_modules/abbrev/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/node_modules/abbrev/lib/abbrev.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/node_modules/abbrev/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/nopt/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/once/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/once/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/once/once.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/once/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/once/test/once.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/osenv/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/osenv/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/osenv/osenv.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/osenv/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/osenv/test/unix.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/osenv/test/windows.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/semver/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/semver/README.md create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/semver/bin/semver create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/semver/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/semver/semver.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/node_modules/semver/test.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/npmconf.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/test/00-setup.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/test/basic.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/test/builtin.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/test/fixtures/builtin create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/test/fixtures/globalconfig create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/test/fixtures/userconfig create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/npmconf/test/save.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/AUTHORS create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/README.md create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/bin.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs/.npmignore create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs/README.md create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs/graceful-fs.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs/polyfills.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/node_modules/graceful-fs/test/open.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/package/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/rimraf.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/test/run.sh create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/test/setup.sh create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/test/test-async.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/rimraf/test/test-sync.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/which/LICENSE create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/which/README.md create mode 100755 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/which/bin/which create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/which/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/node_modules/which/which.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/package.json create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/test/loadspeed.js create mode 100644 node_modules/karma-phantomjs-launcher/node_modules/phantomjs/test/tests.js create mode 100644 node_modules/karma-phantomjs-launcher/package.json create mode 100644 node_modules/karma-requirejs/LICENSE create mode 100644 node_modules/karma-requirejs/README.md create mode 100644 node_modules/karma-requirejs/lib/adapter.js create mode 100644 node_modules/karma-requirejs/lib/index.js create mode 100644 node_modules/karma-requirejs/package.json create mode 100644 node_modules/karma-script-launcher/LICENSE create mode 100644 node_modules/karma-script-launcher/README.md create mode 100644 node_modules/karma-script-launcher/index.js create mode 100644 node_modules/karma-script-launcher/package.json create mode 100644 node_modules/karma/CHANGELOG.md create mode 100644 node_modules/karma/LICENSE create mode 100644 node_modules/karma/README.md create mode 100755 node_modules/karma/bin/karma create mode 100644 node_modules/karma/config.tpl.coffee create mode 100644 node_modules/karma/config.tpl.js create mode 100644 node_modules/karma/karma-completion.sh create mode 100644 node_modules/karma/lib/browser.js create mode 100644 node_modules/karma/lib/cli.js create mode 100644 node_modules/karma/lib/completion.js create mode 100644 node_modules/karma/lib/config.js create mode 100644 node_modules/karma/lib/constants.js create mode 100644 node_modules/karma/lib/events.js create mode 100644 node_modules/karma/lib/executor.js create mode 100644 node_modules/karma/lib/file-list.js create mode 100644 node_modules/karma/lib/helper.js create mode 100644 node_modules/karma/lib/index.js create mode 100755 node_modules/karma/lib/init.js create mode 100644 node_modules/karma/lib/launcher.js create mode 100644 node_modules/karma/lib/launchers/Base.js create mode 100644 node_modules/karma/lib/logger.js create mode 100644 node_modules/karma/lib/middleware/common.js create mode 100644 node_modules/karma/lib/middleware/karma.js create mode 100644 node_modules/karma/lib/middleware/proxy.js create mode 100644 node_modules/karma/lib/middleware/runner.js create mode 100644 node_modules/karma/lib/middleware/source-files.js create mode 100644 node_modules/karma/lib/plugin.js create mode 100644 node_modules/karma/lib/preprocessor.js create mode 100644 node_modules/karma/lib/reporter.js create mode 100644 node_modules/karma/lib/reporters/Base.js create mode 100644 node_modules/karma/lib/reporters/BaseColor.js create mode 100644 node_modules/karma/lib/reporters/Dots.js create mode 100644 node_modules/karma/lib/reporters/DotsColor.js create mode 100644 node_modules/karma/lib/reporters/Multi.js create mode 100644 node_modules/karma/lib/reporters/Progress.js create mode 100644 node_modules/karma/lib/reporters/ProgressColor.js create mode 100644 node_modules/karma/lib/runner.js create mode 100644 node_modules/karma/lib/server.js create mode 100644 node_modules/karma/lib/watcher.js create mode 100644 node_modules/karma/lib/web-server.js create mode 100755 node_modules/karma/node_modules/.bin/cake create mode 100755 node_modules/karma/node_modules/.bin/coffee create mode 100755 node_modules/karma/node_modules/.bin/node-http-proxy create mode 100644 node_modules/karma/node_modules/chokidar/.npmignore create mode 100644 node_modules/karma/node_modules/chokidar/CHANGELOG.md create mode 100644 node_modules/karma/node_modules/chokidar/README.md create mode 100644 node_modules/karma/node_modules/chokidar/lib/index.js create mode 100644 node_modules/karma/node_modules/chokidar/lib/is-binary.js create mode 100644 node_modules/karma/node_modules/chokidar/package.json create mode 100644 node_modules/karma/node_modules/chokidar/setup.js create mode 100644 node_modules/karma/node_modules/chokidar/src/index.coffee create mode 100644 node_modules/karma/node_modules/chokidar/src/is-binary.coffee create mode 100644 node_modules/karma/node_modules/chokidar/test/chokidar-test.coffee create mode 100644 node_modules/karma/node_modules/chokidar/test/common.js create mode 100644 node_modules/karma/node_modules/chokidar/test/fixtures/binary.mp3 create mode 100644 node_modules/karma/node_modules/chokidar/test/fixtures/change.txt create mode 100644 node_modules/karma/node_modules/chokidar/test/fixtures/unlink.txt create mode 100644 node_modules/karma/node_modules/coffee-script/.npmignore create mode 100644 node_modules/karma/node_modules/coffee-script/CNAME create mode 100644 node_modules/karma/node_modules/coffee-script/CONTRIBUTING.md create mode 100644 node_modules/karma/node_modules/coffee-script/LICENSE create mode 100644 node_modules/karma/node_modules/coffee-script/README create mode 100644 node_modules/karma/node_modules/coffee-script/Rakefile create mode 100755 node_modules/karma/node_modules/coffee-script/bin/cake create mode 100755 node_modules/karma/node_modules/coffee-script/bin/coffee create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/browser.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/cake.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/coffee-script.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/command.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/grammar.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/helpers.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/index.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/lexer.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/nodes.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/optparse.js create mode 100755 node_modules/karma/node_modules/coffee-script/lib/coffee-script/parser.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/repl.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/rewriter.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/scope.js create mode 100644 node_modules/karma/node_modules/coffee-script/lib/coffee-script/sourcemap.js create mode 100644 node_modules/karma/node_modules/coffee-script/package.json create mode 100644 node_modules/karma/node_modules/colors/MIT-LICENSE.txt create mode 100644 node_modules/karma/node_modules/colors/ReadMe.md create mode 100644 node_modules/karma/node_modules/colors/colors.js create mode 100644 node_modules/karma/node_modules/colors/example.html create mode 100644 node_modules/karma/node_modules/colors/example.js create mode 100644 node_modules/karma/node_modules/colors/package.json create mode 100644 node_modules/karma/node_modules/colors/test.js create mode 100644 node_modules/karma/node_modules/connect/.npmignore create mode 100644 node_modules/karma/node_modules/connect/.travis.yml create mode 100644 node_modules/karma/node_modules/connect/LICENSE create mode 100644 node_modules/karma/node_modules/connect/Readme.md create mode 100644 node_modules/karma/node_modules/connect/index.js create mode 100644 node_modules/karma/node_modules/connect/lib/cache.js create mode 100644 node_modules/karma/node_modules/connect/lib/connect.js create mode 100644 node_modules/karma/node_modules/connect/lib/index.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/basicAuth.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/bodyParser.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/compress.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/cookieParser.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/cookieSession.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/csrf.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/directory.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/errorHandler.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/favicon.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/json.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/limit.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/logger.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/methodOverride.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/multipart.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/query.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/responseTime.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/session.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/session/cookie.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/session/memory.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/session/session.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/session/store.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/static.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/staticCache.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/timeout.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/urlencoded.js create mode 100644 node_modules/karma/node_modules/connect/lib/middleware/vhost.js create mode 100644 node_modules/karma/node_modules/connect/lib/patch.js create mode 100644 node_modules/karma/node_modules/connect/lib/proto.js create mode 100644 node_modules/karma/node_modules/connect/lib/public/directory.html create mode 100644 node_modules/karma/node_modules/connect/lib/public/error.html create mode 100644 node_modules/karma/node_modules/connect/lib/public/favicon.ico create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_add.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_attach.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_code.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_copy.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_delete.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_edit.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_error.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_excel.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_find.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_gear.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_go.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_green.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_key.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_lightning.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_link.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_paintbrush.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_paste.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_red.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_refresh.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_save.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_acrobat.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_actionscript.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_add.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_c.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_camera.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_cd.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_code.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_code_red.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_coldfusion.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_compressed.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_copy.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_cplusplus.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_csharp.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_cup.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_database.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_delete.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_dvd.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_edit.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_error.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_excel.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_find.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_flash.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_freehand.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_gear.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_get.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_go.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_h.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_horizontal.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_key.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_lightning.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_link.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_magnify.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_medal.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_office.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_paint.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_paintbrush.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_paste.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_php.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_picture.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_powerpoint.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_put.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_ruby.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_stack.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_star.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_swoosh.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_text.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_text_width.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_tux.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_vector.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_visualstudio.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_width.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_word.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_world.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_wrench.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_white_zip.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_word.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/icons/page_world.png create mode 100644 node_modules/karma/node_modules/connect/lib/public/style.css create mode 100644 node_modules/karma/node_modules/connect/lib/utils.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/buffer-crc32/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/buffer-crc32/.travis.yml create mode 100644 node_modules/karma/node_modules/connect/node_modules/buffer-crc32/README.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/buffer-crc32/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/buffer-crc32/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/buffer-crc32/tests/crc.test.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/bytes/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/bytes/History.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/bytes/Makefile create mode 100644 node_modules/karma/node_modules/connect/node_modules/bytes/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/bytes/component.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/bytes/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/bytes/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie-signature/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie-signature/History.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie-signature/Makefile create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie-signature/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie-signature/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie-signature/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/.travis.yml create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/LICENSE create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/README.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/test/mocha.opts create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/test/parse.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/cookie/test/serialize.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/debug/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/debug/debug.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/debug/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/debug/lib/debug.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/debug/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/.travis.yml create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/LICENSE create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/example/json.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/example/post.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/example/upload.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/lib/file.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/lib/incoming_form.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/lib/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/lib/json_parser.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/lib/multipart_parser.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/lib/octet_parser.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/lib/querystring_parser.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/common.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/file/beta-sticker-1.png create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/file/binaryfile.tar.gz create mode 100755 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/file/blank.gif create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/file/menu_separator.png create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/fixture/multipart.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/integration/test-json.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/legacy/common.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js create mode 100755 node_modules/karma/node_modules/connect/node_modules/formidable/test/run.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/tools/base64.html create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/unit/test-file.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/formidable/tool/record.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/fresh/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/fresh/History.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/fresh/Makefile create mode 100644 node_modules/karma/node_modules/connect/node_modules/fresh/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/fresh/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/fresh/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/methods/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/methods/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/pause/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/pause/History.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/pause/Makefile create mode 100644 node_modules/karma/node_modules/connect/node_modules/pause/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/pause/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/pause/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/qs/.gitmodules create mode 100644 node_modules/karma/node_modules/connect/node_modules/qs/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/qs/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/qs/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/qs/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/History.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/Makefile create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/lib/send.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/lib/utils.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/node_modules/range-parser/.npmignore create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/node_modules/range-parser/History.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/node_modules/range-parser/Makefile create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/node_modules/range-parser/Readme.md create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/node_modules/range-parser/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/node_modules/range-parser/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/send/package.json create mode 100644 node_modules/karma/node_modules/connect/node_modules/uid2/index.js create mode 100644 node_modules/karma/node_modules/connect/node_modules/uid2/package.json create mode 100644 node_modules/karma/node_modules/connect/package.json create mode 100644 node_modules/karma/node_modules/connect/test.js create mode 100644 node_modules/karma/node_modules/di/LICENSE create mode 100644 node_modules/karma/node_modules/di/README.md create mode 100644 node_modules/karma/node_modules/di/lib/annotation.js create mode 100644 node_modules/karma/node_modules/di/lib/index.js create mode 100644 node_modules/karma/node_modules/di/lib/injector.js create mode 100644 node_modules/karma/node_modules/di/lib/module.js create mode 100644 node_modules/karma/node_modules/di/package.json create mode 100644 node_modules/karma/node_modules/glob/.npmignore create mode 100644 node_modules/karma/node_modules/glob/.travis.yml create mode 100644 node_modules/karma/node_modules/glob/LICENSE create mode 100644 node_modules/karma/node_modules/glob/README.md create mode 100644 node_modules/karma/node_modules/glob/examples/g.js create mode 100644 node_modules/karma/node_modules/glob/examples/usr-local.js create mode 100644 node_modules/karma/node_modules/glob/glob.js create mode 100644 node_modules/karma/node_modules/glob/node_modules/inherits/README.md create mode 100644 node_modules/karma/node_modules/glob/node_modules/inherits/inherits.js create mode 100644 node_modules/karma/node_modules/glob/node_modules/inherits/package.json create mode 100644 node_modules/karma/node_modules/glob/package.json create mode 100644 node_modules/karma/node_modules/glob/test/00-setup.js create mode 100644 node_modules/karma/node_modules/glob/test/bash-comparison.js create mode 100644 node_modules/karma/node_modules/glob/test/bash-results.json create mode 100644 node_modules/karma/node_modules/glob/test/cwd-test.js create mode 100644 node_modules/karma/node_modules/glob/test/mark.js create mode 100644 node_modules/karma/node_modules/glob/test/nocase-nomagic.js create mode 100644 node_modules/karma/node_modules/glob/test/pause-resume.js create mode 100644 node_modules/karma/node_modules/glob/test/root-nomount.js create mode 100644 node_modules/karma/node_modules/glob/test/root.js create mode 100644 node_modules/karma/node_modules/glob/test/zz-cleanup.js create mode 100644 node_modules/karma/node_modules/graceful-fs/.npmignore create mode 100644 node_modules/karma/node_modules/graceful-fs/LICENSE create mode 100644 node_modules/karma/node_modules/graceful-fs/README.md create mode 100644 node_modules/karma/node_modules/graceful-fs/graceful-fs.js create mode 100644 node_modules/karma/node_modules/graceful-fs/package.json create mode 100644 node_modules/karma/node_modules/graceful-fs/test/open.js create mode 100644 node_modules/karma/node_modules/graceful-fs/test/ulimit.js create mode 100644 node_modules/karma/node_modules/http-proxy/.npmignore create mode 100644 node_modules/karma/node_modules/http-proxy/.travis.yml create mode 100644 node_modules/karma/node_modules/http-proxy/CHANGELOG.md create mode 100644 node_modules/karma/node_modules/http-proxy/LICENSE create mode 100644 node_modules/karma/node_modules/http-proxy/README.md create mode 100644 node_modules/karma/node_modules/http-proxy/benchmark/websockets-throughput.js create mode 100755 node_modules/karma/node_modules/http-proxy/bin/node-http-proxy create mode 100644 node_modules/karma/node_modules/http-proxy/config.sample.json create mode 100644 node_modules/karma/node_modules/http-proxy/examples/balancer/simple-balancer-with-websockets.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/balancer/simple-balancer.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/helpers/store.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/basic-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/concurrent-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/custom-proxy-error.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/forward-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/latent-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/proxy-https-to-http.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/proxy-https-to-https.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/proxy-table.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/http/standalone-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/middleware/bodyDecoder-middleware.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/middleware/gzip-middleware-proxytable.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/middleware/gzip-middleware.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/middleware/jsonp-middleware.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/middleware/modifyResponse-middleware.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/middleware/url-middleware.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/middleware/url-middleware2.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/examples/websocket/latent-websocket-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/websocket/standalone-websocket-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/examples/websocket/websocket-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/lib/node-http-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/lib/node-http-proxy/http-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/lib/node-http-proxy/proxy-table.js create mode 100644 node_modules/karma/node_modules/http-proxy/lib/node-http-proxy/routing-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/.npmignore create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/README.md create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/docs/docco.css create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/docs/pkginfo.html create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/examples/all-properties.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/examples/array-argument.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/examples/multiple-properties.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/examples/object-argument.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/examples/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/examples/single-property.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/lib/pkginfo.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/pkginfo/test/pkginfo-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/.npmignore create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/.travis.yml create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/CHANGELOG.md create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/LICENSE create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/README.md create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/lib/args.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/lib/base64.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/lib/file.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/lib/format.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/lib/index.js create mode 100755 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/.bin/ncp create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/async/.gitmodules create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/async/.npmignore create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/async/LICENSE create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/async/Makefile create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/async/README.md create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/async/index.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/async/lib/async.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/async/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/deep-equal/.travis.yml create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/deep-equal/README.markdown create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/deep-equal/example/cmp.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/deep-equal/index.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/deep-equal/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/deep-equal/test/cmp.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/.npmignore create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/.travis.yml create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/LICENSE create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/README.md create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/lib/defaults.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/lib/inflect.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/lib/inflections.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/lib/methods.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/lib/native.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/lib/util.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/test/inflector/cases.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/test/inflector/inflections-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/test/inflector/methods-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/test/utils/array-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/i/test/utils/string-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/.npmignore create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/.travis.yml create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/LICENSE create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/examples/pow.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/index.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/readme.markdown create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/chmod.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/clobber.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/mkdirp.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/perm.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/perm_sync.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/race.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/rel.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/return.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/return_sync.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/root.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/sync.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/umask.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/mkdirp/test/umask_sync.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/.npmignore create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/.travis.yml create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/LICENSE.md create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/README.md create mode 100755 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/bin/ncp create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/lib/ncp.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/fixtures/src/a create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/fixtures/src/b create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/fixtures/src/c create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/fixtures/src/d create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/fixtures/src/e create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/fixtures/src/f create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/fixtures/src/sub/a create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/fixtures/src/sub/b create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/ncp/test/ncp-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/AUTHORS create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/LICENSE create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/README.md create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/fiber.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/rimraf.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/test/run.sh create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/test/setup.sh create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/test/test-async.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/test/test-fiber.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/node_modules/rimraf/test/test-sync.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/file-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/fixtures/read-json-file/config.json create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/fixtures/require-directory/directory/index.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/fixtures/require-directory/helloWorld.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/format-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/function-args-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/helpers/macros.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/random-string-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/require-directory-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/node_modules/utile/test/utile-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/package.json create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/README.md create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/common.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/pummel/test-http-upload-timeout.js create mode 100755 node_modules/karma/node_modules/http-proxy/test/core/run create mode 100755 node_modules/karma/node_modules/http-proxy/test/core/run-single create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-chunked.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-client-abort.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-client-abort2.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-client-upload-buf.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-client-upload.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-contentLength0.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-eof-on-connect.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-extra-response.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-head-request.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-head-response-has-no-body-end.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-head-response-has-no-body.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-host-headers.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-many-keep-alive-connections.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-multi-line-headers.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-proxy.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-response-close.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-server-multiheaders.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-set-cookies.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-status-code.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-upgrade-server2.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/core/simple/test-http.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/examples-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/fixtures/agent2-cert.pem create mode 100644 node_modules/karma/node_modules/http-proxy/test/fixtures/agent2-csr.pem create mode 100644 node_modules/karma/node_modules/http-proxy/test/fixtures/agent2-key.pem create mode 100644 node_modules/karma/node_modules/http-proxy/test/fixtures/agent2.cnf create mode 100644 node_modules/karma/node_modules/http-proxy/test/helpers/http.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/helpers/index.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/helpers/ws.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/http/http-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/http/routing-table-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/macros/examples.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/macros/http.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/macros/index.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/macros/ws.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/ws/routing-table-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/ws/socket.io-test.js create mode 100644 node_modules/karma/node_modules/http-proxy/test/ws/ws-test.js create mode 100644 node_modules/karma/node_modules/lodash/README.md create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.compat.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.compat.min.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.legacy.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.legacy.min.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.min.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.mobile.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.mobile.min.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.underscore.js create mode 100644 node_modules/karma/node_modules/lodash/dist/lodash.underscore.min.js create mode 100644 node_modules/karma/node_modules/lodash/package.json create mode 100644 node_modules/karma/node_modules/log4js/.bob.json create mode 100644 node_modules/karma/node_modules/log4js/.bob/report/lint.out create mode 100644 node_modules/karma/node_modules/log4js/.jshintrc create mode 100644 node_modules/karma/node_modules/log4js/.npmignore create mode 100644 node_modules/karma/node_modules/log4js/.travis.yml create mode 100644 node_modules/karma/node_modules/log4js/README.md create mode 100644 node_modules/karma/node_modules/log4js/examples/example-connect-logger.js create mode 100644 node_modules/karma/node_modules/log4js/examples/example-socket.js create mode 100644 node_modules/karma/node_modules/log4js/examples/example.js create mode 100644 node_modules/karma/node_modules/log4js/examples/fromreadme.js create mode 100644 node_modules/karma/node_modules/log4js/examples/log-rolling.js create mode 100644 node_modules/karma/node_modules/log4js/examples/memory-test.js create mode 100644 node_modules/karma/node_modules/log4js/examples/patternLayout-tokens.js create mode 100644 node_modules/karma/node_modules/log4js/examples/smtp-appender.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/categoryFilter.js create mode 100755 node_modules/karma/node_modules/log4js/lib/appenders/clustered.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/console.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/dateFile.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/file.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/gelf.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/hookio.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/logLevelFilter.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/multiprocess.js create mode 100644 node_modules/karma/node_modules/log4js/lib/appenders/smtp.js create mode 100644 node_modules/karma/node_modules/log4js/lib/connect-logger.js create mode 100644 node_modules/karma/node_modules/log4js/lib/date_format.js create mode 100644 node_modules/karma/node_modules/log4js/lib/debug.js create mode 100644 node_modules/karma/node_modules/log4js/lib/layouts.js create mode 100644 node_modules/karma/node_modules/log4js/lib/levels.js create mode 100644 node_modules/karma/node_modules/log4js/lib/log4js.js create mode 100644 node_modules/karma/node_modules/log4js/lib/log4js.json create mode 100644 node_modules/karma/node_modules/log4js/lib/logger.js create mode 100644 node_modules/karma/node_modules/log4js/lib/streams/BaseRollingFileStream.js create mode 100644 node_modules/karma/node_modules/log4js/lib/streams/DateRollingFileStream.js create mode 100644 node_modules/karma/node_modules/log4js/lib/streams/RollingFileStream.js create mode 100644 node_modules/karma/node_modules/log4js/lib/streams/index.js create mode 100755 node_modules/karma/node_modules/log4js/node_modules/.bin/semver create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/.gitmodules create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/LICENSE create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/Makefile create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/README.md create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/deps/nodeunit.css create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/deps/nodeunit.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/dist/async.min.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/index.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/lib/async.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/nodelint.cfg create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/package.json create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/test/test-async.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/async/test/test.html create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/LICENSE create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/README.md create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/duplex.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/examples/CAPSLOCKTYPER.JS create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/examples/typer-fsr.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/examples/typer.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/float.patch create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/fs.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/lib/_stream_duplex.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/lib/_stream_passthrough.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/lib/_stream_readable.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/lib/_stream_transform.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/lib/_stream_writable.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/package.json create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/passthrough.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/readable.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/common.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/fixtures/x1024.txt create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-basic.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-compatibility.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-finish-pipe.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-large-read-stall.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-objects.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-pipe-error-handling.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-push.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-read-sync-stack.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-readable-empty-buffer-no-eof.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-readable-from-list.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-readable-legacy-drain.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-readable-non-empty-end.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-set-encoding.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-transform.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-unpipe-drain.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-unpipe-leak.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/test/simple/test-stream2-writable.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/transform.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/writable.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/readable-stream/zlib.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/semver/LICENSE create mode 100644 node_modules/karma/node_modules/log4js/node_modules/semver/README.md create mode 100755 node_modules/karma/node_modules/log4js/node_modules/semver/bin/semver create mode 100644 node_modules/karma/node_modules/log4js/node_modules/semver/package.json create mode 100644 node_modules/karma/node_modules/log4js/node_modules/semver/semver.js create mode 100644 node_modules/karma/node_modules/log4js/node_modules/semver/test.js create mode 100644 node_modules/karma/node_modules/log4js/package.json create mode 100644 node_modules/karma/node_modules/log4js/test/categoryFilter-test.js create mode 100755 node_modules/karma/node_modules/log4js/test/clusteredAppender-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/configuration-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/configureNoLevels-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/connect-logger-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/consoleAppender-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/date-file-test create mode 100644 node_modules/karma/node_modules/log4js/test/dateFileAppender-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/date_format-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/debug-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/fileAppender-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/gelfAppender-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/global-log-level-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/hookioAppender-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/layouts-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/levels-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/log-abspath-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/log4js.json create mode 100644 node_modules/karma/node_modules/log4js/test/logLevelFilter-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/logger-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/logging-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/multiprocess-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/nolog-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/reloadConfiguration-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/setLevel-asymmetry-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/smtpAppender-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/streams/BaseRollingFileStream-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/streams/DateRollingFileStream-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/streams/rollingFileStream-test.js create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-file-stream create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-file-stream-write-less create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-file-stream-write-more create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-file-stream-write-more.1 create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-stream-with-existing-files create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-stream-with-existing-files.0 create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-stream-with-existing-files.1 create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-stream-with-existing-files.11 create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-stream-with-existing-files.2 create mode 100644 node_modules/karma/node_modules/log4js/test/streams/test-rolling-stream-with-existing-files.20 create mode 100644 node_modules/karma/node_modules/log4js/test/with-categoryFilter.json create mode 100644 node_modules/karma/node_modules/log4js/test/with-dateFile.json create mode 100644 node_modules/karma/node_modules/log4js/test/with-log-rolling.json create mode 100644 node_modules/karma/node_modules/log4js/test/with-logLevelFilter.json create mode 100644 node_modules/karma/node_modules/log4js/test0 create mode 100644 node_modules/karma/node_modules/log4js/test1 create mode 100644 node_modules/karma/node_modules/log4js/test2 create mode 100644 node_modules/karma/node_modules/log4js/test3 create mode 100644 node_modules/karma/node_modules/log4js/test4 create mode 100644 node_modules/karma/node_modules/mime/LICENSE create mode 100644 node_modules/karma/node_modules/mime/README.md create mode 100644 node_modules/karma/node_modules/mime/mime.js create mode 100644 node_modules/karma/node_modules/mime/package.json create mode 100644 node_modules/karma/node_modules/mime/test.js create mode 100644 node_modules/karma/node_modules/mime/types/mime.types create mode 100644 node_modules/karma/node_modules/mime/types/node.types create mode 100644 node_modules/karma/node_modules/minimatch/LICENSE create mode 100644 node_modules/karma/node_modules/minimatch/README.md create mode 100644 node_modules/karma/node_modules/minimatch/minimatch.js create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/.npmignore create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/LICENSE create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/README.md create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/package.json create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/test/basic.js create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/test/foreach.js create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/sigmund/LICENSE create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/sigmund/README.md create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/sigmund/bench.js create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/sigmund/package.json create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/sigmund/sigmund.js create mode 100644 node_modules/karma/node_modules/minimatch/node_modules/sigmund/test/basic.js create mode 100644 node_modules/karma/node_modules/minimatch/package.json create mode 100644 node_modules/karma/node_modules/minimatch/test/basic.js create mode 100644 node_modules/karma/node_modules/minimatch/test/brace-expand.js create mode 100644 node_modules/karma/node_modules/minimatch/test/caching.js create mode 100644 node_modules/karma/node_modules/minimatch/test/defaults.js create mode 100644 node_modules/karma/node_modules/optimist/.travis.yml create mode 100644 node_modules/karma/node_modules/optimist/LICENSE create mode 100644 node_modules/karma/node_modules/optimist/example/bool.js create mode 100644 node_modules/karma/node_modules/optimist/example/boolean_double.js create mode 100644 node_modules/karma/node_modules/optimist/example/boolean_single.js create mode 100644 node_modules/karma/node_modules/optimist/example/default_hash.js create mode 100644 node_modules/karma/node_modules/optimist/example/default_singles.js create mode 100644 node_modules/karma/node_modules/optimist/example/divide.js create mode 100644 node_modules/karma/node_modules/optimist/example/line_count.js create mode 100644 node_modules/karma/node_modules/optimist/example/line_count_options.js create mode 100644 node_modules/karma/node_modules/optimist/example/line_count_wrap.js create mode 100644 node_modules/karma/node_modules/optimist/example/nonopt.js create mode 100644 node_modules/karma/node_modules/optimist/example/reflect.js create mode 100644 node_modules/karma/node_modules/optimist/example/short.js create mode 100644 node_modules/karma/node_modules/optimist/example/string.js create mode 100644 node_modules/karma/node_modules/optimist/example/usage-options.js create mode 100644 node_modules/karma/node_modules/optimist/example/xup.js create mode 100644 node_modules/karma/node_modules/optimist/index.js create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/.npmignore create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/README.markdown create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/example/center.js create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/example/meat.js create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/index.js create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/package.json create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/test/break.js create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/test/idleness.txt create mode 100644 node_modules/karma/node_modules/optimist/node_modules/wordwrap/test/wrap.js create mode 100644 node_modules/karma/node_modules/optimist/package.json create mode 100644 node_modules/karma/node_modules/optimist/readme.markdown create mode 100644 node_modules/karma/node_modules/optimist/test/_.js create mode 100644 node_modules/karma/node_modules/optimist/test/_/argv.js create mode 100755 node_modules/karma/node_modules/optimist/test/_/bin.js create mode 100644 node_modules/karma/node_modules/optimist/test/parse.js create mode 100644 node_modules/karma/node_modules/optimist/test/usage.js create mode 100644 node_modules/karma/node_modules/q/CONTRIBUTING.md create mode 100644 node_modules/karma/node_modules/q/LICENSE create mode 100644 node_modules/karma/node_modules/q/README.md create mode 100644 node_modules/karma/node_modules/q/benchmark/compare-with-callbacks.js create mode 100644 node_modules/karma/node_modules/q/benchmark/scenarios.js create mode 100644 node_modules/karma/node_modules/q/package.json create mode 100644 node_modules/karma/node_modules/q/q.js create mode 100644 node_modules/karma/node_modules/q/queue.js create mode 100644 node_modules/karma/node_modules/rimraf/AUTHORS create mode 100644 node_modules/karma/node_modules/rimraf/LICENSE create mode 100644 node_modules/karma/node_modules/rimraf/README.md create mode 100644 node_modules/karma/node_modules/rimraf/package.json create mode 100644 node_modules/karma/node_modules/rimraf/rimraf.js create mode 100644 node_modules/karma/node_modules/rimraf/test/run.sh create mode 100644 node_modules/karma/node_modules/rimraf/test/setup.sh create mode 100644 node_modules/karma/node_modules/rimraf/test/test-async.js create mode 100644 node_modules/karma/node_modules/rimraf/test/test-sync.js create mode 100644 node_modules/karma/node_modules/socket.io/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/.travis.yml create mode 100644 node_modules/karma/node_modules/socket.io/History.md create mode 100644 node_modules/karma/node_modules/socket.io/LICENSE create mode 100644 node_modules/karma/node_modules/socket.io/Makefile create mode 100644 node_modules/karma/node_modules/socket.io/Readme.md create mode 100644 node_modules/karma/node_modules/socket.io/benchmarks/decode.bench.js create mode 100644 node_modules/karma/node_modules/socket.io/benchmarks/encode.bench.js create mode 100644 node_modules/karma/node_modules/socket.io/benchmarks/runner.js create mode 100644 node_modules/karma/node_modules/socket.io/index.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/logger.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/manager.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/namespace.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/parser.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/socket.io.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/socket.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/static.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/store.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/stores/memory.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/stores/redis.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transport.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/flashsocket.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/htmlfile.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/http-polling.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/http.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/index.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/jsonp-polling.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/websocket.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/websocket/default.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/websocket/hybi-16.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/websocket/index.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/transports/xhr-polling.js create mode 100644 node_modules/karma/node_modules/socket.io/lib/util.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/base64id/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/base64id/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/base64id/lib/base64id.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/base64id/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/LICENSE create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/Makefile create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/doc/index.html create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/examples/basic.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/lib/server.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/buffer_bench.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/hiredis_parser.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/re_sub_test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/reconnect_test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/codec.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/pub.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/run create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/server.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/pub.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/run create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/server.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/speed/00 create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/speed/plot create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/speed/size-rate.png create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/stress/speed/speed.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/benches/sub_quit_test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/changelog.md create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/redis/diff_multi_bench_output.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/auth.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/eval.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/extend.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/file.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/mget.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/monitor.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/multi.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/multi2.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/psubscribe.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/pub_sub.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/simple.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/sort.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/subqueries.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/subquery.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/unix_socket.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/examples/web_server.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/generate_commands.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/lib/commands.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/lib/queue.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/lib/to_array.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/lib/util.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/mem.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/multi_bench.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/redis/test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/History.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/Makefile create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/README.md create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/bin/builder.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/component.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/component.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/component.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/component-json/component.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/component-json/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/component.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/emitter.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/parser.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/socket.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transport.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/flashsocket.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-jsonp.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-xhr.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/websocket.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/util.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-socket.io-protocol/component.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-socket.io-protocol/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/timoxley-to-array/component.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/timoxley-to-array/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/visionmedia-debug/component.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/visionmedia-debug/debug.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/components/visionmedia-debug/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/dist/WebSocketMain.swf create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/dist/WebSocketMainInsecure.swf create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.min.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/events.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/io.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/json.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/namespace.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/parser.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/socket.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/transport.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/transports/flashsocket.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/transports/htmlfile.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/transports/jsonp-polling.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/transports/websocket.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/transports/xhr-polling.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/transports/xhr.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/util.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/WebSocketMain.swf create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/WebSocketMainInsecure.zip create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/IWebSocketLogger.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/WebSocket.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/WebSocketEvent.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/WebSocketMain.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/WebSocketMainInsecure.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/build.sh create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/adobe/net/proxies/RFC2817Socket.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/gsolo/encryption/MD5.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/Crypto.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/cert/MozillaRootCertificates.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/cert/X509Certificate.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/cert/X509CertificateCollection.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/HMAC.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/IHMAC.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/IHash.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/MAC.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/MD2.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/MD5.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/SHA1.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/SHA224.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/SHA256.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/SHABase.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/prng/ARC4.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/prng/IPRNG.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/prng/Random.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/prng/TLSPRF.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/rsa/RSAKey.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/AESKey.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/BlowFishKey.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/CBCMode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/CFB8Mode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/CFBMode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/CTRMode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/DESKey.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/ECBMode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/ICipher.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/IMode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/IPad.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/IStreamCipher.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/ISymmetricKey.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/IVMode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/NullPad.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/OFBMode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/PKCS5.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/SSLPad.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/SimpleIVMode.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/TLSPad.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/TripleDESKey.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/XTeaKey.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/aeskey.pl create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/dump.txt create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/AESKeyTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/ARC4Test.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/BigIntegerTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/BlowFishKeyTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/CBCModeTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/CFB8ModeTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/CFBModeTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/CTRModeTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/DESKeyTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/ECBModeTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/HMACTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/ITestHarness.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/MD2Test.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/MD5Test.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/OFBModeTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/RSAKeyTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/SHA1Test.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/SHA224Test.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/SHA256Test.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/TLSPRFTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/TestCase.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/TripleDESKeyTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/XTeaKeyTest.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/BulkCiphers.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/CipherSuites.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/IConnectionState.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/ISecurityParameters.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/KeyExchanges.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/MACs.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLConnectionState.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLEvent.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLSecurityParameters.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConfig.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConnectionState.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEngine.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSError.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEvent.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSecurityParameters.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocket.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocketEvent.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSTest.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/BarrettReduction.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/BigInteger.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/ClassicReduction.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/IReduction.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/MontgomeryReduction.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/NullReduction.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/bi_internal.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/ArrayUtil.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/Base64.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/Hex.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/Memory.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/ByteString.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/DER.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/IAsn1Type.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/Integer.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/OID.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/ObjectIdentifier.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/PEM.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/PrintableString.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/Sequence.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/Set.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/Type.as create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/UTCTime.as create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/sample.html create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/swfobject.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/web_socket.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/.bin/uglifyjs create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/.bin/wscat create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/Readme.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/LICENSE create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/README create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/Tokenizer.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/ZeParser.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/benchmark.html create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/unicodecategories.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/docstyle.css create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/lib/object-ast.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/lib/parse-js.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/lib/process.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/lib/squeeze-more.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json~ create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/beautify.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/testparser.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/array1.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/array2.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/array3.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/array4.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/assignment.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/concatstring.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/const.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/empty-blocks.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/forstatement.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/if.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/ifreturn.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/ifreturn2.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue10.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue11.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue13.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue14.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue16.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue17.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue20.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue21.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue25.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue27.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue278.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue28.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue29.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue30.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue34.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue4.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue48.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue50.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue53.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue54.1.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue68.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue69.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue9.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/mangle.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/null_string.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/strict-equals.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/var.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/whitespace.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/with.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/array1.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/array2.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/array3.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/array4.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/assignment.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/concatstring.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/const.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/empty-blocks.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/forstatement.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/if.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/ifreturn.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/ifreturn2.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue10.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue11.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue13.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue14.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue16.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue17.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue20.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue21.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue25.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue27.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue278.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue28.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue29.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue30.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue34.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue4.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue48.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue50.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue53.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue54.1.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue68.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue69.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue9.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/mangle.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/null_string.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/strict-equals.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/var.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/whitespace.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/with.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/scripts.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs2.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/uglify-js.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.travis.yml create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/History.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/Makefile create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/parser.benchmark.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/sender.benchmark.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/speed.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/util.js create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bin/wscat create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/binding.gyp create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Makefile create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/bufferutil.node.d create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/validation/src/validation.o.d create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/validation.node.d create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/bufferutil.node create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/linker.lock create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/bufferutil/src/bufferutil.o create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/validation/src/validation.o create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/validation.node create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/binding.Makefile create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/bufferutil.target.mk create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/config.gypi create mode 100755 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/gyp-mac-tool create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/validation.target.mk create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/builderror.log create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/doc/ws.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/app.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/index.html create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/uploader.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/server.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/public/index.html create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/server.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/public/index.html create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/server.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/ssl.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferPool.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.fallback.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/ErrorCodes.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.hixie.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.hixie.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.fallback.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocket.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocketServer.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/browser.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.travis.yml create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/History.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Makefile create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Readme.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/lib/commander.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/.index.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/LICENSE create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/nan.h create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/Makefile create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/lib/options.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/fixtures/test.conf create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/options.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/.npmignore create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/example.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/tinycolor.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/bufferutil.cc create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/validation.cc create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/BufferPool.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.hixie.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.hixie.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Validation.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.integration.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocketServer.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn-server.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-cert.pem create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-key.pem create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-cert.pem create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-key.pem create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/certificate.pem create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/key.pem create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/request.pem create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/textfile create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/hybi-common.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/testserver.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/README.md create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/autotest.watchr create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/example/demo.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/lib/XMLHttpRequest.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-constants.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-events.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-exceptions.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-headers.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-methods.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-protocols.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/testdata.txt create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/package.json create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/events.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/io.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/node/builder.common.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/node/builder.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/parser.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/socket.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/util.test.js create mode 100644 node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/worker.js create mode 100644 node_modules/karma/node_modules/socket.io/package.json create mode 100644 node_modules/karma/node_modules/useragent/.npmignore create mode 100644 node_modules/karma/node_modules/useragent/.travis.yml create mode 100644 node_modules/karma/node_modules/useragent/CHANGELOG.md create mode 100644 node_modules/karma/node_modules/useragent/CREDITS create mode 100644 node_modules/karma/node_modules/useragent/LICENSE create mode 100644 node_modules/karma/node_modules/useragent/README.md create mode 100755 node_modules/karma/node_modules/useragent/bin/testfiles.js create mode 100755 node_modules/karma/node_modules/useragent/bin/update.js create mode 100644 node_modules/karma/node_modules/useragent/features/index.js create mode 100644 node_modules/karma/node_modules/useragent/index.js create mode 100644 node_modules/karma/node_modules/useragent/lib/regexps.js create mode 100644 node_modules/karma/node_modules/useragent/lib/update.js create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/.npmignore create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/AUTHORS create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/LICENSE create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/README.md create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/lib/lru-cache.js create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/package.json create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/s.js create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/basic.js create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/foreach.js create mode 100644 node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/memory-leak.js create mode 100644 node_modules/karma/node_modules/useragent/package.json create mode 100644 node_modules/karma/node_modules/useragent/static/user_agent.after.yaml create mode 100644 node_modules/karma/node_modules/useragent/test/features.test.js create mode 100644 node_modules/karma/node_modules/useragent/test/fixtures/firefoxes.yaml create mode 100644 node_modules/karma/node_modules/useragent/test/fixtures/pgts.yaml create mode 100644 node_modules/karma/node_modules/useragent/test/fixtures/static.custom.yaml create mode 100644 node_modules/karma/node_modules/useragent/test/fixtures/testcases.yaml create mode 100644 node_modules/karma/node_modules/useragent/test/mocha.opts create mode 100644 node_modules/karma/node_modules/useragent/test/parser.qa.js create mode 100644 node_modules/karma/node_modules/useragent/test/parser.test.js create mode 100644 node_modules/karma/package.json create mode 100644 node_modules/karma/static/client.html create mode 100644 node_modules/karma/static/context.html create mode 100644 node_modules/karma/static/debug.html create mode 100644 node_modules/karma/static/karma.js create mode 100644 node_modules/karma/test-results.xml create mode 100644 node_modules/karma/thesis.pdf create mode 100644 node_modules/requirejs/README.md create mode 100755 node_modules/requirejs/bin/r.js create mode 100644 node_modules/requirejs/package.json create mode 100644 node_modules/requirejs/require.js create mode 100644 scripts/e2e-test.bat create mode 100755 scripts/e2e-test.sh create mode 100644 scripts/test.bat create mode 100755 scripts/test.sh create mode 100755 scripts/watchr.rb create mode 100755 scripts/web-server.js create mode 100644 test/e2e/runner.html create mode 100644 test/e2e/scenarios.js create mode 100644 test/lib/angular/angular-mocks.js create mode 100644 test/lib/angular/angular-scenario.js create mode 100755 test/lib/angular/version.txt create mode 100644 test/unit/controllersSpec.js create mode 100644 test/unit/directivesSpec.js create mode 100644 test/unit/filtersSpec.js create mode 100644 test/unit/servicesSpec.js create mode 100755 update-angular.sh diff --git a/README.md b/README.md index 6365debd..416f794b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,86 @@ -webogram -======== +## Webogram - Telegram UNOFFICIAL web application +================================================= -Telegram UNOFFICIAL web application, GPL v3 +Telegram offers great [apps for mobile communication](https://www.telegram.org). It is based on the [MTProto protocol](https://core.telegram.org/protocol) and has an [Open API](http://core.telegram.org/api). I personally like Telegram for its speed and cloud-support (that makes a web app possible, unlike in the case of WA and others). + +MTProto data can be carried over HTTP, but no official web-version for Telegram exists for the time being. So this project is my take at creating one. + + +> **Disclaimer**: +> This is an alpha version of the Telegram **UNOFFICIAL** web application. It may have undetected security issues, and there is definitely a load of bugs to fix, features to add and so on. So if you want 200% secure and fully functional communication, don't use this yet! You can always find Telegram official mobile applications here: https://telegram.org + +That said, I'm using this app myself and I'd like to share its sources, so anyone can contribute to the development. Any help is welcome! + + +### Interface + + +Here are some screenshots of the interface: + +[ To be added soon :) ] + +### Implemented functionality list + +* Sign in by phone number + SMS code (no calls supported yet) +* View list of existings chats (up-posting) with infinite scrolling +* View messages history for each chat/group (bottom-posting) with infinite scrolling +* View brief profile info +* View group info, members list +* View media in messages: photo, video +* Download documents from messages +* Emoji display in all browsers (Chrome, non-OSX ones) +* Emoji keyboard +* Send plain-text messages to user or group +* Send files (photos or documents) via attach icon or drag'n'drop + + +### Unsupported at the moment + +* Secret chats +* Create new group +* Edit group photo/title/participants +* Desktop notifications +* Settings +* Edit profile/userpic +* Contacts +* Edit, delete, forward messsages +* a lot more... + + +## Technical details + +The app is based on AngularJS JavaScript framework, written in pure JavaScript (migration to CoffeeScript is planned for the future). jQuery is used for DOM manipulations, and Bootstrap is the CSS-framework. + + +### Running locally + + +#### Running web-server + +Project repository is based on angularjs-seed and includes a simple web-server, so it's easy to launch the app locally on your desktop. +Install [node.js](http://nodejs.org/) and run `scripts/web-server.js`. Open page http://localhost:8000/app/index.html in your browser. + +#### Running as Chrome Packaged App + +It is possible to run this application in Chrome browser as a packaged app. In order to do this, open this URL in Chrome: `chrome://extensions/`, then tick "Developer mode" and press "Load unpacked extension...". Select the downloaded `app` folder and Webogram application should appear in the list. + + +### Third party libraries + +Besides frameworks mentioned above, other libraries are used for protocol and UI needs. Here is the short list: + +* [JSBN](http://www-cs-students.stanford.edu/~tjw/jsbn/) +* [CryptoJS](https://code.google.com/p/crypto-js/) +* [zlib.js](https://github.com/imaya/zlib.js) +* [UI Bootstrap](http://angular-ui.github.io/bootstrap/) +* [jQuery Emojiarea](https://github.com/diy/jquery-emojiarea) +* [nanoScrollerJS](https://github.com/jamesflorentino/nanoScrollerJS) +* [gemoji](https://github.com/github/gemoji) +* [emoji-data](https://github.com/iamcal/emoji-data) + +Many thanks to all these libraries' authors and contributors. Detailed list with descriptions and licenses is available [here](/app/vendors). + + +### Licensing + +The source code is licensed under GPL v3. License is available [here](/LICENSE). \ No newline at end of file diff --git a/app/css/app.css b/app/css/app.css new file mode 100644 index 00000000..c16bef1b --- /dev/null +++ b/app/css/app.css @@ -0,0 +1,1162 @@ +/* app css stylesheet */ + +html { + background: #dee4e9 url(../img/bg_tile.png?1) 0 0 repeat; + /*background: #dee4e9 url(../img/bg_full.png) 0 0 no-repeat;*/ + /*background-size: cover;*/ + /*background-size: contain;*/ + /*background-size: 248px 382px;*/ +} +body { + background: none; + + /*font: 12px/18px "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif;*/ + /*font: 12px/18px Arial, "Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, Verdana, sans-serif;*/ + font: 12px/18px "Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, Verdana, sans-serif; + -webkit-font-smoothing: antialiased; +} +a { + color: #3a6d99; +} +a:hover { + color: #3a6d99; +} +a:hover { + cursor: pointer; +} +.form-control { + border: 1px solid #d9dbde; + border-radius: 2px; + -webkit-box-shadow: none; + box-shadow: none; + -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +} + +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); +} + +.form-control:-moz-placeholder { + color: #9aa2ab; +} +.form-control::-moz-placeholder { + color: #9aa2ab; +} +.form-control:-ms-input-placeholder { + color: #9aa2ab; +} +.form-control::-webkit-input-placeholder { + color: #9aa2ab; +} + + +.btn-tg { + color: #ffffff; + background-color: #6AC065; + /*58b152*/ + border-color: #6AC065; +} + +.btn-tg:hover, +.btn-tg:focus, +.btn-tg:active, +.btn-tg.active, +.open .dropdown-toggle.btn-tg { + color: #ffffff; + background-color: #61b75b; + border-color: #61b75b; +} + +.btn-tg:active, +.btn-tg.active, +.open .dropdown-toggle.btn-tg { + background: #5aaf54; + background-image: none; +} + +.btn-tg.disabled, +.btn-tg[disabled], +fieldset[disabled] .btn-tg, +.btn-tg.disabled:hover, +.btn-tg[disabled]:hover, +fieldset[disabled] .btn-tg:hover, +.btn-tg.disabled:focus, +.btn-tg[disabled]:focus, +fieldset[disabled] .btn-tg:focus, +.btn-tg.disabled:active, +.btn-tg[disabled]:active, +fieldset[disabled] .btn-tg:active, +.btn-tg.disabled.active, +.btn-tg[disabled].active, +fieldset[disabled] .btn-tg.active { + background-color: #999; + border-color: #999; +} + +.font-light { + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Light", Helvetica, Arial , Verdana, sans-serif; + font-weight: 300; +} + +.tg_page_head .container { + display: block; + width: auto; + padding: 0; +} +.tg_page_head .navbar-inverse { + /*-webkit-app-region: drag;*/ + background: #497495; + border: 0; + + -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.11); + -moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.11); + box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.11); + + margin: 0; +} +.tg_page_head .navbar > .container .navbar-brand { + padding: 9px; + opacity: 0.9; + margin-left: 0; + -webkit-transition: opacity swing .9s; +} + +.tg_page_head .navbar > .container .navbar-brand-alpha { + color: #FFFFFF; + font-size: 12px; + padding-left: 5px; +} + +.tg_head_logo { + background: url(../img/Logo_2x.png) 0 0 no-repeat; + background-size: 110px 31px; + display: inline-block; + width: 110px; + height: 31px; +} + +.tg_page_head .navbar > .container .navbar-brand:hover { + opacity: 1; +} + +.tg_page_head .navbar-inverse .navbar-nav > li > a { + color: #b9cfe3; + font-size: 13px; +} +.tg_page_head .navbar-inverse .navbar-nav > li > a:hover { + color: #FFF; +} + +.tg_progress { + height: 12px; + margin: 0; + padding: 0; + background: rgba(255,255,255, 0.4); + border: 5px solid rgba(0,0,0, 0.5); + border-radius: 3px; +} +.tg_progress .progress-bar { + height: 2px; + line-height: 2px; + background: rgba(255,255,255, 0.9); + border-radius: 2px; + overflow: hidden; +} + +.modal-content { + border-radius: 4px; + -webkit-box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); +} +.modal_close_wrap { + cursor: pointer; + position: fixed; + top: 0; + right: 0; + width: 50%; + height: 100%; +} +.modal_close { + background: url(../img/icons/CloseHover_2x.png) 0 0 no-repeat; + background-size: 33px 33px; + width: 33px; + height: 33px; + float: right; + margin: 60px 10px 0 0; + opacity: 0.5; + + -webkit-transition : .2s; + -moz-transition : .2s; + -o-transition : .2s; + transition : .2s; +} +.modal_close_wrap:hover .modal_close { + opacity: 1; +} + +.modal-header { + padding: 12px 0 4px 3px; + border-bottom: 2px solid #E1E1E1; + margin: 0 18px; +} +.modal-title { + font-weight: bold; + font-size: 17px; + line-height: 1.4; +} + +.modal-close-link { + font-size: 12px; + line-height: 1.4; + float: right; + padding: 0 2px 0; + margin: 6px 2px 0 0; +} +.modal-close-link:hover { + text-decoration: none; +} + + +.img_fullsize_with_progress_wrap { + position: relative; + /*margin: 0 auto 20px;*/ + margin: 0 auto; +} +.img_fullsize_progress_overlay { + position: absolute; + width: 100%; + height: 100%; +} +.img_fullsize_progress_wrap { + background: rgba(0,0,0, .1); + position: relative; +} +.img_fullsize_progress { + position: absolute; + bottom: 15px; + left: 50%; + width: 190px; + margin-left: -95px; +} + + +/* Welcome */ +.jumbotron { + background: none; +} + +/* Login page */ +.login_form_wrap { + max-width: 310px; + padding: 25px; + background: #FFF; + margin: 200px auto 0; + border-radius: 3px; + overflow: hidden; + + -webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); +} +.login_form_head { + color: #222222; + margin-top: 0; + text-align: center; +} +.login_form_lead { + color: #959595; + text-align: center; + margin: 15px 0 30px; + font-size: 13px; +} + + +/* IM page start */ + + + +.im_page_wrap { + background: #FFF; + max-width: 1000px; + margin: 0 auto; + + -webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); + margin-bottom: 40px; + + border-radius: 0 0 3px 3px; + overflow: hidden; +} + +.im_dialogs_col_wrap { + float: left; + width: 310px; + border-right: 2px solid #E9EBED; + padding-bottom: 10px; +} + +.im_history_col_wrap { + float: left; + width: 690px; +} + + +/* Dialogs list */ + +.im_dialogs_col .nano > .pane { + background : rgba(0,0,0,.0); + width : 12px; + right: -7px; + -webkit-transition : .2s; + -moz-transition : .2s; + -o-transition : .2s; + transition : .2s; + -moz-border-radius : 0; + -webkit-border-radius : 0; + border-radius : 0; +} +.im_dialogs_col .nano > .pane > .slider { + background: #A5B1B9; + margin: 0 5px; + -moz-border-radius : 0; + -webkit-border-radius : 0; + border-radius : 0; +} + +.im_dialogs_search { + padding: 14px 12px; + /*border-right: 2px solid #E9EBED;*/ +} +.im_dialogs_search_field { + font-size: 12px; + line-height: normal; + background: #F2F2F2 url(../img/icons/Search_2x.png) 7px 9px no-repeat; + background-size: 15px 14px; + border: 1px solid #F2F2F2; + border-radius: 3px; + padding: 6px 6px 6px 30px; + margin-bottom: 0; + margin: 0; +} +.im_dialogs_search_field:focus, +.im_dialogs_search_field:active { + background-color: #FFF; +} + + + +.im_dialogs_wrap { + overflow: visible; + overflow-x: visible !important; + overflow-y: visible; +} +.im_dialogs_scrollable_wrap { + /*border-right: 2px solid #E9EBED;*/ + padding: 0 12px; + outline: none ! important; + overflow-x: visible; +} +.im_dialogs_scrollable_wrap .nav-stacked > li + li { + margin-top: 0; + margin-left: 0; +} + +.im_dialogs_scrollable_wrap a.im_dialog { + color: #000; + padding: 8px 9px; + border-radius: 0; + border-bottom: 1px solid #FFF; +} +.im_dialogs_scrollable_wrap li:last-child a.im_dialog { + border-bottom: 1px solid #FFF; +} + +.im_dialogs_scrollable_wrap a.im_dialog:hover, +.im_dialogs_scrollable_wrap .active a.im_dialog { + margin-top: -1px; + overflow: hidden; +} +.im_dialogs_scrollable_wrap a.im_dialog:hover { + background: #f2f6fa; + border-top: 1px solid #f2f6fa; + border-bottom-color: #f2f6fa; +} +.im_dialogs_scrollable_wrap .active a.im_dialog { + border-radius: 2px; + background-color: #5785A5; + border-top: 1px solid #5785A5; + border-bottom-color: #5785A5; +} +.im_dialogs_scrollable_wrap .active a.im_dialog:hover { + background-color: #5785A5; +} +.im_dialogs_scrollable_wrap li:first-child a.im_dialog, +.im_dialogs_scrollable_wrap .active + li > a.im_dialog { + margin-top: 0; + border-top: 0; +} + +.im_dialogs_scrollable_wrap a.im_dialog .icon, +.im_dialogs_scrollable_wrap a.im_dialog .glyphicon { + display: none; +} + +.im_dialog_message_wrap { + overflow: hidden; + word-wrap: break-word; +} +.im_dialog_chat_from_wrap, +.im_dialog_message_media, +.im_dialog_message_service { + color: #3a6d99; +} +.im_dialog_message_text { + color: #808080; +} +a.im_dialog:hover .im_dialog_message_text { + color: #698192; +} +.active a.im_dialog .im_dialog_chat_from_wrap, +.active a.im_dialog .im_dialog_message_media, +.active a.im_dialog .im_dialog_message_service, +.active a.im_dialog .im_dialog_message_text { + color: #FFF; +} +.im_dialog_photo { + width: 40px; + height: 40px; + border-radius: 2px; + overflow: hidden; + margin: 0 10px 0 0; + +} +.im_dialog_peer { + font-weight: bold; + margin-top: 2px; + margin-bottom: 2px; +} + +.im_dialog_badge { + background: #75BB72; + border-radius: 2px; + font-size: 10px; + padding: 3px 4px; + margin-top: 4px; +} +.active .im_dialog_badge { + color: #428bca; + background-color: #fff; +} +.im_dialog_date { + font-size: 0.8em; + visibility: hidden; +} + +.im_dialog_service { + font-style: italic; + color: #999; +} +.im_dialog_message, +.im_dialog_peer { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.icon-group { + display: inline-block; + width: 18px; + height: 12px; + margin-top: 3px; + line-height: 14px; + vertical-align: text-top; + background: url(../img/icons/DialogListGroupChatIcon@2x.png) 0 0 no-repeat; + background-size: 18px 12px; +} +.active .icon-group { + background-image: url(../img/icons/DialogListGroupChatIcon_Highlighted@2x.png); +} + +/* IM history */ +.im_history_col { + padding: 0 8px 0 15px; +} + +.im_history_col .nano > .pane { + /*background : rgba(0,0,0,.0);*/ + background: #E9EBED; + width : 9px; + top: 10px; + /*margin-top: 10px;*/ + /*bottom: */ + -webkit-transition : .2s; + -moz-transition : .2s; + -o-transition : .2s; + transition : .2s; + -moz-border-radius : 2px; + -webkit-border-radius : 2px; + border-radius : 2px; +} +.im_history_col .nano > .pane > .slider { + background: #B3BFC7; + margin: 0; + -moz-border-radius : 2px; + -webkit-border-radius : 2px; + border-radius : 2px; +} + +.im_history_panel_wrap { + position: relative; + -webkit-box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12); + -moz-box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12); + box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12); + margin-right: 15px; +} +.im_history_panel { + padding: 10px 4px 0; +} +.im_history_panel_title h4 { + color: #333333; + margin-bottom: 7px; + font-size: 17px; +} +.im_history_panel_title h4 small { + color: #999; + font-size: 13px; + margin-left: 5px; +} +.im_history_panel_info_link { + /*color: #999;*/ + font-size: 13px; + font-weight: normal; + padding-top: 5px; + line-height: 1; +} +.im_history_panel_info_link:hover { + text-decoration: none; +} + + +.im_history_wrap { + overflow: hidden; + /*overflow-y: scroll;*/ +} +.im_history_scrollable_wrap { + outline: none ! important; + -webkit-user-select: text; +} + +.im_history_to_bottom { + position: relative; +} +.im_history_to_bottom .im_history_scrollable { + position: absolute; + bottom: 0; + width: 100%; +} +.im_history { + padding: 20px 0 0 3px; + /*max-width: 555px;*/ + max-width: 500px; + margin: 0 auto; +} + +.im_history_typing_wrap { + margin-top: 13px; + height: 18px; + line-height: 18px; + width: 100%; + margin-bottom: 13px; + overflow: hidden; +} +.im_history_typing { + font-size: 11px; + color: #999; + max-width: 495px; + margin: 0 auto; + + padding: 0 40px 0 47px; +} + +/*.im_history_typing { + -webkit-transition:all swing .2s; + -moz-transition:all swing .2s; + -ms-transition:all swing .2s; + -o-transition:all swing .2s; + transition:all swing .2s; +} +.im_history_typing.ng-enter { + opacity: 0; +} +.im_history_typing.ng-enter.ng-enter-active { + opacity: 1; +} +.im_history_typing.ng-leave { + opacity: 1; +} +.im_history_typing.ng-leave.ng-leave-active { + opacity: 0; +} + + +.im_history_message_wrap { + -webkit-transition:all swing .2s; + -moz-transition:all swing .2s; + -ms-transition:all swing .2s; + -o-transition:all swing .2s; + transition:all swing .2s; +} +.im_history_message_wrap.ng-enter { + position: relative; + bottom: -100px; + overflow: hidden; + opacity: 0; +} +.im_history_message_wrap.ng-enter.ng-enter-active { + bottom: 0; + opacity: 1; +} +.im_history_message_wrap.ng-leave { + opacity: 1; +} +.im_history_message_wrap.ng-leave.ng-leave-active { + opacity: 0; +}*/ + + + +.im_message_author { + color: #3a6d99; + font-weight: bold; +} + +.im_message_from_photo, +.im_message_contact_photo { + width: 34px; + height: 34px; + + border-radius: 2px; + overflow: hidden; +} +a.im_message_from_photo, +a.im_message_contact_photo { + margin: 1px 12px 0 0; +} +.im_message_contact_name { + color: #3C6E97; + font-weight: bold; +} +a.im_message_photo_thumb, +a.im_message_video_thumb { + display: block; + margin-top: 5px; + overflow: hidden; + border-radius: 2px; +} +img.im_message_photo_thumb, +img.im_message_video_thumb { + overflow: hidden; + border-radius: 2px; +} + +div.im_message_video_thumb { + position: relative; +} +.im_message_video_duration_wrap { + background: rgba(0, 0, 0, 0.5); + color: #FFF; + position: absolute; + margin-top: -15px; + height: 15px; + padding: 0 3px; + font-size: 11px; + line-height: 15px; + + border-radius: 0 0 2px 2px; + overflow: hidden; +} +.im_message_video_duration { + +} + +.im_message_geopoint { + border-radius: 2px; + margin-top: 5px; + overflow: hidden; + display: block; + position: relative; + width: 200px; + height: 100px; +} +.icon-geo-point { + position: absolute; + display: inline-block; + top: 50%; + left: 50%; + margin-left: -5px; + margin-top: -7px; + width: 10px; + height: 14px; + + background: url(../img/icons/Location_Active.png) 0 0 no-repeat; + background-size: 10px 14px; +} + + + +.im_message_document { + margin-top: 3px; + border-radius: 3px; + display: inline-block; + line-height: 0; +} +.icon-document { + display: inline-block; + width: 38px; + height: 38px; + vertical-align: text-top; + background: #F2F2F2 url(../img/icons/DocGrey_2x.png) 8px 10px no-repeat; + background-size: 20px 20px; + border-radius: 3px; + margin-right: 0; +} +.im_message_document .icon-group { + background-image: url(../img/icons/DialogListGroupChatIcon_Highlighted@2x.png); +} +.im_message_document .im_message_document_name { + color: #999; + vertical-align: text-top; + display: inline-block; + line-height: 20px; + padding: 9px 5px 9px 0; + max-width: 200px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.im_message_document:hover, +.im_message_document:hover .icon-document { + background: #EBF0F5; + text-decoration: none; +} +.im_message_document:hover .icon-document { + background: #EBF0F5 url(../img/icons/DocBlue_2x.png) 8px 10px no-repeat; + background-size: 20px 20px; +} +.im_message_document:hover .im_message_document_name { + color: #698192; +} +.im_message_document_name strong { + color: #000; + padding-right: 3px; +} + + +.im_service_message_wrap { + text-align: center; +} +.im_service_message { + display: inline-block; + min-width: 10px; + padding: 4px 7px; + line-height: 1.4; + color: #999; + text-align: center; + border-radius: 10px; + margin: 5px 0; +} + +.im_service_message_photo_thumb { + display: block; + width: 100px; + margin: 0 auto; +} + + + +.im_content_message_wrap { + margin: 10px 0 5px; +} +.icon-message-status-unread { + background: #43A4DB; + border: 1px solid #FFF; + display: block; + width: 11px; + height: 11px; + border-radius: 5px; + overflow: hidden; + position: absolute; + margin-left: -27px; + margin-top: 14px; +} +.icon-message-status-tick { + /*display: inline-block;*/ + display: none; + width: 16px; + height: 10px; + background: url(../img/icons/Checks2_2x.png?1) 0 0 no-repeat; + background-size: 16px 10px; + top: 2px; + position: relative; +} +.icon-message-status-tick.message-status-unread-tick { + /*width: 13px;*/ + background: url(../img/icons/Checks1_2x.png?1) 0 0 no-repeat; + background-size: 16px 10px; +} +.im_message_date { + color: #adadad; + font-size: 0.9em; + /*font-size: 0.8em;*/ +} +div.im_message_author, +div.im_message_body { + border-radius: 2px; + display: block; + overflow: hidden; +} + +.im_message_text { + word-wrap: break-word; +} + +span.emoji { + display: -moz-inline-box; + -moz-box-orient: vertical; + display: inline-block; + vertical-align: baseline; + *vertical-align: auto; + *zoom: 1; + *display: inline; + height: 18px; + width: 18px; + background-size: 18px; + background-repeat: no-repeat; + text-indent: -9999px; +} + +.im_history_not_selected { + text-align: center; + color: #999; + font-size: 1.5em; + padding: 200px 50px 0; +} + +.im_send_form_wrap { + /*width: 581px;*/ + width: 526px; + margin: 0 auto; + padding: 10px 12px 22px 0; +} +.im_send_form { + /*width: 444px;*/ + width: 389px; + float: left; +} +.im_submit { + padding: 5px 12px; + font-size: 13px; + line-height: 17px; +} + +.im_send_dropbox_wrap { + background: #FFF; + display: none; + padding: 15px 10px; + margin: 1px; + border-radius: 4px; + overflow: hidden; + text-align: center; + color: #999; + position: absolute; +} +textarea.im_message_field { + font-size: 12px; + margin-bottom: 10px; + padding: 6px; + min-height: 50px; + height: 50px; + resize: none; +} +.im_attach { + cursor: pointer; + display: block; + overflow: hidden; + position: relative; + padding: 0 2px; + + width: 23px; + height: 23px; + margin-top: 4px; +} + +.icon-paperclip { + display: inline-block; + width: 19px; + height: 22px; + vertical-align: text-top; + background: url(../img/icons/Attach_2x.png) 0 0 no-repeat; + background-size: 19px 22px; +} +.im_attach:hover .icon-paperclip { + background-image: url(../img/icons/Attach_pressed_2x.png); +} + +.im_emoji_btn { + cursor: pointer; + padding: 0 2px; + + width: 23px; + height: 23px; + margin-top: 4px; + margin-left: 15px; +} +.icon-emoji { + display: inline-block; + width: 22px; + height: 22px; + vertical-align: text-top; + background: url(../img/icons/Smile_2x.png) 0 0 no-repeat; + background-size: 22px 22px; +} +.im_emoji_btn:hover .icon-emoji { + background-image: url(../img/icons/Smile_pressed_2x.png); +} + +.im_attach_input { + cursor: pointer; + font-size: 72px !important; + /*visibility: hidden;*/ + opacity: 0.01; + position: absolute; + z-index: 100; + margin: 0; + padding: 0; + + right: 0; +} + +.im_panel_peer_photo, +.im_panel_own_photo { + width: 50px; + height: 50px; + border-radius: 3px; + overflow: hidden; +} +div.im_panel_peer_photo { + cursor: pointer; + margin-left: 12px; + height: 55px; +} +div.im_panel_own_photo { + margin-right: 12px; +} + +.im_panel_peer_online { + background: #6DBF69; + border: 1px solid #FFF; + display: block; + width: 11px; + height: 11px; + border-radius: 5px; + overflow: hidden; + position: absolute; + margin-top: -7px; + margin-left: 43px; +} + + +.media_modal_wrap .modal-body { + padding: 19px 18px 17px; +} +a.img_fullsize { + display: block; + text-align: center; +} +img.img_fullsize { + margin: 0 auto; +} +.media_modal_info { + color: #777; + margin: 20px 0 0; +} +.media_modal_author { + font-weight: bold; +} + +.user_modal_window .modal-dialog { + padding-top: 150px; + max-width: 506px; +} +.user_modal_wrap .modal-body { + padding: 23px 25px 70px; +} +.user_modal_image_wrap { + width: 120px; + margin-right: 22px; +} +.user_modal_image { + width: 120px; + height: 120px; +} +.user_modal_header { + margin: 0 0 5px; +} +.user_modal_status { + color: #999; +} +.user_modal_send_btn { + padding-left: 0; + padding-right: 0; + font-size: 12px; + margin-top: 8px; +} + + +.chat_modal_window .modal-dialog { + max-width: 506px; +} +.chat_modal_wrap .modal-body { + padding: 23px 25px 15px; +} +.chat_modal_image_wrap { + width: 120px; + margin-right: 22px; +} +.chat_modal_image { + width: 120px; + height: 120px; +} +.chat_modal_header { + margin: 0 0 5px; +} +.chat_modal_members_count { + color: #999; +} +.chat_modal_invite_btn { + padding-left: 0; + padding-right: 0; + font-size: 12px; + margin-top: 8px; +} + +.chat_modal_members_header { + margin-top: 15px; +} + +.chat_modal_participant_wrap { + padding: 8px 7px; + border-top: 1px solid #E0E0E0; +} +.chat_modal_participant_name { + color: #3C6E97; + font-weight: bold; + margin: 4px 0 5px; +} +.chat_modal_participant_status { + color: #999; +} +.chat_modal_participant_photo { + width: 50px; + height: 50px; + margin-right: 10px; + overflow: hidden; +} + + + + + +/* Emoji area */ +.emoji-wysiwyg-editor:empty:before{ + content:attr(placeholder); + color: #9aa2ab; +} + +.emoji-wysiwyg-editor { + font-size: 12px; + margin-bottom: 10px; + padding: 6px; + min-height: 50px; + height: 50px; + resize: none; + overflow: auto; + + border: 1px solid #d9dbde; + border-radius: 2px; + -webkit-box-shadow: none; + box-shadow: none; + -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +} +.emoji-wysiwyg-editor img { + width: 20px; + height: 20px; + vertical-align: middle; + margin: -3px 0 0 0; +} +.emoji-menu { + position: absolute; + z-index: 999; + width: 180px; + padding: 5px 2px 5px 5px; + margin-left: -88px; + margin-top: -225px; + + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + background: rgba(0,0,0, 0.7); + overflow: hidden; +} +.emoji-menu .emoji-items-wrap { + position: relative; + height: 190px; +} +.emoji-menu .emoji-items { + padding-right: 8px; +} +.emoji-menu img { + width: 20px; + height: 20px; + vertical-align: middle; + border: 0 none; +} +.emoji-menu a { + margin: -1px 0 0 -1px; + /*border: 1px solid #f2f2f2;*/ + padding: 4px; + display: block; + float: left; + border-radius: 2px; +} +.emoji-menu a:hover { + background-color: rgba(0,0,0, 0.5); + /*background-color: #fffae7;*/ +} +.emoji-menu:after { + content: ' '; + display: block; + clear: left; +} +.emoji-menu a .label { + display: none; +} + + +.emoji-menu .nano > .pane { + background : rgba(255,255,255,.0); +} +.emoji-menu .nano > .pane > .slider { + background: rgba(255,255,255,0.4); + /*background: #A5B1B9;*/ + /*margin: 0 5px;*/ + /*-moz-border-radius : 0; + -webkit-border-radius : 0; + border-radius : 0;*/ +} \ No newline at end of file diff --git a/app/img/Logo_1x.png b/app/img/Logo_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..f099252dbf8727981b381af55271d7609668cfb8 GIT binary patch literal 1550 zcmV+p2J!icP)`lH%4Mk~Esw^^q77)Lj!b z7((J2VeDbjQzp|M)+4gn=rn{ z0=4TUZUw_*V=yPrI&TkDucsW~?(21Jt6^LjOq+5&Yfy7n5VYkC`w5B}rjGP%_qkQ_QA(S~mfWF;4X zak*Gr!)OPXJZU1-Et~^O@0tx$t3&6{AME|ji!>p;zH3r&uT=R_tP#`XynUs)O0ktC zEtTUd;C}N~sJ$}+^CP#ow%N7s2bn}gR#GmOW4oNcqLLF+w!XT1?sRy0-AdT;*3o;UG0OU?n#R{e(fDp)-KHf0TF_IFE%NKK@Pm2DG+q;RDRMY&~> z!XoF9>w+wya6wuliK#6(uGhWLL}@z7c2j6IVI-#2(XXBmoWc7}kdV-c=VF|=3NLLO z=^IeiAh)#kgE`se6`F{PlGSQDN(2+HTP_L~vC<$GlP8vwCy5VDgwh3wOF6RJJT8JT zu_|zJ$3Te8I-Y@E=VOF9aYJ6(cyD_fb9*^xdNc}=X;Y*$`0e*U!^u;pWfiXLl~0(& zxR_)gll0AaSdKA@jMa9DpJ60WTkXh+J6fng_o3e*{_56|4DzXm?u8pe*A*O4BAcYr zr#U%EJKT>ru&JRFpuhNMWBKwVLP?B{8rO z+t?(@X_UODMq<@T$7VuF+iqp}u@HZ0`jtw@m5b&=V$FrkkDkMQ(6I3X+3tL?@H(T{ zhmVB}qI6p!v7lLHu_QuRpoOJ`%-C9!6Y*N-YlaS$j-R)8!7so5N!;X*s@B%)({4~6 z-DXxX8x(ykm+Uj<_}}ajyNZpi^=$-wANQ%$CFF^LhcW%xEq4`Lg`kwCTn%D(~(07P7d{X-4H`v3p{07*qoM6N<$g0^bq AQUCw| literal 0 HcmV?d00001 diff --git a/app/img/Logo_2x.png b/app/img/Logo_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..f93dd4ecc7c6aeae2c4747c993ccf89405c8d4b6 GIT binary patch literal 2857 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 Hu0mjfqrQ6p literal 0 HcmV?d00001 diff --git a/app/img/bg_full.png b/app/img/bg_full.png new file mode 100644 index 0000000000000000000000000000000000000000..30c0042917dffc6d264bf6d3e80586d0cf31999b GIT binary patch literal 587517 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%0AGhcb$Z6*Fz5wTaGG%+ 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 +x}i`7x-fp>_i& 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�L7$x-{!~^h@&ORHB|z`Dn7bqsyBOS31M5 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ȼMpPz$h`R12 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 z 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 M)78&qol`;+0AK|&rT_o{ literal 0 HcmV?d00001 diff --git a/app/img/icons/Arrow_2x.png b/app/img/icons/Arrow_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..8f53434c481201b4b046fb96021c2788876820ee GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^GC<77!3HF4glkxU6id3JuOkD)`V;1?T`z%r$r9Iy zlHmNblJdl&R0hYC{G?O`&)mfH)S%SFl*+=BsWw1G<(@8%Ar-gwTr}isFyLUlaO=qH z0_D6nhprsnkKpnKoG@GhW|q<&<>;nNd;ai2viVLK}-eF3W5~`E8wgk*a7L_=peh9x0#*GiFh+_ z1X+H!AMcp8ZEGg3EvY2UaX*k6(xxa1&wtD&z%r5}EpdOsZ%(=clz2s#+yFX~?)gP% zL3#tQan5Dw6<7n%0VV3?Q95t<%;k<{R+CnwGY6{DvPdtvRGW-|o&b`PxZE#NuiysF z@3?~G2G9!S^2_g$3{42z05k+3ZgPdbNmgYrs6oR@>?j}^0E1qTv4(JIhNf6xNG?$U z9}3hXqd7|3skk-i8_zTKY{%BH7eJvU^oBO@;GPEI(qPw4CNl#1w;_Rk`zV<$(4QIs zX9dauG5~eT%qIf<4I)+9gq9GH!*!+N)`+t)Yit9MS0J%P9of)_FmB|lD#J(oRin2T zK?2KheMCT}{Iv(D#9@|6`q&xNrgg!y1Kb{)q`3yO>eFHY2|?Z1_bNd~0}irGu~#57 z1tiuGQ+|?KG}x%mbTtK}%jAYX;><0TaUawHzq)<|7y$V;kMJ6lMKb^Z002ovPDHLk FV1mbT*H{1m literal 0 HcmV?d00001 diff --git a/app/img/icons/Attach_2x.png b/app/img/icons/Attach_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..2f9a2ed91eba17f701518108150aeeedae1a185c GIT binary patch literal 892 zcmV-?1B3jDP)6wkPb)%;0lbN@=D(GfIB$tjmYS9 zE70;0&1hoCvi$aski_2Qc|M!KLhu+o0$+nK$p5b31$YWx8e^Oj1QS3V!7K1b@b3)D z+6w#tezAaH>#4!4N+tL&2aIGE`~q?ZEN+;3DJT~X1(Tp+k2y+wa~oTrl7qlf z2KDL*_1ECh6&QDoC04ay0MynIQ$teBji?p{J)w3C%3$2k$87M129MiRv)5+yR4@Tl zlVEdv>vB9!I_55D`k8w`#SH4^fa2gZs2?%kNq`mky$(E}o_j)3J76m5vPCces_am6 zZxcBFrMW86DA5IGlu)iQDN!uuR6qV5 zlh}ZL6S~hneU}UB#R2u-d;oRi3HHNLlz9&Ffzl|?p`0HhZz%OusDCSE-=$eVrh%d{ zmSQm0iWW!H&7K`lDSoce`4Zn+sp-4g#zq6?6TuQT$-5_%Q7T{ibQdu;bTr{b!X$~} zhCYiF!R|eaGG74C>OPBX1v`2`_3hD0Z66;HwRQ}$6ndtv8%9H+D41b!a1!cY+R^H0 z#&|16li*lIc`wY@tLN7Qr>k+)wnM$aq|FZ_v^wF~P}b(cW0T-EEM7F-#303J7rAZu z#41PLhEjpikJ8f@?2V~o?8H<{gBmz|E#$7X)36;1Z!_-_vK&NOYx3DzQLAe5-4kb1Q-Bti!CHS S+lQh60000+nGjJ_Q8EJ(3mb4`;KJG3Xeh>_RM5Kyz56~XsH6zs*tM_yW zj6o$SA?-+KqzM$09!RI0ApxVX2et)hgA(;>P&#jT!{v5mR*=S|0|(++ijUo1a{p}5 z0h$3MC2_f*+#>}yXg>Ee3H|{Zqg?*@$&=yH02TnX4v3pPN8co?%o$XxVHtK5kPLu9 zx5!vSxHLmkoM1?0paPy1s76L3l$NWwDd`LEBlRw4YuG+!p3;~HX#FQ_jS2WnbN7@p-D^Lge8fPw1#=TMpymx&IFaSJvkXrmi RJ!k*`002ovPDHLkV1h1}*5m*H literal 0 HcmV?d00001 diff --git a/app/img/icons/Attach_pressed_2x.png b/app/img/icons/Attach_pressed_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..0b814d22947c13439fafff83c2ab9414a2a25f77 GIT binary patch literal 904 zcmV;319$w1P)G30+SOMpTKm{b=_^d2suH>4af6^zq{`5(s81i`h_!wqBxO(;F+hl|hLL?9|#1djg{&#{XA##Z7$HzC;1%eTv z_7FA1EyOzpWyS(x2XQojufKj@jtyp1svtgDV5DKdj{uj91$K=pE!h48#0QA?7&j1i z5EnM@p2J-YkYgd{%!1`nf(lB9icW1D#E;>w>iQS zM!4-#%^X{hT~ROsR8wG|@Tq&k?X+d>l9r#T2UNnKE*2;bPLui;>zxExli$n01M0pb z6dgM(C2eCC^nj{b)ZCf^j(=&bN;OKffkjFv+nk&znX~pK)y0=q<^o%?C#AXC%2Q3A z*wUbdwhkOnC36W|cIA;0YSLEYunkeLGUy0pQ!{Zuty|Pf$@$C$7TjGlo@!3^8QYS1 zf=hERm}6%)=Scf46x<}RH03#K%0odl>YXifXgd7W#5GPK#M?JxYUUp4P_%(#dwK!W zK((pK=ekr4ahuNh+?d1$?5*HFyZ9~})Pn`;pY;H0&kO7?OH<}G$OlTJJcqKrjQm8Y zPeT7&D1Dda0tyWj&9NMl@vN{o8aI2eK;`(lM%PPyd!@#Ax#q?_))T=}w#c(5RHRh? z?BgyHG<3A!#lj+~;)FgIDS};lHf4SRysG^o zP!ud;d5{VHFK@9rnmOKz(IPlhQ{D>eb@Ke0L zisg&OP4rTXy2!QT6{{NfGn5L9zLaMF;oF!x$1Q+1}u-%P{d{ z{9Ri-T09weOf8kYBFQ|*40`W~Cz6QjvkriAjPz2K~STsumaU&3i05Lxn`Qt#`0mPe-1)0zk zB>?elAWp_%2nbjL@kSut0>nJn3@QcU`A}~V1H6Iwu-=6GJje#Q0&zP7>A(PLIRhgw zu$h7M4Ioy*qVOXS?}G-g4K(1f0XI-!2jVaU6sVy<{1izn6Nsl_QCk7>njaR4??4=l zW(WvO2jVGM)Z2p$Qp6&05Qy*N@Wx^+V$2|eB(O+)!4tqAu?aHaNH3tY!iK{jS6l}D z#*w-wU=de=rh2Rfox))=D29#!aT+x7febhg#6noqegj4SBp?pJlN~IHNSIqdF4_;o zcNxeBe}Ook2`QhE3nl@Jk{2+8)&ucYG7JHwwQBU-pG6@3U;~Lj*L+7e=n)V%kzmMN zXb!+yu=PPRD=}Uw##ciAg=W?-1Y#)yJ*zO`uq_LZLG{=YF%zB~z7mW0K4`(uK&(L^ zkOHlOVBiJROMgi<2oz31&_eDPw6uJUOEKgB|Nj}N0RRFF0G4%CK&<@Hv;Y7A07*qo IM6N<$f~_dUs{jB1 literal 0 HcmV?d00001 diff --git a/app/img/icons/Checks1_1x.png b/app/img/icons/Checks1_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..35b72decb5a18c9c9621eba656dbef1d3a33d803 GIT binary patch literal 362 zcmV-w0hRuVP)P?VgAAvXsmtk-NK`sDdW-NxWLA?p`?k}ie zm+?7(38+a0NS_Dd$yns)1F;j7od`5+A0Z!sTxbu(qClJpG`s@IbuBB+b!KdMT8i4m2!_*wnxR^9~S8K)tsRNq!R$=aQ1};mHOXo2P+T6)JZYh;4zc z`%adDP(!VO)HWdg48-O@!=5sb2rv>hG)Mdb8g`R`3;+;d0EW+9l3kzA{{R3007*qo IM6N<$f~$*&HUIzs literal 0 HcmV?d00001 diff --git a/app/img/icons/Checks1_2x.png b/app/img/icons/Checks1_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..86c6f6a8a958670fa9f4b6071ffad991284e7343 GIT binary patch literal 535 zcmV+y0_gpTP)P12qtV zMoqhb0LhbX*FXiV$?JFGPHN#L+nW?(U=F&q@v|hq|841+Fc5?>ZTtcKYVGHeTsKex z)6kp6H3Kl8q76bU*W@a^a-4t=yulM3XPDm(D^RRyAreRP{f^EXn37|aRCP<5xk}rV zIZkZDOd-q2F>tME^{@&)P4kJSx7Qd9@$|L{1H%y4boF-%L#YrJ&52v+A^B&aUCgP0 zD=Dshs1?mG9nLw|TdZH|#WH0;#i>;DE|iHDNSU8dPY#dSwAp<6zyXXyx|`dw_D@Kj zF!c-drqMQ_2}V=&SrSJK?;kRD!euzq#wziGIlqy&vK~>AgOAyJxAQVDyU8eu65Twr$Aya3i-l(0)3THm*iLq1 zNMn(5uGeu)1GGNYH!ub}9UIb^qg+D0GL$JvM#SeW$7rEv&yYXG5Jvf91 zU5_DXK>@Q?JW{WV1A~fp;C(-ZOSpnp7|_9#+L^h?35{KbNBxL#2a7NYJu(XwGx+OP z{JPjgpQN0@yB`U?Ny)=1+Wx=y%nW^Ij`BGeiD_w=i0^I3mjD9*oCCfiJxdWZ00000 LNkvXXu0mjfsO-Pu literal 0 HcmV?d00001 diff --git a/app/img/icons/Checks2_2x.png b/app/img/icons/Checks2_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..233b82825d22948d1c48f6e8ca785ce0bdc72aa7 GIT binary patch literal 713 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 literal 0 HcmV?d00001 diff --git a/app/img/icons/Close_2x.png b/app/img/icons/Close_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..1a892be1dd5019f6fbbd5526872994c85ea9c46c GIT binary patch literal 1515 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 literal 0 HcmV?d00001 diff --git a/app/img/icons/DialogListGroupChatIcon_Highlighted@2x.png b/app/img/icons/DialogListGroupChatIcon_Highlighted@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4991d5bd80070a1ee3ede11194cb60820bb7612f GIT binary patch literal 529 zcmV+s0`C2ZP)_HkOfqg(!$cAYf-BSPBulU}510CWj&@29x!z z-iaJ{JCijgKKQ|HZf5T>ncF!br4$TOpa`DjmoC9Rm}2I$;RKaHLk8;wqHqp)$x5F^6uPzp2NFyb05$-Xmgm0;=%}9*o{#=8=9LGB$2OJR~Qp88_9i zyeOkTCN<|#S(A4FE<)~YhrWr7>Z}vPbyJhO91yR*9L7zj{Tz5C484IBVEJ+__q)lj zD=^!sAsZaY&ZHim12IMqsn{fCNNuzT&gAcO4^BXnh*Oo{@He-2F$@ae2DD{w<$ydG zRbC>Wu7t?Aoj)S_BXy3|)lBpZ)!hjl5&hFU*zydu`)ua>6!H$niufO@d-j TmEKmm00000NkvXXu0mjfsUq6a literal 0 HcmV?d00001 diff --git a/app/img/icons/DocBlue_1x.png b/app/img/icons/DocBlue_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..6a85c564b82bdd96553bdcf93fbe45f844e7bc78 GIT binary patch literal 476 zcmV<20VDp2P)}`dcC@>CtCeJr+O`e;bKDF)n7{2)OdIIV+gdMXk1I98fiQ>Z9g3hA=mC0$j?fbO zg`OStJ(;jqI!_VJr?+2XdXh`9SA{*WgwOnfoDbu0+|MpXNLWR4%30tOXbY`yL1Us! zV8`JVFtKHQ2hBAijz)_WcEBP!-$JQ@1EQ(E!K8|{u?1E$`iWiwTVP|g ze{yJGW5P;n16FvcNZ3Yd$5J%g*nP10OkO4Wd+h)VR7e*r;<~1yv8j<%oNa8=s5uU1 zLsDV={i19L+x`Xi3&_KsM zgw53+`ahK1Ecvlld{S`@?4-(Yt~F=OSH@>|{<`{}tPOi)aXtv!4TZ`07GMA)mdX3d SU+_2p0000y55TAOCeeOk?AkhS|C$KVs+(XV*k3C5nRGlE+pxVHN`oKOs z7z8Ow>MP&lOC(vuM*swW@$P!PCjWE$Fm-^}x9{5HHS{OwDfSig9(srU_36v!i#EXB zR1Z1;2aqH5EMSNe^a4P8>7iL5Dubuq1K|?<-8)P){TG0Pkp?|zTMc~&{o@cZ{5xE? z%;Sv&X%>VVLbgGe8n5mB8lP>*{o%bcK(3YmTsz=e&wDL{9L9N`8}QG}1-LHcWmp^? zdin1y>P0hg1+UO^X$%~JY;iT)32!F@3UCQ}qGR5Dz`phj`HlSlIEM!-2A7kZvvu$n zPNKomQ?V6Jy;!pa7Y_*Dt7sSy?nJK7JlRRjYdni4q24x;aG3&EVMuN3*lJEk6!CF@ z0$eG;ark>&IE9pBLb-|q1h|YDKSACU3LJ+o+2WBF-I|3u3=rWe2A8wk%D4a!>ZR6b zPG5on1-M#(s~B7^40V(MNPCe=j`6@fFykFHE_v1g$HV`X+1ZouUTDcN3S5fig2HXA zZgapF!cfmbZnkWa)O&?jup%7Y{5hQXoNW4`;rHeCtp^3;{X%ftkO&w@vWCL-4!EtB zyI8C%SNiw>4`|TBb)-&J0dS&mMc6vwL_h@E2yi#D%0BlQCzDXqC+e%t2S>i@xbX{a zb5zp*Amzk0$dwb}5*Q`#Xmvjbo=XCZABE@j7>Q>TWnuHF1-QK<{F-r}u$=_>iLykh>WuBLqv15b zRQOJC3D*NNz8AD%8T)1CEi=4`VlJMD@jcsrUjpRUWWb(@2M(QMJ&X~qvjF~dNO1~T zDsb%_a2jCE&Pr0xsTLOpySa|cjB=pU`p)j)-j;ocyR>0+)6S@K+}u}oqX(dxg#VGP z_SxaQYDN&Kt`-dk(TXoK80ve^L1ejv=WP2ezyNFkcTaWKXA=Mb002ovPDHLkV1oS) BmLdQE literal 0 HcmV?d00001 diff --git a/app/img/icons/DocGrey_1x.png b/app/img/icons/DocGrey_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..8835c3b49f89160f75b799ebd76428d36f0cf49d GIT binary patch literal 474 zcmV<00VV#4P);eysgnZS<2 z8(?C~`T<&KL>#RaE9`+qbiRjD0}Gf#Sv#7G^wQ%Q(1S@88)FNsVe~V-1h&AYYX9WW zz@~&%)&{KfQjxHY)Q+WSwy}p`@rArf^pDyB7O0RuSj2TrMQc+dskqqKrct*zn2$+? z_4kXiA#C>-*e@V+^eW}YLC58i&RaTHwAXzwKf=^N`l2oME3to`cJHri=*il!Cl=>}u)|oGjBf!30CO?QJt|<4 QhX4Qo07*qoM6N<$f@nO|EdT%j literal 0 HcmV?d00001 diff --git a/app/img/icons/DocGrey_2x.png b/app/img/icons/DocGrey_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..7bcc7642d20a3eda224343fde81d757c0e923afa GIT binary patch literal 898 zcmV-|1AY97P)EyAc1A3?WMYXd;C9b>Y zY3Kz{53-=4x@W*pIaAHZlJ$34aK)C=;A-h!F0-ybeQ5d}fQDU{h-XKt^UhmTmsEdH z{Ymu|U`q{hIx<`(?i&Wn_!`~%!k`U6nnwUyxJ1A$6)-F<#oiqH?Z*b30bI*gYkRz7 zDf%zSii=SI=|u^|TpMY*t3p=n#=VJ0f9?ikxQgBDg6rD09B-kNQ$YS44yeF&Wi8;W zWltPaJMMpiF=)j`gw0(Re20lL&T$s5;(QodOgD>07{Lqzq=6;4E8|=zSD}GCScu6J zwrHp%y#X06^}uQEUClW@T1+Ji%_~3GYZ?qUwLg32P(@3}!CO;BfF798j z9ag1v*~~M?O2lRz4ajgMz-8h-g_t_BTe0i~z=zWQS6qKa0V;4G5>A76z@hu!U>=z# zTloRgfXPdUAs<}hfZHnWui-t?1FxJD-GY^K(9Py=2Xgxf;Fik%8?vzGp|w{mM8Z`g zz!^|3ss}U|?{M>1;1Z$hG&n6h@{l}}uJr+CJTby)vTCis83j&$g!+*hoC?St*F324 z$tv3(AzWLJc3ivQqE2-#Sta0Ia4k#v7DR*zd}REY#3iegm%4)s%6|a{ Y0P47awlYa~O8@`>07*qoM6N<$g5{B$>;M1& literal 0 HcmV?d00001 diff --git a/app/img/icons/Location_Active.png b/app/img/icons/Location_Active.png new file mode 100755 index 0000000000000000000000000000000000000000..9878efba9ccc37dc5a4280ffa097c6d3b52e75e8 GIT binary patch literal 574 zcmV-E0>S->P)9UOoaP>~meBhUx7!MVYV)B)zeT{K&cnGEw_#`3N%P=IMdWw;2& zt;R*W%EL4w8}@;WA*l$C`BGF0fUImt=h3DJq#GRqQ7{U+K?-~-Vq>Us*v};=6aiH* z#?{H%mn(88A-KOnip3*^nXMeR&YyM@8Z*mqUZfg$QauDRY}X|98w>-QLR!i2OOq5g zm`-zZJJm^sm*88mNVi^ayci#M#Jc7~w{*)N-~sd~0>W%c=k?4L2MtHDBcxk%n>qt7 zX0PDTHrxeoR&&Z=l+|oQ>imT!%&xfM>xRP~IQxegy{IXwPBp$#9MFhXVOG@5!xC6) zz^uemTRUJ$OW@k$R+Ff%>Sp*Gs2NeR(y9*&!&cG;vlFnTS`db$949(OFJ@AgBwV(Y zbc``-jS2AbU&9I;RHbt>_Nw2*ZC-$R`e%R*w_xG1-*UWtSN#Yu0L}elc9<2bA^-pY M07*qoM6N<$f)}0ojsO4v literal 0 HcmV?d00001 diff --git a/app/img/icons/Logo_1x.png b/app/img/icons/Logo_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..f099252dbf8727981b381af55271d7609668cfb8 GIT binary patch literal 1550 zcmV+p2J!icP)`lH%4Mk~Esw^^q77)Lj!b z7((J2VeDbjQzp|M)+4gn=rn{ z0=4TUZUw_*V=yPrI&TkDucsW~?(21Jt6^LjOq+5&Yfy7n5VYkC`w5B}rjGP%_qkQ_QA(S~mfWF;4X zak*Gr!)OPXJZU1-Et~^O@0tx$t3&6{AME|ji!>p;zH3r&uT=R_tP#`XynUs)O0ktC zEtTUd;C}N~sJ$}+^CP#ow%N7s2bn}gR#GmOW4oNcqLLF+w!XT1?sRy0-AdT;*3o;UG0OU?n#R{e(fDp)-KHf0TF_IFE%NKK@Pm2DG+q;RDRMY&~> z!XoF9>w+wya6wuliK#6(uGhWLL}@z7c2j6IVI-#2(XXBmoWc7}kdV-c=VF|=3NLLO z=^IeiAh)#kgE`se6`F{PlGSQDN(2+HTP_L~vC<$GlP8vwCy5VDgwh3wOF6RJJT8JT zu_|zJ$3Te8I-Y@E=VOF9aYJ6(cyD_fb9*^xdNc}=X;Y*$`0e*U!^u;pWfiXLl~0(& zxR_)gll0AaSdKA@jMa9DpJ60WTkXh+J6fng_o3e*{_56|4DzXm?u8pe*A*O4BAcYr zr#U%EJKT>ru&JRFpuhNMWBKwVLP?B{8rO z+t?(@X_UODMq<@T$7VuF+iqp}u@HZ0`jtw@m5b&=V$FrkkDkMQ(6I3X+3tL?@H(T{ zhmVB}qI6p!v7lLHu_QuRpoOJ`%-C9!6Y*N-YlaS$j-R)8!7so5N!;X*s@B%)({4~6 z-DXxX8x(ykm+Uj<_}}ajyNZpi^=$-wANQ%$CFF^LhcW%xEq4`Lg`kwCTn%D(~(07P7d{X-4H`v3p{07*qoM6N<$g0^bq AQUCw| literal 0 HcmV?d00001 diff --git a/app/img/icons/Logo_2x.png b/app/img/icons/Logo_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..f93dd4ecc7c6aeae2c4747c993ccf89405c8d4b6 GIT binary patch literal 2857 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 Hu0mjfqrQ6p literal 0 HcmV?d00001 diff --git a/app/img/icons/NoResults.png b/app/img/icons/NoResults.png new file mode 100755 index 0000000000000000000000000000000000000000..9b6747ecd5f0f15b97a12f469a8ace260c1a22a2 GIT binary patch literal 4655 zcmV+~64335P)005u}1^@s6i_d2*00004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU@!AV3xRCwC# zoezjy#T~~ddog-?dV29RdU`R@Af%*NB0@^Ul44OJ7K_Cauv8R9Q7DQ_ChU|lCuLU3F7>?~Quaxi zQs0{mA9Du_8cx79QdTRn>DNUSyzhjRmz6-+7ZgDQ0X@e$B@l0IMPy4u$`_?PqhvY| z(0vR`xkAe2ig?2gT|1g_o0KP%rVIph1Orkok@7Ps>!l2Oa8D5MQ65-;lPHDvZq`cPFG2NCfl;X{Z0Fhjl0rFdHa&ZI<#6(J7Awq&LmCD${&bAYgJVQs(v*(Mci)uItWNod9yOP17ZEG z3jQweoq$BPPl=FTvDGA_2`}-Lfb6Y!Udlybt*r&ti89{Rz7dd0#=oST7uMK%5Rm*u zbgC#`5OB59e4%s2E!?jnWTy#uf$}Ssg!ObbLVmzi0%C5T7NMl(I&K!7@|{xzT&c)6 z9M;bZP`wT&ej_@aG_?^Bzb`ZwG&?AHJdZz^hk(KF3&`ycW+mW|deh+d1!#Y8LzM*lr3lI9 zfWz@X7E_#sfFzo44WD;F4@Oi_k_uVIv(ekP*0)dZ>#x5ShYlSQUw-*z`}M1@z7pSj z^G*Bv$iTpWSg>G0`}L@!juML&Eo#3a0rOx~-1(w2UN{jJrhJ19K9LWiefsIAVrFJW z%+AiXzn+_$YZI@p>1egugE63DgYy*`3)O(ASmw1j z-CT+`J9zM*IB?*A_~esM+M2EiKs<;zJUlE;IN^jgF&m7Vq&!qK0dX>KcA0n|fBdod z;DZmuXPU%9*xKNyU;)!DM;>B&P*g));vO>KULO^mouM0;)K-lS>KmQzzxsR9{CVT>W-R^vt& z?u=*`0>=4z5CK9|4ak1lX{WV=4igC}0iwO@OcPZAcG0a$LqMikt+V~ENQIDUF-5yX zwo8{TZKqV~1j*>}@o}T}C5lcGI601M(-3fj3wMN%Wy) zGY1Ef67VY9?*^@bM1jZ>^4XT~9T^#Eo8%}EF~9rnyFQy@nprMRLO^V_)n|2Jaw)Mz zEf%Ch)7YZU2sm5}$}f4^@9$6;L2 zYld5f^o!Nn&y;c@$&ABqJJ8NNC{e%JFyA~lQ7I$ZyU_T)6R`Wv*Vuf; zEM}Bn1o1FsWdP#Q9i3FWLKu8hf+U2mPe1+iSn~4w@m+g;TkaPUdb+zVl7JW3e8qH( zM0JhmHu|#Ak9-gX6HRJJYb=uCXl1=$xF4w8L%Y z)lqWeS_n|OQzno_OB#@r#vkmh>?GaK;vfc8FtWoL0-{}_N^fOqKNAQ@XdciH1g4rC zWY%k;F;#DT>V4?AXHTas97aGA&{iKRV`|#0a=$GEdF!pW=2JnKSegs+M&Nn}UM~UJ zr(eA>_J7hI&WN799ex{suDY8=JNZUTQjjs3g124|UA(>*j` zreIqG4haX&`(QClT_Z(nL0w+UQ{6}#kw>8cV}6G<0j&q*i&_xKSLA+L-N~Y-o0biH zzo<4dJ#*S~47P+Lrya#D2xHNTf+hpnuZkuIoeYn1Ihrs-5CS?gn#nX$4botWi-2y6 zs;Ujj^zhK4=dt zY-fx@lF6j~pu1eE(tZRxQF%;EZy9@BEW{xQIOoz8LyjoZ#6srXIHY~CDi)vjGHGo_ zcQj;>`78u6f3FzbAkGBqGU661KIOfTsr1{O8!NUwPUIyWCSZo(9GRkTcz3F^GSzudih zx6wy+WwKWwU{6GBGFkY6jMgYBKbTkZ(N!IHWCL3;qvqatj%iK6NmuWHU1_GNSek?k z0IzFr1sZR1ax#{DfQ}e`&L*v00j4wor<@JrTdj6?v#D;X&2b&)aiD$QeDlr3sUaR1 zt~2h;6OVw^opD|R0)6&cT>1jdGBGjH4o=FRIz^HhlM9*Bc5Le-$FfH94x!CCT~e5E z{cflcLqZ&V(?|=xul+)DiTIF3?zy103&HvQc?Vn4k&K__|Pg zHC+e39)6!`oNrW0hd_oFsNMss_0BZRHUi-Y7-u%lhoToeARPDQQJIb-T&KDpshz$NP@fA- z;XlpHWe8T(aB>L4b&zC+v=BJUF$|<}NYiivlm~l7_Up_`w`1{wkDe~U34S2~N*Po1 zO`xO(@m8!@F+V_Er;M^5QjMvHgdUtJH_x?h6HKe|LDvJ3IB4xdl!`_vBOQZw!rao; zVhU{VA;}MB-9`YpF~<%!t==i+zFq=?e@j^{8UVBjWJDlBR+EcngJ?wH`tX?~&7{01 zb7!(9$IF<~RUt0aTCkUZ8>QSK8U*|@@`Dgk?=j|UJuX9QNga$3iRwrhfq1-T>0%*$ zL&7>M2{GxMJLgyv11W>W>h%Z$GQIqH(QxQsK~JsHV{)}0S7c5O4NTrLPtZfMnr)<|uiNEZ!=hKWPlq1m*CD`Qv?NpQ4So@xhG6Ftku5dsPm0U_VBBA`;R z2Lux40kvbwj1HWx6iYzxM4&|VAXQ^JO+6`ar)YpE>wv`qK(2YJ9|5-oGh7ewcTONtF>U^sA5VI56a z;{n(Y8r_XP|8Y~GK>eWJj8B+nVisC7uQ|^Ml-SO!1SBW8D^Q?*(0WDpOO}!yrNkN= zS?`Mtxca#dK?~XgTCYgaq#+@uyNF;WBT!!3^AJ#|=w&i2za60U$}|%vO7lU!8mH~w z-R}pI5D?Gx-mvucfRbImF>+e-<;^AL0Dj+-MGz1?B0Si6UZp|eGr0KJcy8nOk`6G*$O#_Lom2we11bfdsW4CsH%^rVUuL zY;f2V0+Ij&ZV@RDKFUJCLm?muhyYcyEouK#E61CKrquwA*{n(_&mO~@M5vGibZ|pf zw=53<88`J4Ws(D$i$_F`=HW@_hXTB3vW?# zCVm?H!AAOhxqC&6B4F?bgWp#x0kuDPO;{W6@vPE*!Zrc|a)Wn*DFDdd>a)^1=XMjE^LdC>pY**24WwRmcIE3~I<=E~E>unYODCLKu;`!ip zor287B)0Co5Z1kR%qXjLLmif>&SSWBa`V@L1GQnNQUtXf%~AI`@I=UW2a{Y2@W;O^ zYTn`4vgE_yScq?na7t5ECYMIiTZ9GY!L%&;V5X&fUvyf$4+Nf+0;W}cOC*?D)kFen z&`GmgbebLmiUDT!Ql<4;{~=X{{UZ_gyi|1dB8Rli z;nNIRg?MldXMgOux~tZ4}G z(EeTe1Gd$G2QjQoAD#%r1AAzY)P`=%1G7w1Y@rQ{s- z^)e|V1-{2lMXpH|t-h>erpX_CAYeQ=AN9PhuSXOyHAa54wR#llaqsTkl37eopxpmxo}_7 z9<&Z}5``j%@x6L&yZ`>Py!v|6Kl8nR-ur(y3`55jK@d!kvXF)tJi-|qc%Jtn-?%mz zah0?Oo$v(maT2k_mFCk5!*>uFbOkMKeznV4rvp% z+KhLjFa;%>sId#5FmK9(n#)dfyg?Nbru?pXsD<1Cad0C_V3+(@u#5!@BfQcWh&j0TEW%C|8paXGy2f3rBFH=RBf?e)Jf( z5ie^u3~`a?L+FOQ-k>kmWjN!|1JA5g>f3OA-(OZyE=WlRqP_naGOz&^uXV?Ni4wm8 Z3;>r&bJa?K&H(@b002ovPDHLkV1mK=v6lb< literal 0 HcmV?d00001 diff --git a/app/img/icons/Search_2x.png b/app/img/icons/Search_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..e920e66e4ecd13ea0375275038d172c2d4737774 GIT binary patch literal 706 zcmV;z0zLhSP)lSlXadT3`U?orYoE^- zOlRwILJYzls3o8-!_rq^78}^hi5P?)s10B&%e@AGQEcElYhorn1v-pZ6j};tjGxN^ zp9sAz6#jObyf}+puN$OsU=dh=vmaxVMNreg9N^(;%7YzXNd3idM1&V&>J1nMVJL%L zJ=8u>Bc_L77tj(vLN$ueHpBQ?c|=uE4}1i6!qvJJhE0N$WLZl}g0&Q#c`;Q@N9NYp ziZLa|nu9C934DrYzlOM8jGyoYAK9{UCf`e+8sbVZj#|z|+E!?Y<6>Nt1MweQ4e`4e z*W^GfZKE3ECo!%=mU|u4_Hr&DNuL_xBjb76!Pib1p+3?UkQ=C0apv9swLHVN1?oza z&M<5n+{zu#7)f#fhkj+hJ{F`&U)m-yXgrsaLpa`sUNI{fmq`lmxIwy#wI>;y1b3M& zU_{aI-}x9S(qup7$^eMt{}O|=1Zo%PGhV$oxK^vcq)nPO)F7o$9;Rsemq0HQFBx?_ zmE1C6DC4gW-?>xc-r0W;U2yU#)>1j`=Xzeri5KCh1h6)u`q^Vg=P7>T!aye+#jHF@ zv5|>%-@GXjr#qjdNn$3wzvIKAicH0NZ5V0U=kq@c;k-07*qoM6N<$f`LRe761SM literal 0 HcmV?d00001 diff --git a/app/img/icons/Smile_1x.png b/app/img/icons/Smile_1x.png new file mode 100755 index 0000000000000000000000000000000000000000..29c057a316d47634803cc0bd47c193a8820bc2c0 GIT binary patch literal 773 zcmV+g1N!`lP)lX#At3D+TM`ryaBxnFbNo%`N%UT^ZN>v&SwYuS*M31GAzS(`Bl7_p zI0w!t(>bskIpjcwyYksmj9d_yb()tQm%pd^7)sBL5%BZ6a zZH-@A&us>Np_duE)!}#@jxU?d=1l||)8RD4Ic3z*hPI*p=2(yEFsZ1Yr`2{l;4XMn zuh$o&(dca~|0g|KtyThoM_EVN?EGsf-w*s5tKgcWkK;ZVroX!4H28o(UZc@S63!`; zjy5d>9hNW00yaw}W?Jj2_WCnqHHQpY*e~D$OW-)pNg87LpYh0{2Cygh`t ztXbU*taT9%89>K<@C%uKBAiP`T}B&gM!vJbfo~6bDki~u{oPk!MO!{)>{61g$R;hH z&RKlW)s)kTcbKbbk);e@O-`T7G~4GgE%drf{|Ybwh&~8<;o%eH00000NkvXXu0mjf D><3<_ literal 0 HcmV?d00001 diff --git a/app/img/icons/Smile_2x.png b/app/img/icons/Smile_2x.png new file mode 100755 index 0000000000000000000000000000000000000000..f6103f12997d4d1f628d14795278d3e321accef6 GIT binary patch literal 1384 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 literal 0 HcmV?d00001 diff --git a/app/img/icons/VideoIcon.png b/app/img/icons/VideoIcon.png new file mode 100755 index 0000000000000000000000000000000000000000..ea9482b45ff9c6b41abacf4a121a910ea810b590 GIT binary patch literal 321 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

6MdmZc zOwKY?dF1>vs{U(U{;MFs<3<-0Ld=PYzE6AyclSL2YF8Lsc&p!ID*d>|{#Vca8+!_S U(cPo?)Bpeg07*qoM6N<$g7e5})&Kwi literal 0 HcmV?d00001 diff --git a/app/img/icons/icon16.png b/app/img/icons/icon16.png new file mode 100644 index 0000000000000000000000000000000000000000..249892e1d4cd770af0597af23582dc2f5be8fc35 GIT binary patch literal 4262 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 literal 0 HcmV?d00001 diff --git a/app/img/placeholders/GroupAvatar1@2x.png b/app/img/placeholders/GroupAvatar1@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..99a1762ba18620f772b0e6f2377ef48d11d0a243 GIT binary patch literal 1834 zcmV+_2i5qAP){ZTg$|91xmOq&rBpfrq%3j=5aPzcyO>5%f*R#Jem&4-!h&#Rr473 z=F`GULrFa#fj=9(ry_MTyt(_X_xf_wco2~_4g7)Ev;9Go{o8Wtv%o(n9Nt@4me+4N z7ob5XzrOEw6iM039^5xr5DPWCI&gcqGiZ;RdA+uV`{I7FYuOi+?~_9{ocs&#c>32&?~k!DKdutL2;*^zvTzNm4eDVM*d90x(=e z-Rw}+Lv2qeuTZzyzWFHobUVF=De$5oih}fimR^WT+cQszN!=81jo}$Y8M0=nlIF*p zt=QrhcHG7A6n5W&Rq`%J7pkn4jcqiam86$L+QFcV5KvX~$aK4lXvqN*La>;l!P>yN z14CqW#!XOb6iZCfi6n)k$$H$d6j7mlOBb)UAGqDMdPfQ?rDkG>MS1Y!2Oi1ZArCHZ zKEcu~U5?p6fXd#X<4;_l4B)_mkyf)Ys=FXS!o3s6Pu?sbf;A6kRr7c}8^xIl#Wv+( z54a@k&c_@9mgSp{Zy^fAZ6+WDb4b-M6$BA`4hsZWvzVJ%pA~Kt!Hce;IN1=T#3fX& z__8NKRVU%phMR#U(Nv(Cl%#@7;5h{ZSexlOT)T%PRTyd#rd5_D1pyXqQfD5tMU}2# z!dknpiC|^4+y+R2WWdg%dP@q``l+Id6Il_v*JMjVedoA7Sz8yUq{>}M@5Bu&ua~G^ z-=DPK^Km7-pzddq0$;Lc$*9okoqCq{+^splYn7++WG zQFfoUa~-{BPwPu%8coUlu=TS$AHVCqK|FIU=w)3=l~dH)JdQJ`)h3DBK!MVO-cLiE z0toExv%*U@ZyAUCTb+(stU2OlOsN@W7jCG?2^vB*xw0Y51`F*ey{wkMllQW%91E;8 zUW+-cu^T0b0^H~6^Li1-XMK5xIh4{Gv@c?7e=qX{&%4NFV+S7=kRmyfB*=rMh#3u7 zzpDJSmD-J}>vD2Ge<+D-ybEJOd7OJTnUA8J*+JF1gAo@gHEpP=euQ(@YvMnW^>Ek{ zhafyJzKYVTJS=^W)#`-sjM9D}Zxe`76o)x9pa90L%%gl-jyOw1(rM;`Bcmaosxh}8 zAiBwuOe9#A*JsW8$TcQ-2$}x$|2nLSZw$Ah>q3bQ=03_nfNl!~$!%T%K9gc{pRfv8Hp5@~F^P1rUXy zhcJXaNVg$qCloB^RrBrYCK*X!o|td@ZU-0Eh~{e`s;tp^7rIx2PMr@wu6P!h26|Ap zPI}|^e*Q%YqkjMk&>1%=1WTZHc@&Y=om|$eDhjEaan(xfy{<*u)StHYupZD@nQ7?J z{!+r@`|#ZUcwwK$^raNj?H+ahXpb6f&k4Y+V0y5YlqNC!&_AN$wLTPwz6Ddc^$#{6 z4p@(-Q}2vhTj||OYKPo3!Nedi*}m5f*5|16`*wP7C-a!(1VCPm36{&*;MXQ0d$gQ$ z2(hBEwVmEw>s{UXK!)&vAc9qjTa_Y|>*3#lrpdaYq(ErA zIF}Pv0z?o56r>a4`tzqnAFHKc zYQrTDWkAON*cfTO0k($2inEaBu=wDxI4ll}!{V?wEIv3a4vWL$usAFZiw_P9d;BH9 Y015#QcyQl2J^%m!07*qoM6N<$f*KKU#sB~S literal 0 HcmV?d00001 diff --git a/app/img/placeholders/GroupAvatar2@2x.png b/app/img/placeholders/GroupAvatar2@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..85619a500c21ed3928d2975b991fd069c1a512f6 GIT binary patch literal 1781 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 M07*qoM6N<$f-{RPDF6Tf literal 0 HcmV?d00001 diff --git a/app/img/placeholders/GroupAvatar4@2x.png b/app/img/placeholders/GroupAvatar4@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..b87915554c0f0df661895d7002a55115f088dccf GIT binary patch literal 1680 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 B+>ihO literal 0 HcmV?d00001 diff --git a/app/img/placeholders/UserAvatar2@2x.png b/app/img/placeholders/UserAvatar2@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..ac3cb9ec33b147b91e33e48e1b0b0b6023fcf0b7 GIT binary patch literal 1569 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 literal 0 HcmV?d00001 diff --git a/app/img/placeholders/UserAvatar4@2x.png b/app/img/placeholders/UserAvatar4@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..7e697fbe5fd77a068a036645f8b8ac6118e611ff GIT binary patch literal 1477 zcmV;$1v>hPP)nUVkn&VUiy>EZd9lsQbT9UX+(h zr;)e%a?23Uh6jT##A%c2uvmLA|Ks7{KwwpMy>h~hx0Nm5!BJe@c|R_u#y}H(8J1Oj zxxBY&NIhHq>$Qhh;bCE!G`sHJlr%3lek?YuAkGjRG5HNQs)dGy=$y?@E6s|!$0`gls!X;nO6G7k%L{6sNCm5^nHB3H=E{mnOjs2+tfxFd zNLY0Xtl(9|)GS$&_+e4c5EU$`jf!R^sDW48sQ-%U4OOKDSQ7Etr+TD*8)b4?P*{pA z^LJvXoeJUe@b_S-r-$&}`B$Q%2n$Q^bNAUaabfY)#b3KZu{BF#jN|(%dDE2;792U} zO4R80k5Iu1;_UAmC(R1Rl0)T&iIA{tFN)Hfv#OQm#r4|9t9Y;yMxA<{8~RZu9;~{R zf|j@jz7-*LzjUyqR$!54Jai?Rc3_ciK&67EwX|z?KpELl!D7yJo^wOey^~b1Mn<0> zmQFlFgqp=)b+CwMh|qV;#|CrNfqK6rA*?ATnz8;j8|kXJB^p@T-%c>u9F`uK&L$@L zr;xt;P}hEZn`K4$bLA3ci|~M^(T5f@G~YOEFakwW?-Ri~pIZ}CKd9W0uG7OA&~d?{ z2_ujva2~K@g7r|37cj7D2iC)3O9JIGb?pFQQD^}sV8nH5ha1+^(wps!ffVzWIX+ke zO}&^|4JJ3IlOc2N$y!!Mw%Anq_HAzQC+gfa`0uCV{bMd*nvIMeyKuu&WXUr2RW7!W zy=7Rv$8PBUDd$nZDywS$LpE&{__<+i{CNNVt0GB<5349E+il{=X*;YKVL_o5Yp;Bty1MZZZjkU4mkCd@E^MEa)U)Jeb#>=mE*ziUb<1@1}W(_;oStm%5|DAH!{{GmgoMx@f~5ols??U z7k))X|4-ea@)$5=Q_GlIyKjk5KWma;kFeIVqU?z#a5(VJD<>EY2h)+U!w#}-VMR%f z$$>VBzGoZX{^@Q?O_66K17mwd`xq81B?7-z4gpX{XGk!SHo=_D$3tU_ioW{3fxOuS z47Y`~t7uQr#!%Nz#>4mfDR0AqNy74m{q7x&z|O#{>wWcNKKfOo`wdvgPLVxOUsduo z1=a>>6Fk8A3~7M+0jxVWymP|3chvGw&xq2~sd+Xvr8g640J>g#tD`6NOar$6pQTg2 zx~}O3*3$NwFO>cIg5>-)um51#Uc_^IrEn5w#f|O1z(R0v>x3PbcOuQ;v3nptwGs~U zEMT;^$F=< fb+BmUUjYUH0ko?d{(sl|00000NkvXXu0mjfR7=sd literal 0 HcmV?d00001 diff --git a/app/img/placeholders/UserAvatar5@2x.png b/app/img/placeholders/UserAvatar5@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..de984d8b91ce9aea13edc8d472d777ba97a5f825 GIT binary patch literal 1398 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 ZFaRT_xM3AOqzeE5002ovPDHLkV1g*r-d_L! literal 0 HcmV?d00001 diff --git a/app/img/placeholders/UserAvatar7@2x.png b/app/img/placeholders/UserAvatar7@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..bf6e73f16d948071df94c135ebc90925f5fa48eb GIT binary patch literal 1477 zcmV;$1v>hPP)+jE+lGTJO1PYddrC=#o3YLPU5GYtEV)XtC>ZVDnI;%uki-$Sn%rcG%_~WK+gS>>nn6~TK zheKyz=-UFTZMBm{80O_GJ~&Tv7<;aLH1_DVtOo~w?nkd6^`ii2= zSpPYtXpUz=Cy#n_W(e;F>HxZsmUWj(x`=efc5G`yV1awSjMCX^zWfyn#XpPiCMj5Yfm93sN?ESlBa!1*;EM=(djq%iuj!%34iMSY{uvn8u`p)k~S2b2(w@ zoNZo>9P#-!xpL{qwvYJqfld#L$qLIcsrT7TU0Tg@Et7O9Wa#kdA28=~gYSg^(eiyoGX zoG>727Jb!Wggirt?(o2~iK`A1M_O2Wu1#5q-*;_^OElnVKTL)miKholha(sLTTq|w zS?0%sNh!q1JVMGAVFd(NwdW29Hs2_w-O}};Wg@|PKlXN=!A9kVwyC2jFWs6;1q&yz zwscN;z>WykT|HjHz^WfuoG}|AMjZ{z4TQB!fXvP(U~F5P32WE2yWJTBQk=F8j1HD< z=ttvWhsn*mp+lT|l9uQoTkPt%+n+l_n>kz>ipzwnqNgJJuHg2u2?n$b$hZLU}aVPe(X_}`O#s`lKdi!G5WNE zybO!-H_v%Da%qx8Tv*p}b{Qt9)_oIai>#n2E~E8lwJo@FR8kL%tY}Ub(eW(Ekvr&6 zG%GGEAXU_K4W;*A`f2L#x`-ESbquR+n#(YS)vA}Jz16;5umvUwzO3`+l+GTP*8-yR zd0I4W{|%Dh#b5xe1J9XsS0h{(7TB7<{AD?<(XAp7teln61!tgWyN1Hq^Y@|i{C>*Qu)rmK4O5@?uEu@^{LIO`a!liB$NRss^%JllJB92) zG_AIM0^SDFCeW`x#@^#I-ao?v8wN|>MovG~GxG9qjk1< fDOfo2p8x{@8xELgk6Sc=00000NkvXXu0mjfHnqm6 literal 0 HcmV?d00001 diff --git a/app/img/placeholders/UserAvatar8@2x.png b/app/img/placeholders/UserAvatar8@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..614b75ef12530dc3909057a41e19834106ee5e90 GIT binary patch literal 1426 zcmV;D1#S9?P)PC$BIPt;5`lyzVM$mLmV_l?NdyuWifFz6f^D;{@~SGTrm9~)95JTpnySHd ztd3O)O94Q9lVovr{A(jNnphLVHQ~xsc8jp$b(Cz9Q@+`5+dRpkjYcCt=G-};bhiSl zZCn4lU-0~lKg^;OnmM&*_fs&{;XC;7DL8}FTLE6HKUZZ|4jdNuc@|}t->0b??_u4^ zt**`t;oY(@EwZxeR2_n)5ANS^jDf%cM-#7O?k7n14<7x+x5e1dg*U@?yY(JCJW~74 z2$lg{g@*;NQRV1vxGw87NX3R#@B)G(s&OL`8&*Q{0xtsy^o^*nz+07Rp%6;Wb5UVc zMNJ&R5%dkivkPKa;O4Q%L_9NW6>@2+Mo?JW9$?ji!sc6CG{VL{5)11;npLW4Ex z0T#CHW5MdB{@V(wS*q3pENpE?gEj7I8P3zueJ6)vn~lf>%?)w;Q#Lz&fy$AGFnJAi7W+jk9U9ouZp{u`E=G4MFV5{SsLSz8i1f!MG zll(Yf%Qfv!cIS&zI)nA!87CYtwY}{4{U5S8g9fm6MIpDd8sVj|>Z%6+nnfA0(VZd? ztOU!Ft(f7O=G44=((FuF;7YS32TWJU=)GsyseHh}k%33ErsvOHYrp*9aA#}SCnzAr z#^6t(8IEDitTW1Lr^14<2091gz-w?xmq)YER80kB*33R#(LRO+o|12pUN!+>M`w^= zLIZbZ&z)0N4Qj_7WcVBroEFye&>8IpDBaZUPtNiAl*6#VB}MBfk2B?F1pG{yZN`)F z^nRxQWT)f-Sdg6tOCS5FlIs-kHjp-fejTi5XzxY|dcenBKG g2}{E2UH%nd0L_}063LVE5dZ)H07*qoM6N<$f*p&cjQ{`u literal 0 HcmV?d00001 diff --git a/app/index.html b/app/index.html new file mode 100644 index 00000000..1a806b4c --- /dev/null +++ b/app/index.html @@ -0,0 +1,45 @@ + + + + + + Webogram + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/js/app.js b/app/js/app.js new file mode 100644 index 00000000..828de512 --- /dev/null +++ b/app/js/app.js @@ -0,0 +1,55 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +'use strict'; + +// window._testMode = 1; + + +// Declare app level module which depends on filters, and services +angular.module('myApp', [ + 'ngRoute', + 'ngAnimate', + 'ngSanitize', + 'ui.bootstrap', + 'myApp.filters', + 'myApp.services', + 'mtproto.services', + 'myApp.directives', + 'myApp.controllers' +]). +config(['$locationProvider', '$routeProvider', '$compileProvider', function($locationProvider, $routeProvider, $compileProvider) { + + var icons = {}, reverseIcons = {}, i, j, hex, name, dataItem, + ranges = [[0x1f600, 0x1f637], [0x270a, 0x270c], [0x1f446, 0x1f450]]; + + for (j in ranges) { + for (i = ranges[j][0]; i <= ranges[j][1]; i++) { + hex = i.toString(16); + if (dataItem = Config.Emoji[hex]) { + name = dataItem[1][0]; + icons[':' + name + ':'] = hex + '.png'; + reverseIcons[name] = dataItem[0]; + } + } + } + + $.emojiarea.path = 'vendor/gemoji/images'; + $.emojiarea.icons = icons; + $.emojiarea.reverseIcons = reverseIcons; + + $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|filesystem|chrome-extension):|data:image\//); + $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|file|mailto|blob|filesystem|chrome-extension):|data:image\//); + + + // $locationProvider.html5Mode(true); + $routeProvider.when('/', {templateUrl: 'partials/welcome.html', controller: 'AppWelcomeController'}); + $routeProvider.when('/login', {templateUrl: 'partials/login.html', controller: 'AppLoginController'}); + $routeProvider.when('/im', {templateUrl: 'partials/im.html', controller: 'AppIMController', reloadOnSearch: false}); + $routeProvider.otherwise({redirectTo: '/'}); + +}]); diff --git a/app/js/background.js b/app/js/background.js new file mode 100644 index 00000000..71f326cc --- /dev/null +++ b/app/js/background.js @@ -0,0 +1,18 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +chrome.app.runtime.onLaunched.addListener(function(launchData) { + chrome.app.window.create('../index.html', { + bounds: { + width: 1100, + height: 700 + }, + minWidth: 1100, + minHeight: 700, + frame: 'chrome' + }); +}); \ No newline at end of file diff --git a/app/js/controllers.js b/app/js/controllers.js new file mode 100644 index 00000000..15c8bcdd --- /dev/null +++ b/app/js/controllers.js @@ -0,0 +1,507 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +'use strict'; + +/* Controllers */ + +angular.module('myApp.controllers', []) + + .controller('AppWelcomeController', function($scope, $location, MtpApiManager) { + MtpApiManager.getUserID().then(function (id) { + if (id) { + $location.path('/im'); + } else { + $location.path('/login'); + } + }); + }) + + .controller('AppLoginController', function ($scope, $location, MtpApiManager) { + var dcID = 1; + + $scope.credentials = {}; + + function saveAuth (result) { + MtpApiManager.setUserAuth(dcID, { + expires: result.expires, + id: result.user.id + }); + + $location.path('/im'); + }; + + $scope.sendCode = function () { + MtpApiManager.invokeApi('auth.sendCode', { + phone_number: $scope.credentials.phone_number, + sms_type: 0, + api_id: 2496, + api_hash: '8da85b0d5bfe62527e5b244c209159c3' + }, {dcID: dcID}).then(function (sentCode) { + + $scope.credentials.phone_code_hash = sentCode.phone_code_hash; + $scope.credentials.phone_occupied = sentCode.phone_registered; + $scope.error = {}; + + }, function (error) { + dLog('sendCode', error); + if (error.code == 303) { + var newDcID = error.type.match(/^(PHONE_MIGRATE_|NETWORK_MIGRATE_)(\d+)/)[2]; + if (newDcID != dcID) { + dcID = newDcID; + $scope.sendCode(); + return; + } + } + switch (error.type) { + case 'PHONE_NUMBER_INVALID': + $scope.error = {field: 'phone'}; + break; + } + }); + } + + $scope.logIn = function (forceSignUp) { + var method = 'auth.signIn', params = { + phone_number: $scope.credentials.phone_number, + phone_code_hash: $scope.credentials.phone_code_hash, + phone_code: $scope.credentials.phone_code + }; + if (forceSignUp) { + method = 'auth.signUp'; + angular.extend(params, { + first_name: $scope.credentials.first_name, + last_name: $scope.credentials.last_name + }); + } + + MtpApiManager.invokeApi(method, params, {dcID: dcID}).then(saveAuth, function (error) { + if (error.code == 400 && error.type == 'PHONE_NUMBER_UNOCCUPIED') { + return $scope.logIn(true); + } else if (error.code == 400 && error.type == 'PHONE_NUMBER_UNOCCUPIED') { + return $scope.logIn(false); + } + + switch (error.type) { + case 'FIRSTNAME_INVALID': + $scope.error = {field: 'first_name'}; + break; + case 'LASTNAME_INVALID': + $scope.error = {field: 'last_name'}; + break; + case 'PHONE_CODE_INVALID': + $scope.error = {field: 'phone_code'}; + break; + } + }); + + }; + }) + + .controller('AppIMController', function ($scope, $location, $routeParams, MtpApiManager) { + + $scope.$on('$routeUpdate', updateCurDialog); + + $scope.isLoggedIn = true; + $scope.logOut = function () { + MtpApiManager.logOut().then(function () { + $location.path('/login'); + }); + } + + updateCurDialog(); + + + function updateCurDialog() { + $scope.curDialog = { + peer: $routeParams.p || false + }; + } + }) + + .controller('AppImDialogsController', function ($scope, $location, MtpApiManager, AppUsersManager, AppChatsManager, AppMessagesManager, AppPeersManager) { + + $scope.dialogs = []; + + var offset = 0, + hasMore = false, + limit = 20; + + + MtpApiManager.invokeApi('account.updateStatus', {offline: false}); + $scope.$on('dialogs_need_more', function () { + showMoreDialogs(); + }); + + $scope.$on('dialog_unread', function (e, dialog) { + angular.forEach($scope.dialogs, function(curDialog) { + if (curDialog.peerID == dialog.peerID) { + curDialog.unreadCount = dialog.unread_count; + } + }); + }); + + $scope.$on('dialogs_update', function (e, dialog) { + var pos = false; + angular.forEach($scope.dialogs, function(curDialog, curPos) { + if (curDialog.peerID == dialog.peerID) { + pos = curPos; + } + }); + + var wrappedDialog = AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count); + if (pos !== false) { + var prev = $scope.dialogs.splice(pos, 1); + wrappedDialog = angular.extend(prev[0], wrappedDialog); + offset++; + } + $scope.dialogs.unshift(wrappedDialog); + }); + + loadDialogs(); + + + + function loadDialogs (startLimit) { + offset = 0; + hasMore = false; + startLimit = startLimit || limit; + + AppMessagesManager.getDialogs(offset, startLimit).then(function (dialogsResult) { + offset += startLimit; + hasMore = offset < dialogsResult.count; + + $scope.dialogs = []; + angular.forEach(dialogsResult.dialogs, function (dialog) { + $scope.dialogs.push(AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count)); + }); + + $scope.$broadcast('ui_dialogs_change'); + }, function (error) { + if (error.code == 401) { + $location.path('/login'); + } + }); + } + + function showMoreDialogs () { + if (!hasMore || !offset) { + return; + } + + AppMessagesManager.getDialogs(offset, limit).then(function (dialogsResult) { + offset += limit; + hasMore = offset < dialogsResult.count; + + angular.forEach(dialogsResult.dialogs, function (dialog) { + $scope.dialogs.push(AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count)); + }); + + $scope.$broadcast('ui_dialogs_append'); + }); + } + + }) + + .controller('AppImHistoryController', function ($scope, $location, $timeout, MtpApiManager, AppUsersManager, AppChatsManager, AppMessagesManager, AppPeersManager, ApiUpdatesManager) { + + $scope.$watch('curDialog.peer', applyDialogSelect); + + ApiUpdatesManager.attach(); + + $scope.history = []; + $scope.typing = {}; + + var peerID, offset, hasMore, maxID, limit = 20; + + function applyDialogSelect (newPeer) { + newPeer = newPeer || $scope.curDialog.peer || ''; + + peerID = AppPeersManager.getPeerID(newPeer); + + $scope.curDialog.peerID = peerID; + $scope.curDialog.inputPeer = AppPeersManager.getInputPeer(newPeer); + + if (peerID) { + loadHistory(peerID); + } else { + showEmptyHistory(); + } + } + + function showMoreHistory () { + if (!hasMore || !offset) { + return; + } + + console.trace('load history'); + AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, limit).then(function (historyResult) { + offset += limit; + hasMore = offset < historyResult.count; + maxID = historyResult.history[historyResult.history.length - 1]; + + angular.forEach(historyResult.history, function (id) { + $scope.history.unshift(AppMessagesManager.wrapForHistory(id)); + }); + + $scope.$broadcast('ui_history_prepend'); + }, function () { + $scope.state = {error: true}; + }); + } + + function loadHistory () { + hasMore = false; + offset = 0; + maxID = 0; + + AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, limit).then(function (historyResult) { + offset += limit; + hasMore = offset < historyResult.count; + maxID = historyResult.history[historyResult.history.length - 1]; + + $scope.history = []; + angular.forEach(historyResult.history, function (id) { + $scope.history.push(AppMessagesManager.wrapForHistory(id)); + }); + $scope.history.reverse(); + + $scope.historyPeer = { + id: peerID, + data: AppPeersManager.getPeer(peerID), + photo: AppPeersManager.getPeerPhoto(peerID, 'User', 'Group') + }; + + $scope.typing = {}; + + MtpApiManager.getUserID().then(function (id) { + $scope.ownPhoto = AppUsersManager.getUserPhoto(id, 'User'); + }); + + $scope.state = {loaded: true}; + + $scope.$broadcast('ui_history_change'); + + AppMessagesManager.readHistory($scope.curDialog.inputPeer); + }, function () { + $scope.state = {error: true}; + }); + } + + function showEmptyHistory () { + $scope.state = {notSelected: true}; + $scope.history = []; + } + + + + var typingTimeouts = {}; + + $scope.$on('history_append', function (e, addedMessage) { + if (addedMessage.peerID == $scope.curDialog.peerID) { + dLog('append', addedMessage); + // console.trace(); + $scope.history.push(AppMessagesManager.wrapForHistory(addedMessage.messageID)); + $scope.typing = {}; + $scope.$broadcast('ui_history_append'); + offset++ + } + }); + + $scope.$on('apiUpdate', function (e, update) { + // dLog('on apiUpdate inline', update); + switch (update._) { + case 'updateUserTyping': + if (update.user_id == $scope.curDialog.peerID) { + $scope.typing = {user: AppUsersManager.getUser(update.user_id)}; + + $timeout.cancel(typingTimeouts[update.user_id]); + + typingTimeouts[update.user_id] = $timeout(function () { + $scope.typing = {}; + }, 6000); + } + break; + + case 'updateChatUserTyping': + if (-update.chat_id == $scope.curDialog.peerID) { + $scope.typing = {user: AppUsersManager.getUser(update.user_id)}; + + $timeout.cancel(typingTimeouts[update.user_id]); + + typingTimeouts[update.user_id] = $timeout(function () { + $scope.typing = {}; + }, 6000); + } + break; + } + }); + + $scope.$on('history_need_more', function () { + showMoreHistory(); + }); + + }) + + .controller('AppImPanelController', function($scope) { + $scope.$on('user_update', angular.noop); + }) + + .controller('AppImSendController', function ($scope, MtpApiManager, AppPeersManager, AppMessagesManager, ApiUpdatesManager, MtpApiFileManager) { + + $scope.$watch('curDialog.peer', resetDraft); + $scope.$on('user_update', angular.noop); + + $scope.draftMessage = {text: ''}; + + var lastTyping = false; + $scope.$watch('draftMessage.text', function (newVal) { + AppMessagesManager.readHistory($scope.curDialog.inputPeer); + + var now = +new Date(); + if (newVal === undefined || !newVal.length || now - lastTyping < 6000) { + return; + } + lastTyping = now; + + MtpApiManager.invokeApi('messages.setTyping', { + peer: $scope.curDialog.inputPeer, + typing: true + }); + }); + + $scope.sendMessage = sendMessage; + + $scope.$watch('draftMessage.files', onFilesSelected); + + function sendMessage (e) { + cancelEvent(e); + + var text = $scope.draftMessage.text; + + if ($scope.draftMessage.sending || !text.length) { + return false; + } + + text = text.replace(/:\s*(.+?)\s*:/g, function (all, name) { + var utfChar = $.emojiarea.reverseIcons[name]; + if (utfChar !== undefined) { + return utfChar; + } + return all; + }); + + $scope.draftMessage.sending = true; + + MtpApiManager.invokeApi('messages.sendMessage', { + peer: $scope.curDialog.inputPeer, + message: text, + random_id: $scope.draftMessage.randomID + }).then(function (result) { + + if (ApiUpdatesManager.saveSeq(result.seq)) { + + MtpApiManager.getUserID().then(function (fromID) { + ApiUpdatesManager.saveUpdate({ + _: 'updateNewMessage', + message: { + _: 'message', + id: result.id, + from_id: fromID, + to_id: AppPeersManager.getOutputPeer($scope.curDialog.peerID), + out: true, + unread: true, + date: result.date, + message: text, + media: {_: 'messageMediaEmpty'} + }, + pts: result.pts + }); + }); + + } + + $scope.$broadcast('ui_message_send'); + + resetDraft(); + }, function () { + delete $scope.draftMessage.sending; + }); + + return cancelEvent(e); + } + + + function resetDraft () { + $scope.draftMessage = { + randomID: [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)], + text: '' + }; + } + + function onFilesSelected (newVal) { + if (!angular.isArray(newVal) || !newVal.length) { + return; + } + + for (var i = 0; i < newVal.length; i++) { + (function (file, randomID) { + MtpApiFileManager.uploadFile(file).then(function (inputFile) { + var inputMedia; + if (file.type == 'image/jpeg') { + inputMedia = {_: 'inputMediaUploadedPhoto', file: inputFile}; + } else { + inputMedia = {_: 'inputMediaUploadedDocument', file: inputFile, file_name: file.name, mime_type: file.type}; + } + MtpApiManager.invokeApi('messages.sendMedia', { + peer: $scope.curDialog.inputPeer, + media: inputMedia, + random_id: randomID + }).then(function (result) { + + if (ApiUpdatesManager.saveSeq(result.seq)) { + ApiUpdatesManager.saveUpdate({ + _: 'updateNewMessage', + message: result.message, + pts: result.pts + }); + } + + $scope.$broadcast('ui_message_send'); + }); + }, function (error) { + dLog('upload error', error); + }) + + })(newVal[i], [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)]); + } + } + + }) + + .controller('PhotoModalController', function ($scope, AppPhotosManager) { + $scope.photo = AppPhotosManager.wrapForFull($scope.photoID); + }) + + .controller('VideoModalController', function ($scope, AppVideoManager) { + $scope.video = AppVideoManager.wrapForFull($scope.videoID); + }) + + .controller('UserModalController', function ($scope, $location, AppUsersManager) { + $scope.user = AppUsersManager.wrapForFull($scope.userID); + $scope.goToHistory = function () { + $scope.$close(); + $location.url('/im?p=' + $scope.user.peerString); + }; + }) + + .controller('ChatModalController', function ($scope, AppUsersManager, AppChatsManager, fullChat) { + $scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, fullChat); + }) + + + diff --git a/app/js/directives.js b/app/js/directives.js new file mode 100644 index 00000000..482a445e --- /dev/null +++ b/app/js/directives.js @@ -0,0 +1,512 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +'use strict'; + +/* Directives */ + + +angular.module('myApp.directives', ['myApp.filters']) + .directive('myDialog', function() { + return { + restrict: 'AE', + scope: true, + translude: false, + templateUrl: 'partials/dialog.html' + }; + }) + + .directive('myMessage', function() { + return { + restrict: 'AE', + scope: true, + translude: false, + templateUrl: 'partials/message.html' + }; + }) + + .directive('myDialogsList', function($window, $timeout) { + + return { + link: link + }; + + function link (scope, element, attrs) { + var dialogsWrap = $('.im_dialogs_wrap')[0], + scrollableWrap = $('.im_dialogs_scrollable_wrap')[0], + // dialogsSearch = $('im_dialogs_search')[0], + moreNotified = false; + + onContentLoaded(function () { + $(dialogsWrap).nanoScroller({preventPageScrolling: true, tabIndex: -1}); + }); + + var updateScroller = function () { + onContentLoaded(function () { + $(dialogsWrap).nanoScroller(); + }); + } + + scope.$on('ui_dialogs_prepend', updateScroller); + + + scope.$on('ui_dialogs_append', function () { + onContentLoaded(function () { + updateScroller(); + moreNotified = false; + }); + }); + + scope.$on('ui_dialogs_change', function () { + onContentLoaded(function () { + updateScroller(); + moreNotified = false; + }); + }); + + $(scrollableWrap).on('scroll', function (e) { + if (!moreNotified && scrollableWrap.scrollTop >= scrollableWrap.scrollHeight - scrollableWrap.clientHeight - 300) { + scope.$emit('dialogs_need_more'); + moreNotified = true; + } + }); + + + function updateSizes () { + $(element).css({ + height: $($window).height() - 162 + }); + } + + $($window).on('resize', updateSizes); + + updateSizes(); + }; + + }) + + .directive('myHistory', function ($window, $timeout) { + + return { + link: link + }; + + function link (scope, element, attrs) { + var historyWrap = $('.im_history_wrap')[0], + scrollableWrap = $('.im_history_scrollable_wrap')[0], + scrollable = $('.im_history_scrollable')[0], + panelWrap = $('.im_history_panel_wrap', element)[0], + sendFormWrap = $('.im_send_form_wrap', element)[0], + moreNotified = false; + + onContentLoaded(function () { + $(historyWrap).nanoScroller({preventPageScrolling: true, scroll: 'bottom', tabIndex: -1}); + }); + + var updateScroller = function (delay) { + $timeout(function () { + $(historyWrap).nanoScroller(); + }, delay || 0); + } + + scope.$on('ui_history_append', function () { + var st = scrollableWrap.scrollTop; + $(scrollableWrap).addClass('im_history_to_bottom'); + if (atBottom) { + onContentLoaded(function () { + $(scrollableWrap).removeClass('im_history_to_bottom'); + updateSizes(); + $(historyWrap).nanoScroller({scrollBottom: 0}); + // scrollableWrap.scrollTop = st; + // $(scrollableWrap).animate({ + // scrollTop: scrollableWrap.scrollHeight - scrollableWrap.clientHeight + // }, 200); + updateScroller(); + }); + } + }); + + scope.$on('ui_history_change', function () { + $(scrollableWrap).addClass('im_history_to_bottom'); + $(scrollable).css({bottom: 0}); + onContentLoaded(function () { + $(scrollableWrap).removeClass('im_history_to_bottom'); + $(scrollable).css({bottom: ''}); + updateSizes(); + $(historyWrap).nanoScroller(); + $(historyWrap).nanoScroller({scrollBottom: 0}); + updateScroller(100); + moreNotified = false; + }); + }); + + + scope.$on('ui_history_prepend', function () { + var sh = scrollableWrap.scrollHeight, + st = scrollableWrap.scrollTop, + ch = scrollableWrap.clientHeight; + + $(scrollableWrap).addClass('im_history_to_bottom'); + $(scrollable).css({bottom: -(sh - st - ch)}); + + onContentLoaded(function () { + $(scrollableWrap).removeClass('im_history_to_bottom'); + $(scrollable).css({bottom: ''}); + $(historyWrap).nanoScroller(); + $(historyWrap).nanoScroller({scrollTop: st + scrollableWrap.scrollHeight - sh}); + + // updateScroller(); + updateScroller(50); + moreNotified = false; + }); + }); + + var atBottom = true; + $(scrollableWrap).on('scroll', function (e) { + atBottom = scrollableWrap.scrollTop >= scrollableWrap.scrollHeight - scrollableWrap.clientHeight; + + if (!moreNotified && scrollableWrap.scrollTop <= 300) { + moreNotified = true; + scope.$emit('history_need_more'); + } + }); + + function updateSizes () { + $(historyWrap).css({ + height: $($window).height() - panelWrap.offsetHeight - sendFormWrap.offsetHeight - 90 + }); + if (atBottom) { + onContentLoaded(function () { + $(historyWrap).nanoScroller({scroll: 'bottom'}); + }); + } + updateScroller(100); + } + + $($window).on('resize', updateSizes); + + onContentLoaded(updateSizes); + } + + }) + + .directive('mySendForm', function ($timeout) { + + return { + link: link, + scope: { + draftMessage: '=' + } + }; + + function link (scope, element, attrs) { + var messageField = $('textarea', element)[0], + fileSelect = $('input', element)[0], + dropbox = $('.im_send_dropbox_wrap', element)[0], + emojiButton = $('.im_emoji_btn', element)[0], + editorElement = messageField, + dragStarted, dragTimeout, + emojiArea = $(messageField).emojiarea({button: emojiButton}), + emojiMenu = $('.emoji-menu')[0], + richTextarea = $('.emoji-wysiwyg-editor', element)[0]; + + if (richTextarea) { + editorElement = richTextarea; + $(richTextarea).addClass('form-control'); + $(richTextarea).attr('placeholder', $(messageField).attr('placeholder')); + } + + // $(emojiMenu.firstChild).addClass('nano').nanoScroller({preventPageScrolling: true, tabIndex: -1}); + + + $(fileSelect).on('change', function () { + scope.$apply(function () { + scope.draftMessage.files = Array.prototype.slice.call(fileSelect.files); + }); + }); + + var sendOnEnter = true; + $(editorElement).on('keydown', function (e) { + if (e.keyCode != 13) { + return; + } + var submit = false; + if (sendOnEnter && !e.shiftKey) { + submit = true; + } else if (!sendOnEnter && (e.ctrlKey || e.metaKey)) { + submit = true; + } + + if (submit) { + $(element).trigger('submit'); + dLog('after submit'); + return cancelEvent(e); + } + }); + + if (richTextarea) { + scope.$watch('draftMessage.text', function (newVal) { + if (!newVal.length && !messageField.value.length) { + $timeout(function () { + $(richTextarea).html(''); + }, 0); + } + }); + } + + + $('body').on('dragenter dragleave dragover drop', onDragDropEvent); + + scope.$on('ui_history_change', focusField); + scope.$on('ui_message_send', focusField); + + scope.$on('$destroy', function cleanup() { + $('body').off('dragenter dragleave dragover drop', onDragDropEvent); + }); + + focusField(); + + function focusField () { + onContentLoaded(function () { + $(editorElement).focus(); + }); + } + + function onDragDropEvent(e) { + var dragStateChanged = false; + if (!dragStarted || dragStarted == 1) { + dragStarted = checkDragEvent(e) ? 2 : 1; + dragStateChanged = true; + } + if (dragStarted == 2) { + if (dragTimeout) { + setTimeout(function () { + clearTimeout(dragTimeout); + dragTimeout = false; + }, 0); + } + + if (e.type == 'dragenter' || e.type == 'dragover') { + if (dragStateChanged) { + $(dropbox) + .css({height: $(editorElement).height() + 12, width: $(editorElement).width() + 12}) + .show(); + } + } else { + if (e.type == 'drop') { + scope.$apply(function () { + scope.draftMessage.files = Array.prototype.slice.call(e.originalEvent.dataTransfer.files); + }); + } + dragTimeout = setTimeout(function () { + $(dropbox).hide(); + dragStarted = false; + dragTimeout = false; + }, 300); + } + } + + return cancelEvent(e); + }; + } + + }) + + .directive('myLoadThumb', function(MtpApiFileManager) { + + return { + link: link, + scope: { + thumb: '=' + } + }; + + function link (scope, element, attrs) { + + scope.$watch('thumb.location', function (newVal) { + if (!scope.thumb) dLog(222, scope); + if (!scope.thumb.location) { + element.attr('src', scope.thumb.placeholder || ''); + return; + } + + MtpApiFileManager.downloadSmallFile(scope.thumb.location, scope.thumb.size).then(function (url) { + element.attr('src', url); + }, function (e) { + dLog('Download image failed', e, scope.thumb.location); + element.attr('src', scope.thumb.placeholder || ''); + }); + }) + + } + + }) + + .directive('myLoadFullPhoto', function(MtpApiFileManager) { + + return { + link: link, + transclude: true, + template: + '', + scope: { + fullPhoto: '=', + thumbLocation: '=' + } + }; + + function link (scope, element, attrs) { + var imgElement = $('img', element), + fullLoaded = false; + + + if (!scope.fullPhoto.location) { + imgElement.attr('src', scope.fullPhoto.placeholder || ''); + return; + } + + MtpApiFileManager.getCachedFile(scope.thumbLocation).then(function (url) { + if (!fullLoaded) { + imgElement + .attr('src', url) + .addClass('thumb_blurred') + .addClass('thumb_blur_animation'); + } + }); + + var apiPromise; + if (scope.fullPhoto.size) { + var inputLocation = { + _: 'inputFileLocation', + volume_id: scope.fullPhoto.location.volume_id, + local_id: scope.fullPhoto.location.local_id, + secret: scope.fullPhoto.location.secret + }; + apiPromise = MtpApiFileManager.downloadFile(scope.fullPhoto.location.dc_id, inputLocation, scope.fullPhoto.size); + } else { + apiPromise = MtpApiFileManager.downloadSmallFile(scope.fullPhoto.location); + } + + scope.progress = {enabled: true, percent: 1}; + + apiPromise.then(function (url) { + fullLoaded = true; + scope.progress.enabled = false; + imgElement + .attr('src', url) + .removeClass('thumb_blurred'); + + }, function (e) { + dLog('Download image failed', e, scope.fullPhoto.location); + scope.progress.enabled = false; + imgElement + .attr('src', scope.fullPhoto.placeholder || '') + .removeClass('thumb_blurred'); + + }, function (progress) { + scope.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total)); + }); + } + + }) + + + .directive('myLoadVideo', function($sce, MtpApiFileManager) { + + return { + link: link, + transclude: true, + template: + '
\ +
\ +
\ +
\ +
\ + {{progress.percent}}% Complete (success)\ +
\ +
\ +
\ +
\ +
\ + \ +
\ +
\ + \ +
\ +
', + scope: { + video: '=' + } + }; + + function link (scope, element, attrs) { + + scope.progress = {enabled: true, percent: 1}; + scope.player = {}; + + var inputLocation = { + _: 'inputVideoFileLocation', + id: scope.video.id, + access_hash: scope.video.access_hash + }; + + MtpApiFileManager.downloadFile(scope.video.dc_id, inputLocation, scope.video.size).then(function (url) { + scope.progress.enabled = false; + // scope.progress = {enabled: true, percent: 50}; + scope.player.src = $sce.trustAsResourceUrl(url); + }, function (e) { + dLog('Download image failed', e, scope.fullPhoto.location); + scope.progress.enabled = false; + scope.player.src = ''; + }, function (progress) { + scope.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total)); + }); + } + + }) + + .directive('myMapPoint', function(ExternalResourcesManager) { + + return { + link: link, + scope: { + point: '=' + } + }; + + function link (scope, element, attrs) { + + var apiKey = 'AIzaSyC32ij28dCa0YzEV_HqbWfIwTZQql-RNS0'; + + var src = 'https://maps.googleapis.com/maps/api/staticmap?sensor=false¢er=' + scope.point['lat'] + ',' + scope.point['long'] + '&zoom=13&size=200x100&scale=2&key=' + apiKey; + + ExternalResourcesManager.downloadImage(src).then(function (url) { + element.append(''); + }); + + element.attr('href','https://maps.google.com/?q=' + scope.point['lat'] + ',' + scope.point['long']); + element.attr('target','_blank'); + } + + }) diff --git a/app/js/filters.js b/app/js/filters.js new file mode 100644 index 00000000..a2914d42 --- /dev/null +++ b/app/js/filters.js @@ -0,0 +1,126 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +'use strict'; + +/* Filters */ + +angular.module('myApp.filters', []) + + .filter('userName', [function() { + return function (user) { + if (!user || !user.first_name && !user.last_name) { + return 'DELETED'; + } + return user.first_name + ' ' + user.last_name; + } + }]) + + .filter('userFirstName', [function() { + return function (user) { + if (!user || !user.first_name && !user.last_name) { + return 'DELETED'; + } + return user.first_name || user.last_name; + } + }]) + + .filter('userStatus', ['$filter', function($filter) { + return function (user) { + if (!user || !user.status || user.status._ == 'userStatusEmpty') { + return 'offline'; + } + if (user.status._ == 'userStatusOnline') { + return 'online'; + } + + return 'last seen ' + $filter('relativeTime')(user.status.was_online); + } + }]) + + .filter('chatTitle', [function() { + return function (chat) { + if (!chat || !chat.title) { + return 'DELETED'; + } + return chat.title; + } + }]) + + .filter('dateOrTime', ['$filter', function($filter) { + return function (timestamp) { + var ticks = timestamp * 1000, + diff = Math.abs(+new Date() - ticks), + format = 'HH:mm'; + + if (diff > 518400000) { // 6 days + format = 'shortDate'; + } + else if (diff > 43200000) { // 12 hours + format = 'EEE'; + } + return $filter('date')(ticks, format); + } + }]) + + .filter('duration', [function() { + return function (duration) { + var secs = duration % 60, + mins = Math.floor((duration - secs) / 60.0); + + if (secs < 10) { + secs = '0' + secs; + } + + return mins + ':' + secs; + } + }]) + + .filter('phoneNumber', [function() { + return function (phoneRaw) { + if (phoneRaw.charAt(0) == '7') { + return '+' + phoneRaw.charAt(0) + ' (' + phoneRaw.substr(1, 3) + ') ' + phoneRaw.substr(4, 3) + '-' + phoneRaw.substr(7, 2) + '-' + phoneRaw.substr(9, 2); + } + return '+' + phoneRaw; + } + }]) + + .filter('formatSize', [function () { + return function (size) { + return Math.round(size / 1024) + 'Kb'; + } + }]) + + .filter('nl2br', [function () { + return function (text) { + return text.replace(/\n/g, '
'); + } + }]) + + .filter('richText', ['$filter', function ($filter) { + return function (text) { + return $filter('linky')(text, '_blank').replace(/\n| /g, '
'); + } + }]) + + .filter('relativeTime', ['$filter', function($filter) { + return function (timestamp) { + var ticks = timestamp * 1000, + diff = Math.abs(+new Date() - ticks); + + if (diff < 60000) { + return 'just now'; + } + if (diff < 3000000) { + return Math.ceil(diff / 60000) + ' minutes ago'; + } + if (diff < 10000000) { + return Math.ceil(diff / 3600000) + ' hours ago'; + } + return $filter('dateOrTime')(timestamp); + } + }]) \ No newline at end of file diff --git a/app/js/lib/aes_worker.js b/app/js/lib/aes_worker.js new file mode 100644 index 00000000..fe1ff83b --- /dev/null +++ b/app/js/lib/aes_worker.js @@ -0,0 +1,21 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +importScripts('mtproto.js', '../../vendor/jsbn/jsbn_combined.js', '../../vendor/cryptoJS/crypto.js'); + +onmessage = function (e) { + // console.log('AES worker in', e.data); + var taskID = e.data.taskID, + result; + + if (e.data.task == 'encrypt') { + result = aesEncrypt(e.data.bytes, e.data.keyBytes, e.data.ivBytes); + } else { + result = aesDecrypt(e.data.encryptedBytes, e.data.keyBytes, e.data.ivBytes); + } + postMessage({taskID: taskID, result: result}); +} \ No newline at end of file diff --git a/app/js/lib/config.js b/app/js/lib/config.js new file mode 100644 index 00000000..7f7ef7ad --- /dev/null +++ b/app/js/lib/config.js @@ -0,0 +1,14 @@ +Config = window.Config || {}; +Config.Schema = Config.Schema || {}; + + +Config.Schema.MTProto = {"constructors":[{"id":"481674261","predicate":"vector","params":[],"type":"Vector t"},{"id":"85337187","predicate":"resPQ","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"pq","type":"bytes"},{"name":"server_public_key_fingerprints","type":"Vector"}],"type":"ResPQ"},{"id":"-2083955988","predicate":"p_q_inner_data","params":[{"name":"pq","type":"bytes"},{"name":"p","type":"bytes"},{"name":"q","type":"bytes"},{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"new_nonce","type":"int256"}],"type":"P_Q_inner_data"},{"id":"2043348061","predicate":"server_DH_params_fail","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"new_nonce_hash","type":"int128"}],"type":"Server_DH_Params"},{"id":"-790100132","predicate":"server_DH_params_ok","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"encrypted_answer","type":"bytes"}],"type":"Server_DH_Params"},{"id":"-1249309254","predicate":"server_DH_inner_data","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"g","type":"int"},{"name":"dh_prime","type":"bytes"},{"name":"g_a","type":"bytes"},{"name":"server_time","type":"int"}],"type":"Server_DH_inner_data"},{"id":"1715713620","predicate":"client_DH_inner_data","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"retry_id","type":"long"},{"name":"g_b","type":"bytes"}],"type":"Client_DH_Inner_Data"},{"id":"1003222836","predicate":"dh_gen_ok","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"new_nonce_hash1","type":"int128"}],"type":"Set_client_DH_params_answer"},{"id":"1188831161","predicate":"dh_gen_retry","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"new_nonce_hash2","type":"int128"}],"type":"Set_client_DH_params_answer"},{"id":"-1499615742","predicate":"dh_gen_fail","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"new_nonce_hash3","type":"int128"}],"type":"Set_client_DH_params_answer"},{"id":"-212046591","predicate":"rpc_result","params":[{"name":"req_msg_id","type":"long"},{"name":"result","type":"Object"}],"type":"RpcResult"},{"id":"558156313","predicate":"rpc_error","params":[{"name":"error_code","type":"int"},{"name":"error_message","type":"string"}],"type":"RpcError"},{"id":"1579864942","predicate":"rpc_answer_unknown","params":[],"type":"RpcDropAnswer"},{"id":"-847714938","predicate":"rpc_answer_dropped_running","params":[],"type":"RpcDropAnswer"},{"id":"-1539647305","predicate":"rpc_answer_dropped","params":[{"name":"msg_id","type":"long"},{"name":"seq_no","type":"int"},{"name":"bytes","type":"int"}],"type":"RpcDropAnswer"},{"id":"155834844","predicate":"future_salt","params":[{"name":"valid_since","type":"int"},{"name":"valid_until","type":"int"},{"name":"salt","type":"long"}],"type":"FutureSalt"},{"id":"-1370486635","predicate":"future_salts","params":[{"name":"req_msg_id","type":"long"},{"name":"now","type":"int"},{"name":"salts","type":"vector"}],"type":"FutureSalts"},{"id":"880243653","predicate":"pong","params":[{"name":"msg_id","type":"long"},{"name":"ping_id","type":"long"}],"type":"Pong"},{"id":"-501201412","predicate":"destroy_session_ok","params":[{"name":"session_id","type":"long"}],"type":"DestroySessionRes"},{"id":"1658015945","predicate":"destroy_session_none","params":[{"name":"session_id","type":"long"}],"type":"DestroySessionRes"},{"id":"-1631450872","predicate":"new_session_created","params":[{"name":"first_msg_id","type":"long"},{"name":"unique_id","type":"long"},{"name":"server_salt","type":"long"}],"type":"NewSession"},{"id":"1945237724","predicate":"msg_container","params":[{"name":"messages","type":"vector<%Message>"}],"type":"MessageContainer"},{"id":"1538843921","predicate":"message","params":[{"name":"msg_id","type":"long"},{"name":"seqno","type":"int"},{"name":"bytes","type":"int"},{"name":"body","type":"Object"}],"type":"Message"},{"id":"-530561358","predicate":"msg_copy","params":[{"name":"orig_message","type":"Message"}],"type":"MessageCopy"},{"id":"812830625","predicate":"gzip_packed","params":[{"name":"packed_data","type":"bytes"}],"type":"Object"},{"id":"1658238041","predicate":"msgs_ack","params":[{"name":"msg_ids","type":"Vector"}],"type":"MsgsAck"},{"id":"-1477445615","predicate":"bad_msg_notification","params":[{"name":"bad_msg_id","type":"long"},{"name":"bad_msg_seqno","type":"int"},{"name":"error_code","type":"int"}],"type":"BadMsgNotification"},{"id":"-307542917","predicate":"bad_server_salt","params":[{"name":"bad_msg_id","type":"long"},{"name":"bad_msg_seqno","type":"int"},{"name":"error_code","type":"int"},{"name":"new_server_salt","type":"long"}],"type":"BadMsgNotification"},{"id":"2105940488","predicate":"msg_resend_req","params":[{"name":"msg_ids","type":"Vector"}],"type":"MsgResendReq"},{"id":"-630588590","predicate":"msgs_state_req","params":[{"name":"msg_ids","type":"Vector"}],"type":"MsgsStateReq"},{"id":"81704317","predicate":"msgs_state_info","params":[{"name":"req_msg_id","type":"long"},{"name":"info","type":"bytes"}],"type":"MsgsStateInfo"},{"id":"-1933520591","predicate":"msgs_all_info","params":[{"name":"msg_ids","type":"Vector"},{"name":"info","type":"bytes"}],"type":"MsgsAllInfo"},{"id":"661470918","predicate":"msg_detailed_info","params":[{"name":"msg_id","type":"long"},{"name":"answer_msg_id","type":"long"},{"name":"bytes","type":"int"},{"name":"status","type":"int"}],"type":"MsgDetailedInfo"},{"id":"-2137147681","predicate":"msg_new_detailed_info","params":[{"name":"answer_msg_id","type":"long"},{"name":"bytes","type":"int"},{"name":"status","type":"int"}],"type":"MsgDetailedInfo"}],"methods":[{"id":"1615239032","method":"req_pq","params":[{"name":"nonce","type":"int128"}],"type":"ResPQ"},{"id":"-686627650","method":"req_DH_params","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"p","type":"bytes"},{"name":"q","type":"bytes"},{"name":"public_key_fingerprint","type":"long"},{"name":"encrypted_data","type":"bytes"}],"type":"Server_DH_Params"},{"id":"-184262881","method":"set_client_DH_params","params":[{"name":"nonce","type":"int128"},{"name":"server_nonce","type":"int128"},{"name":"encrypted_data","type":"bytes"}],"type":"Set_client_DH_params_answer"},{"id":"1491380032","method":"rpc_drop_answer","params":[{"name":"req_msg_id","type":"long"}],"type":"RpcDropAnswer"},{"id":"-1188971260","method":"get_future_salts","params":[{"name":"num","type":"int"}],"type":"FutureSalts"},{"id":"2059302892","method":"ping","params":[{"name":"ping_id","type":"long"}],"type":"Pong"},{"id":"-213746804","method":"ping_delay_disconnect","params":[{"name":"ping_id","type":"long"},{"name":"disconnect_delay","type":"int"}],"type":"Pong"},{"id":"-414113498","method":"destroy_session","params":[{"name":"session_id","type":"long"}],"type":"DestroySessionRes"},{"id":"-1835453025","method":"http_wait","params":[{"name":"max_delay","type":"int"},{"name":"wait_after","type":"int"},{"name":"max_wait","type":"int"}],"type":"HttpWait"}]}; + + + + +Config.Schema.API = {"constructors":[{"id":"-1132882121","predicate":"boolFalse","params":[],"type":"Bool"},{"id":"-1720552011","predicate":"boolTrue","params":[],"type":"Bool"},{"id":"481674261","predicate":"vector","params":[],"type":"Vector t"},{"id":"-994444869","predicate":"error","params":[{"name":"code","type":"int"},{"name":"text","type":"string"}],"type":"Error"},{"id":"1450380236","predicate":"null","params":[],"type":"Null"},{"id":"2134579434","predicate":"inputPeerEmpty","params":[],"type":"InputPeer"},{"id":"2107670217","predicate":"inputPeerSelf","params":[],"type":"InputPeer"},{"id":"270785512","predicate":"inputPeerContact","params":[{"name":"user_id","type":"int"}],"type":"InputPeer"},{"id":"-1690012891","predicate":"inputPeerForeign","params":[{"name":"user_id","type":"int"},{"name":"access_hash","type":"long"}],"type":"InputPeer"},{"id":"396093539","predicate":"inputPeerChat","params":[{"name":"chat_id","type":"int"}],"type":"InputPeer"},{"id":"-1182234929","predicate":"inputUserEmpty","params":[],"type":"InputUser"},{"id":"-138301121","predicate":"inputUserSelf","params":[],"type":"InputUser"},{"id":"-2031530139","predicate":"inputUserContact","params":[{"name":"user_id","type":"int"}],"type":"InputUser"},{"id":"1700689151","predicate":"inputUserForeign","params":[{"name":"user_id","type":"int"},{"name":"access_hash","type":"long"}],"type":"InputUser"},{"id":"-208488460","predicate":"inputPhoneContact","params":[{"name":"client_id","type":"long"},{"name":"phone","type":"string"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"}],"type":"InputContact"},{"id":"-181407105","predicate":"inputFile","params":[{"name":"id","type":"long"},{"name":"parts","type":"int"},{"name":"name","type":"string"},{"name":"md5_checksum","type":"string"}],"type":"InputFile"},{"id":"-1771768449","predicate":"inputMediaEmpty","params":[],"type":"InputMedia"},{"id":"767900285","predicate":"inputMediaUploadedPhoto","params":[{"name":"file","type":"InputFile"}],"type":"InputMedia"},{"id":"-1893027092","predicate":"inputMediaPhoto","params":[{"name":"id","type":"InputPhoto"}],"type":"InputMedia"},{"id":"-104578748","predicate":"inputMediaGeoPoint","params":[{"name":"geo_point","type":"InputGeoPoint"}],"type":"InputMedia"},{"id":"-1494984313","predicate":"inputMediaContact","params":[{"name":"phone_number","type":"string"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"}],"type":"InputMedia"},{"id":"1212668202","predicate":"inputMediaUploadedVideo","params":[{"name":"file","type":"InputFile"},{"name":"duration","type":"int"},{"name":"w","type":"int"},{"name":"h","type":"int"}],"type":"InputMedia"},{"id":"-433544891","predicate":"inputMediaUploadedThumbVideo","params":[{"name":"file","type":"InputFile"},{"name":"thumb","type":"InputFile"},{"name":"duration","type":"int"},{"name":"w","type":"int"},{"name":"h","type":"int"}],"type":"InputMedia"},{"id":"2130852582","predicate":"inputMediaVideo","params":[{"name":"id","type":"InputVideo"}],"type":"InputMedia"},{"id":"480546647","predicate":"inputChatPhotoEmpty","params":[],"type":"InputChatPhoto"},{"id":"-1809496270","predicate":"inputChatUploadedPhoto","params":[{"name":"file","type":"InputFile"},{"name":"crop","type":"InputPhotoCrop"}],"type":"InputChatPhoto"},{"id":"-1293828344","predicate":"inputChatPhoto","params":[{"name":"id","type":"InputPhoto"},{"name":"crop","type":"InputPhotoCrop"}],"type":"InputChatPhoto"},{"id":"-457104426","predicate":"inputGeoPointEmpty","params":[],"type":"InputGeoPoint"},{"id":"-206066487","predicate":"inputGeoPoint","params":[{"name":"lat","type":"double"},{"name":"long","type":"double"}],"type":"InputGeoPoint"},{"id":"483901197","predicate":"inputPhotoEmpty","params":[],"type":"InputPhoto"},{"id":"-74070332","predicate":"inputPhoto","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputPhoto"},{"id":"1426648181","predicate":"inputVideoEmpty","params":[],"type":"InputVideo"},{"id":"-296249774","predicate":"inputVideo","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputVideo"},{"id":"342061462","predicate":"inputFileLocation","params":[{"name":"volume_id","type":"long"},{"name":"local_id","type":"int"},{"name":"secret","type":"long"}],"type":"InputFileLocation"},{"id":"1023632620","predicate":"inputVideoFileLocation","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputFileLocation"},{"id":"-1377390588","predicate":"inputPhotoCropAuto","params":[],"type":"InputPhotoCrop"},{"id":"-644787419","predicate":"inputPhotoCrop","params":[{"name":"crop_left","type":"double"},{"name":"crop_top","type":"double"},{"name":"crop_width","type":"double"}],"type":"InputPhotoCrop"},{"id":"1996904104","predicate":"inputAppEvent","params":[{"name":"time","type":"double"},{"name":"type","type":"string"},{"name":"peer","type":"long"},{"name":"data","type":"string"}],"type":"InputAppEvent"},{"id":"-1649296275","predicate":"peerUser","params":[{"name":"user_id","type":"int"}],"type":"Peer"},{"id":"-1160714821","predicate":"peerChat","params":[{"name":"chat_id","type":"int"}],"type":"Peer"},{"id":"-1432995067","predicate":"storage.fileUnknown","params":[],"type":"storage.FileType"},{"id":"8322574","predicate":"storage.fileJpeg","params":[],"type":"storage.FileType"},{"id":"-891180321","predicate":"storage.fileGif","params":[],"type":"storage.FileType"},{"id":"172975040","predicate":"storage.filePng","params":[],"type":"storage.FileType"},{"id":"1384777335","predicate":"storage.fileMp3","params":[],"type":"storage.FileType"},{"id":"1258941372","predicate":"storage.fileMov","params":[],"type":"storage.FileType"},{"id":"1086091090","predicate":"storage.filePartial","params":[],"type":"storage.FileType"},{"id":"-1278304028","predicate":"storage.fileMp4","params":[],"type":"storage.FileType"},{"id":"276907596","predicate":"storage.fileWebp","params":[],"type":"storage.FileType"},{"id":"2086234950","predicate":"fileLocationUnavailable","params":[{"name":"volume_id","type":"long"},{"name":"local_id","type":"int"},{"name":"secret","type":"long"}],"type":"FileLocation"},{"id":"1406570614","predicate":"fileLocation","params":[{"name":"dc_id","type":"int"},{"name":"volume_id","type":"long"},{"name":"local_id","type":"int"},{"name":"secret","type":"long"}],"type":"FileLocation"},{"id":"537022650","predicate":"userEmpty","params":[{"name":"id","type":"int"}],"type":"User"},{"id":"1912944108","predicate":"userSelf","params":[{"name":"id","type":"int"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"},{"name":"phone","type":"string"},{"name":"photo","type":"UserProfilePhoto"},{"name":"status","type":"UserStatus"},{"name":"inactive","type":"Bool"}],"type":"User"},{"id":"-218397927","predicate":"userContact","params":[{"name":"id","type":"int"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"},{"name":"access_hash","type":"long"},{"name":"phone","type":"string"},{"name":"photo","type":"UserProfilePhoto"},{"name":"status","type":"UserStatus"}],"type":"User"},{"id":"585682608","predicate":"userRequest","params":[{"name":"id","type":"int"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"},{"name":"access_hash","type":"long"},{"name":"phone","type":"string"},{"name":"photo","type":"UserProfilePhoto"},{"name":"status","type":"UserStatus"}],"type":"User"},{"id":"1377093789","predicate":"userForeign","params":[{"name":"id","type":"int"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"},{"name":"access_hash","type":"long"},{"name":"photo","type":"UserProfilePhoto"},{"name":"status","type":"UserStatus"}],"type":"User"},{"id":"-1298475060","predicate":"userDeleted","params":[{"name":"id","type":"int"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"}],"type":"User"},{"id":"1326562017","predicate":"userProfilePhotoEmpty","params":[],"type":"UserProfilePhoto"},{"id":"-715532088","predicate":"userProfilePhoto","params":[{"name":"photo_id","type":"long"},{"name":"photo_small","type":"FileLocation"},{"name":"photo_big","type":"FileLocation"}],"type":"UserProfilePhoto"},{"id":"164646985","predicate":"userStatusEmpty","params":[],"type":"UserStatus"},{"id":"-306628279","predicate":"userStatusOnline","params":[{"name":"expires","type":"int"}],"type":"UserStatus"},{"id":"9203775","predicate":"userStatusOffline","params":[{"name":"was_online","type":"int"}],"type":"UserStatus"},{"id":"-1683826688","predicate":"chatEmpty","params":[{"name":"id","type":"int"}],"type":"Chat"},{"id":"1855757255","predicate":"chat","params":[{"name":"id","type":"int"},{"name":"title","type":"string"},{"name":"photo","type":"ChatPhoto"},{"name":"participants_count","type":"int"},{"name":"date","type":"int"},{"name":"left","type":"Bool"},{"name":"version","type":"int"}],"type":"Chat"},{"id":"-83047359","predicate":"chatForbidden","params":[{"name":"id","type":"int"},{"name":"title","type":"string"},{"name":"date","type":"int"}],"type":"Chat"},{"id":"1661886910","predicate":"chatFull","params":[{"name":"id","type":"int"},{"name":"participants","type":"ChatParticipants"},{"name":"chat_photo","type":"Photo"},{"name":"notify_settings","type":"PeerNotifySettings"}],"type":"ChatFull"},{"id":"-925415106","predicate":"chatParticipant","params":[{"name":"user_id","type":"int"},{"name":"inviter_id","type":"int"},{"name":"date","type":"int"}],"type":"ChatParticipant"},{"id":"265468810","predicate":"chatParticipantsForbidden","params":[{"name":"chat_id","type":"int"}],"type":"ChatParticipants"},{"id":"2017571861","predicate":"chatParticipants","params":[{"name":"chat_id","type":"int"},{"name":"admin_id","type":"int"},{"name":"participants","type":"Vector"},{"name":"version","type":"int"}],"type":"ChatParticipants"},{"id":"935395612","predicate":"chatPhotoEmpty","params":[],"type":"ChatPhoto"},{"id":"1632839530","predicate":"chatPhoto","params":[{"name":"photo_small","type":"FileLocation"},{"name":"photo_big","type":"FileLocation"}],"type":"ChatPhoto"},{"id":"-2082087340","predicate":"messageEmpty","params":[{"name":"id","type":"int"}],"type":"Message"},{"id":"585853626","predicate":"message","params":[{"name":"id","type":"int"},{"name":"from_id","type":"int"},{"name":"to_id","type":"Peer"},{"name":"out","type":"Bool"},{"name":"unread","type":"Bool"},{"name":"date","type":"int"},{"name":"message","type":"string"},{"name":"media","type":"MessageMedia"}],"type":"Message"},{"id":"99903492","predicate":"messageForwarded","params":[{"name":"id","type":"int"},{"name":"fwd_from_id","type":"int"},{"name":"fwd_date","type":"int"},{"name":"from_id","type":"int"},{"name":"to_id","type":"Peer"},{"name":"out","type":"Bool"},{"name":"unread","type":"Bool"},{"name":"date","type":"int"},{"name":"message","type":"string"},{"name":"media","type":"MessageMedia"}],"type":"Message"},{"id":"-1618124613","predicate":"messageService","params":[{"name":"id","type":"int"},{"name":"from_id","type":"int"},{"name":"to_id","type":"Peer"},{"name":"out","type":"Bool"},{"name":"unread","type":"Bool"},{"name":"date","type":"int"},{"name":"action","type":"MessageAction"}],"type":"Message"},{"id":"1038967584","predicate":"messageMediaEmpty","params":[],"type":"MessageMedia"},{"id":"-926655958","predicate":"messageMediaPhoto","params":[{"name":"photo","type":"Photo"}],"type":"MessageMedia"},{"id":"-1563278704","predicate":"messageMediaVideo","params":[{"name":"video","type":"Video"}],"type":"MessageMedia"},{"id":"1457575028","predicate":"messageMediaGeo","params":[{"name":"geo","type":"GeoPoint"}],"type":"MessageMedia"},{"id":"1585262393","predicate":"messageMediaContact","params":[{"name":"phone_number","type":"string"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"},{"name":"user_id","type":"int"}],"type":"MessageMedia"},{"id":"694364726","predicate":"messageMediaUnsupported","params":[{"name":"bytes","type":"bytes"}],"type":"MessageMedia"},{"id":"-1230047312","predicate":"messageActionEmpty","params":[],"type":"MessageAction"},{"id":"-1503425638","predicate":"messageActionChatCreate","params":[{"name":"title","type":"string"},{"name":"users","type":"Vector"}],"type":"MessageAction"},{"id":"-1247687078","predicate":"messageActionChatEditTitle","params":[{"name":"title","type":"string"}],"type":"MessageAction"},{"id":"2144015272","predicate":"messageActionChatEditPhoto","params":[{"name":"photo","type":"Photo"}],"type":"MessageAction"},{"id":"-1780220945","predicate":"messageActionChatDeletePhoto","params":[],"type":"MessageAction"},{"id":"1581055051","predicate":"messageActionChatAddUser","params":[{"name":"user_id","type":"int"}],"type":"MessageAction"},{"id":"-1297179892","predicate":"messageActionChatDeleteUser","params":[{"name":"user_id","type":"int"}],"type":"MessageAction"},{"id":"558533855","predicate":"dialog","params":[{"name":"peer","type":"Peer"},{"name":"top_message","type":"int"},{"name":"unread_count","type":"int"}],"type":"Dialog"},{"id":"590459437","predicate":"photoEmpty","params":[{"name":"id","type":"long"}],"type":"Photo"},{"id":"582313809","predicate":"photo","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"},{"name":"user_id","type":"int"},{"name":"date","type":"int"},{"name":"caption","type":"string"},{"name":"geo","type":"GeoPoint"},{"name":"sizes","type":"Vector"}],"type":"Photo"},{"id":"236446268","predicate":"photoSizeEmpty","params":[{"name":"type","type":"string"}],"type":"PhotoSize"},{"id":"2009052699","predicate":"photoSize","params":[{"name":"type","type":"string"},{"name":"location","type":"FileLocation"},{"name":"w","type":"int"},{"name":"h","type":"int"},{"name":"size","type":"int"}],"type":"PhotoSize"},{"id":"-374917894","predicate":"photoCachedSize","params":[{"name":"type","type":"string"},{"name":"location","type":"FileLocation"},{"name":"w","type":"int"},{"name":"h","type":"int"},{"name":"bytes","type":"bytes"}],"type":"PhotoSize"},{"id":"-1056548696","predicate":"videoEmpty","params":[{"name":"id","type":"long"}],"type":"Video"},{"id":"1510253727","predicate":"video","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"},{"name":"user_id","type":"int"},{"name":"date","type":"int"},{"name":"caption","type":"string"},{"name":"duration","type":"int"},{"name":"size","type":"int"},{"name":"thumb","type":"PhotoSize"},{"name":"dc_id","type":"int"},{"name":"w","type":"int"},{"name":"h","type":"int"}],"type":"Video"},{"id":"286776671","predicate":"geoPointEmpty","params":[],"type":"GeoPoint"},{"id":"541710092","predicate":"geoPoint","params":[{"name":"long","type":"double"},{"name":"lat","type":"double"}],"type":"GeoPoint"},{"id":"-486486981","predicate":"auth.checkedPhone","params":[{"name":"phone_registered","type":"Bool"},{"name":"phone_invited","type":"Bool"}],"type":"auth.CheckedPhone"},{"id":"571849917","predicate":"auth.sentCode","params":[{"name":"phone_registered","type":"Bool"},{"name":"phone_code_hash","type":"string"}],"type":"auth.SentCode"},{"id":"-155815004","predicate":"auth.authorization","params":[{"name":"expires","type":"int"},{"name":"user","type":"User"}],"type":"auth.Authorization"},{"id":"-543777747","predicate":"auth.exportedAuthorization","params":[{"name":"id","type":"int"},{"name":"bytes","type":"bytes"}],"type":"auth.ExportedAuthorization"},{"id":"-1195615476","predicate":"inputNotifyPeer","params":[{"name":"peer","type":"InputPeer"}],"type":"InputNotifyPeer"},{"id":"423314455","predicate":"inputNotifyUsers","params":[],"type":"InputNotifyPeer"},{"id":"1251338318","predicate":"inputNotifyChats","params":[],"type":"InputNotifyPeer"},{"id":"-1540769658","predicate":"inputNotifyAll","params":[],"type":"InputNotifyPeer"},{"id":"-265263912","predicate":"inputPeerNotifyEventsEmpty","params":[],"type":"InputPeerNotifyEvents"},{"id":"-395694988","predicate":"inputPeerNotifyEventsAll","params":[],"type":"InputPeerNotifyEvents"},{"id":"1185074840","predicate":"inputPeerNotifySettings","params":[{"name":"mute_until","type":"int"},{"name":"sound","type":"string"},{"name":"show_previews","type":"Bool"},{"name":"events_mask","type":"int"}],"type":"InputPeerNotifySettings"},{"id":"-1378534221","predicate":"peerNotifyEventsEmpty","params":[],"type":"PeerNotifyEvents"},{"id":"1830677896","predicate":"peerNotifyEventsAll","params":[],"type":"PeerNotifyEvents"},{"id":"1889961234","predicate":"peerNotifySettingsEmpty","params":[],"type":"PeerNotifySettings"},{"id":"-1923214866","predicate":"peerNotifySettings","params":[{"name":"mute_until","type":"int"},{"name":"sound","type":"string"},{"name":"show_previews","type":"Bool"},{"name":"events_mask","type":"int"}],"type":"PeerNotifySettings"},{"id":"-860866985","predicate":"wallPaper","params":[{"name":"id","type":"int"},{"name":"title","type":"string"},{"name":"sizes","type":"Vector"},{"name":"color","type":"int"}],"type":"WallPaper"},{"id":"1997575642","predicate":"userFull","params":[{"name":"user","type":"User"},{"name":"link","type":"contacts.Link"},{"name":"profile_photo","type":"Photo"},{"name":"notify_settings","type":"PeerNotifySettings"},{"name":"blocked","type":"Bool"},{"name":"real_first_name","type":"string"},{"name":"real_last_name","type":"string"}],"type":"UserFull"},{"id":"-116274796","predicate":"contact","params":[{"name":"user_id","type":"int"},{"name":"mutual","type":"Bool"}],"type":"Contact"},{"id":"-805141448","predicate":"importedContact","params":[{"name":"user_id","type":"int"},{"name":"client_id","type":"long"}],"type":"ImportedContact"},{"id":"1444661369","predicate":"contactBlocked","params":[{"name":"user_id","type":"int"},{"name":"date","type":"int"}],"type":"ContactBlocked"},{"id":"-360210539","predicate":"contactFound","params":[{"name":"user_id","type":"int"}],"type":"ContactFound"},{"id":"1038193057","predicate":"contactSuggested","params":[{"name":"user_id","type":"int"},{"name":"mutual_contacts","type":"int"}],"type":"ContactSuggested"},{"id":"-1434994573","predicate":"contactStatus","params":[{"name":"user_id","type":"int"},{"name":"expires","type":"int"}],"type":"ContactStatus"},{"id":"909233996","predicate":"chatLocated","params":[{"name":"chat_id","type":"int"},{"name":"distance","type":"int"}],"type":"ChatLocated"},{"id":"322183672","predicate":"contacts.foreignLinkUnknown","params":[],"type":"contacts.ForeignLink"},{"id":"-1484775609","predicate":"contacts.foreignLinkRequested","params":[{"name":"has_phone","type":"Bool"}],"type":"contacts.ForeignLink"},{"id":"468356321","predicate":"contacts.foreignLinkMutual","params":[],"type":"contacts.ForeignLink"},{"id":"-768992160","predicate":"contacts.myLinkEmpty","params":[],"type":"contacts.MyLink"},{"id":"1818882030","predicate":"contacts.myLinkRequested","params":[{"name":"contact","type":"Bool"}],"type":"contacts.MyLink"},{"id":"-1035932711","predicate":"contacts.myLinkContact","params":[],"type":"contacts.MyLink"},{"id":"-322001931","predicate":"contacts.link","params":[{"name":"my_link","type":"contacts.MyLink"},{"name":"foreign_link","type":"contacts.ForeignLink"},{"name":"user","type":"User"}],"type":"contacts.Link"},{"id":"1871416498","predicate":"contacts.contacts","params":[{"name":"contacts","type":"Vector"},{"name":"users","type":"Vector"}],"type":"contacts.Contacts"},{"id":"-1219778094","predicate":"contacts.contactsNotModified","params":[],"type":"contacts.Contacts"},{"id":"-775091636","predicate":"contacts.importedContacts","params":[{"name":"imported","type":"Vector"},{"name":"users","type":"Vector"}],"type":"contacts.ImportedContacts"},{"id":"471043349","predicate":"contacts.blocked","params":[{"name":"blocked","type":"Vector"},{"name":"users","type":"Vector"}],"type":"contacts.Blocked"},{"id":"-1878523231","predicate":"contacts.blockedSlice","params":[{"name":"count","type":"int"},{"name":"blocked","type":"Vector"},{"name":"users","type":"Vector"}],"type":"contacts.Blocked"},{"id":"90570766","predicate":"contacts.found","params":[{"name":"results","type":"Vector"},{"name":"users","type":"Vector"}],"type":"contacts.Found"},{"id":"1447681221","predicate":"contacts.suggested","params":[{"name":"results","type":"Vector"},{"name":"users","type":"Vector"}],"type":"contacts.Suggested"},{"id":"364538944","predicate":"messages.dialogs","params":[{"name":"dialogs","type":"Vector"},{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"messages.Dialogs"},{"id":"1910543603","predicate":"messages.dialogsSlice","params":[{"name":"count","type":"int"},{"name":"dialogs","type":"Vector"},{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"messages.Dialogs"},{"id":"-1938715001","predicate":"messages.messages","params":[{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"messages.Messages"},{"id":"189033187","predicate":"messages.messagesSlice","params":[{"name":"count","type":"int"},{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"messages.Messages"},{"id":"1062078024","predicate":"messages.messageEmpty","params":[],"type":"messages.Message"},{"id":"-7289833","predicate":"messages.message","params":[{"name":"message","type":"Message"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"messages.Message"},{"id":"-1768654661","predicate":"messages.statedMessages","params":[{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"},{"name":"pts","type":"int"},{"name":"seq","type":"int"}],"type":"messages.StatedMessages"},{"id":"-797251802","predicate":"messages.statedMessage","params":[{"name":"message","type":"Message"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"},{"name":"pts","type":"int"},{"name":"seq","type":"int"}],"type":"messages.StatedMessage"},{"id":"-772484260","predicate":"messages.sentMessage","params":[{"name":"id","type":"int"},{"name":"date","type":"int"},{"name":"pts","type":"int"},{"name":"seq","type":"int"}],"type":"messages.SentMessage"},{"id":"1089011754","predicate":"messages.chat","params":[{"name":"chat","type":"Chat"},{"name":"users","type":"Vector"}],"type":"messages.Chat"},{"id":"-2125411368","predicate":"messages.chats","params":[{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"messages.Chats"},{"id":"-438840932","predicate":"messages.chatFull","params":[{"name":"full_chat","type":"ChatFull"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"messages.ChatFull"},{"id":"-1210173710","predicate":"messages.affectedHistory","params":[{"name":"pts","type":"int"},{"name":"seq","type":"int"},{"name":"offset","type":"int"}],"type":"messages.AffectedHistory"},{"id":"1474492012","predicate":"inputMessagesFilterEmpty","params":[],"type":"MessagesFilter"},{"id":"-1777752804","predicate":"inputMessagesFilterPhotos","params":[],"type":"MessagesFilter"},{"id":"-1614803355","predicate":"inputMessagesFilterVideo","params":[],"type":"MessagesFilter"},{"id":"1458172132","predicate":"inputMessagesFilterPhotoVideo","params":[],"type":"MessagesFilter"},{"id":"20626867","predicate":"updateNewMessage","params":[{"name":"message","type":"Message"},{"name":"pts","type":"int"}],"type":"Update"},{"id":"1318109142","predicate":"updateMessageID","params":[{"name":"id","type":"int"},{"name":"random_id","type":"long"}],"type":"Update"},{"id":"-966484431","predicate":"updateReadMessages","params":[{"name":"messages","type":"Vector"},{"name":"pts","type":"int"}],"type":"Update"},{"id":"-1456734682","predicate":"updateDeleteMessages","params":[{"name":"messages","type":"Vector"},{"name":"pts","type":"int"}],"type":"Update"},{"id":"-782376883","predicate":"updateRestoreMessages","params":[{"name":"messages","type":"Vector"},{"name":"pts","type":"int"}],"type":"Update"},{"id":"1806337288","predicate":"updateUserTyping","params":[{"name":"user_id","type":"int"}],"type":"Update"},{"id":"1011273702","predicate":"updateChatUserTyping","params":[{"name":"chat_id","type":"int"},{"name":"user_id","type":"int"}],"type":"Update"},{"id":"125178264","predicate":"updateChatParticipants","params":[{"name":"participants","type":"ChatParticipants"}],"type":"Update"},{"id":"469489699","predicate":"updateUserStatus","params":[{"name":"user_id","type":"int"},{"name":"status","type":"UserStatus"}],"type":"Update"},{"id":"-635250259","predicate":"updateUserName","params":[{"name":"user_id","type":"int"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"}],"type":"Update"},{"id":"-1791935732","predicate":"updateUserPhoto","params":[{"name":"user_id","type":"int"},{"name":"date","type":"int"},{"name":"photo","type":"UserProfilePhoto"},{"name":"previous","type":"Bool"}],"type":"Update"},{"id":"628472761","predicate":"updateContactRegistered","params":[{"name":"user_id","type":"int"},{"name":"date","type":"int"}],"type":"Update"},{"id":"1369737882","predicate":"updateContactLink","params":[{"name":"user_id","type":"int"},{"name":"my_link","type":"contacts.MyLink"},{"name":"foreign_link","type":"contacts.ForeignLink"}],"type":"Update"},{"id":"1869154659","predicate":"updateActivation","params":[{"name":"user_id","type":"int"}],"type":"Update"},{"id":"-1895411046","predicate":"updateNewAuthorization","params":[{"name":"auth_key_id","type":"long"},{"name":"date","type":"int"},{"name":"device","type":"string"},{"name":"location","type":"string"}],"type":"Update"},{"id":"-1519637954","predicate":"updates.state","params":[{"name":"pts","type":"int"},{"name":"qts","type":"int"},{"name":"date","type":"int"},{"name":"seq","type":"int"},{"name":"unread_count","type":"int"}],"type":"updates.State"},{"id":"1567990072","predicate":"updates.differenceEmpty","params":[{"name":"date","type":"int"},{"name":"seq","type":"int"}],"type":"updates.Difference"},{"id":"16030880","predicate":"updates.difference","params":[{"name":"new_messages","type":"Vector"},{"name":"new_encrypted_messages","type":"Vector"},{"name":"other_updates","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"},{"name":"state","type":"updates.State"}],"type":"updates.Difference"},{"id":"-1459938943","predicate":"updates.differenceSlice","params":[{"name":"new_messages","type":"Vector"},{"name":"new_encrypted_messages","type":"Vector"},{"name":"other_updates","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"},{"name":"intermediate_state","type":"updates.State"}],"type":"updates.Difference"},{"id":"-484987010","predicate":"updatesTooLong","params":[],"type":"Updates"},{"id":"-738961532","predicate":"updateShortMessage","params":[{"name":"id","type":"int"},{"name":"from_id","type":"int"},{"name":"message","type":"string"},{"name":"pts","type":"int"},{"name":"date","type":"int"},{"name":"seq","type":"int"}],"type":"Updates"},{"id":"724548942","predicate":"updateShortChatMessage","params":[{"name":"id","type":"int"},{"name":"from_id","type":"int"},{"name":"chat_id","type":"int"},{"name":"message","type":"string"},{"name":"pts","type":"int"},{"name":"date","type":"int"},{"name":"seq","type":"int"}],"type":"Updates"},{"id":"2027216577","predicate":"updateShort","params":[{"name":"update","type":"Update"},{"name":"date","type":"int"}],"type":"Updates"},{"id":"1918567619","predicate":"updatesCombined","params":[{"name":"updates","type":"Vector"},{"name":"users","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"date","type":"int"},{"name":"seq_start","type":"int"},{"name":"seq","type":"int"}],"type":"Updates"},{"id":"1957577280","predicate":"updates","params":[{"name":"updates","type":"Vector"},{"name":"users","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"date","type":"int"},{"name":"seq","type":"int"}],"type":"Updates"},{"id":"-1916114267","predicate":"photos.photos","params":[{"name":"photos","type":"Vector"},{"name":"users","type":"Vector"}],"type":"photos.Photos"},{"id":"352657236","predicate":"photos.photosSlice","params":[{"name":"count","type":"int"},{"name":"photos","type":"Vector"},{"name":"users","type":"Vector"}],"type":"photos.Photos"},{"id":"539045032","predicate":"photos.photo","params":[{"name":"photo","type":"Photo"},{"name":"users","type":"Vector"}],"type":"photos.Photo"},{"id":"157948117","predicate":"upload.file","params":[{"name":"type","type":"storage.FileType"},{"name":"mtime","type":"int"},{"name":"bytes","type":"bytes"}],"type":"upload.File"},{"id":"784507964","predicate":"dcOption","params":[{"name":"id","type":"int"},{"name":"hostname","type":"string"},{"name":"ip_address","type":"string"},{"name":"port","type":"int"}],"type":"DcOption"},{"id":"590174469","predicate":"config","params":[{"name":"date","type":"int"},{"name":"test_mode","type":"Bool"},{"name":"this_dc","type":"int"},{"name":"dc_options","type":"Vector"},{"name":"chat_size_max","type":"int"}],"type":"Config"},{"id":"-1910892683","predicate":"nearestDc","params":[{"name":"country","type":"string"},{"name":"this_dc","type":"int"},{"name":"nearest_dc","type":"int"}],"type":"NearestDc"},{"id":"-1987579119","predicate":"help.appUpdate","params":[{"name":"id","type":"int"},{"name":"critical","type":"Bool"},{"name":"url","type":"string"},{"name":"text","type":"string"}],"type":"help.AppUpdate"},{"id":"-1000708810","predicate":"help.noAppUpdate","params":[],"type":"help.AppUpdate"},{"id":"415997816","predicate":"help.inviteText","params":[{"name":"message","type":"string"}],"type":"help.InviteText"},{"id":"1047852486","predicate":"messages.statedMessagesLinks","params":[{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"},{"name":"links","type":"Vector"},{"name":"pts","type":"int"},{"name":"seq","type":"int"}],"type":"messages.StatedMessages"},{"id":"-1448138623","predicate":"messages.statedMessageLink","params":[{"name":"message","type":"Message"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"},{"name":"links","type":"Vector"},{"name":"pts","type":"int"},{"name":"seq","type":"int"}],"type":"messages.StatedMessage"},{"id":"-371504577","predicate":"messages.sentMessageLink","params":[{"name":"id","type":"int"},{"name":"date","type":"int"},{"name":"pts","type":"int"},{"name":"seq","type":"int"},{"name":"links","type":"Vector"}],"type":"messages.SentMessage"},{"id":"1960072954","predicate":"inputGeoChat","params":[{"name":"chat_id","type":"int"},{"name":"access_hash","type":"long"}],"type":"InputGeoChat"},{"id":"1301143240","predicate":"inputNotifyGeoChatPeer","params":[{"name":"peer","type":"InputGeoChat"}],"type":"InputNotifyPeer"},{"id":"1978329690","predicate":"geoChat","params":[{"name":"id","type":"int"},{"name":"access_hash","type":"long"},{"name":"title","type":"string"},{"name":"address","type":"string"},{"name":"venue","type":"string"},{"name":"geo","type":"GeoPoint"},{"name":"photo","type":"ChatPhoto"},{"name":"participants_count","type":"int"},{"name":"date","type":"int"},{"name":"checked_in","type":"Bool"},{"name":"version","type":"int"}],"type":"Chat"},{"id":"1613830811","predicate":"geoChatMessageEmpty","params":[{"name":"chat_id","type":"int"},{"name":"id","type":"int"}],"type":"GeoChatMessage"},{"id":"1158019297","predicate":"geoChatMessage","params":[{"name":"chat_id","type":"int"},{"name":"id","type":"int"},{"name":"from_id","type":"int"},{"name":"date","type":"int"},{"name":"message","type":"string"},{"name":"media","type":"MessageMedia"}],"type":"GeoChatMessage"},{"id":"-749755826","predicate":"geoChatMessageService","params":[{"name":"chat_id","type":"int"},{"name":"id","type":"int"},{"name":"from_id","type":"int"},{"name":"date","type":"int"},{"name":"action","type":"MessageAction"}],"type":"GeoChatMessage"},{"id":"397498251","predicate":"geochats.statedMessage","params":[{"name":"message","type":"GeoChatMessage"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"},{"name":"seq","type":"int"}],"type":"geochats.StatedMessage"},{"id":"1224651367","predicate":"geochats.located","params":[{"name":"results","type":"Vector"},{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"geochats.Located"},{"id":"-783127119","predicate":"geochats.messages","params":[{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"geochats.Messages"},{"id":"-1135057944","predicate":"geochats.messagesSlice","params":[{"name":"count","type":"int"},{"name":"messages","type":"Vector"},{"name":"chats","type":"Vector"},{"name":"users","type":"Vector"}],"type":"geochats.Messages"},{"id":"1862504124","predicate":"messageActionGeoChatCreate","params":[{"name":"title","type":"string"},{"name":"address","type":"string"}],"type":"MessageAction"},{"id":"209540062","predicate":"messageActionGeoChatCheckin","params":[],"type":"MessageAction"},{"id":"1516823543","predicate":"updateNewGeoChatMessage","params":[{"name":"message","type":"GeoChatMessage"}],"type":"Update"},{"id":"1662091044","predicate":"wallPaperSolid","params":[{"name":"id","type":"int"},{"name":"title","type":"string"},{"name":"bg_color","type":"int"},{"name":"color","type":"int"}],"type":"WallPaper"},{"id":"314359194","predicate":"updateNewEncryptedMessage","params":[{"name":"message","type":"EncryptedMessage"},{"name":"qts","type":"int"}],"type":"Update"},{"id":"386986326","predicate":"updateEncryptedChatTyping","params":[{"name":"chat_id","type":"int"}],"type":"Update"},{"id":"-1264392051","predicate":"updateEncryption","params":[{"name":"chat","type":"EncryptedChat"},{"name":"date","type":"int"}],"type":"Update"},{"id":"956179895","predicate":"updateEncryptedMessagesRead","params":[{"name":"chat_id","type":"int"},{"name":"max_date","type":"int"},{"name":"date","type":"int"}],"type":"Update"},{"id":"-1417756512","predicate":"encryptedChatEmpty","params":[{"name":"id","type":"int"}],"type":"EncryptedChat"},{"id":"1006044124","predicate":"encryptedChatWaiting","params":[{"name":"id","type":"int"},{"name":"access_hash","type":"long"},{"name":"date","type":"int"},{"name":"admin_id","type":"int"},{"name":"participant_id","type":"int"}],"type":"EncryptedChat"},{"id":"-39213129","predicate":"encryptedChatRequested","params":[{"name":"id","type":"int"},{"name":"access_hash","type":"long"},{"name":"date","type":"int"},{"name":"admin_id","type":"int"},{"name":"participant_id","type":"int"},{"name":"g_a","type":"bytes"},{"name":"nonce","type":"bytes"}],"type":"EncryptedChat"},{"id":"1711395151","predicate":"encryptedChat","params":[{"name":"id","type":"int"},{"name":"access_hash","type":"long"},{"name":"date","type":"int"},{"name":"admin_id","type":"int"},{"name":"participant_id","type":"int"},{"name":"g_a_or_b","type":"bytes"},{"name":"nonce","type":"bytes"},{"name":"key_fingerprint","type":"long"}],"type":"EncryptedChat"},{"id":"332848423","predicate":"encryptedChatDiscarded","params":[{"name":"id","type":"int"}],"type":"EncryptedChat"},{"id":"-247351839","predicate":"inputEncryptedChat","params":[{"name":"chat_id","type":"int"},{"name":"access_hash","type":"long"}],"type":"InputEncryptedChat"},{"id":"-1038136962","predicate":"encryptedFileEmpty","params":[],"type":"EncryptedFile"},{"id":"1248893260","predicate":"encryptedFile","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"},{"name":"size","type":"int"},{"name":"dc_id","type":"int"},{"name":"key_fingerprint","type":"int"}],"type":"EncryptedFile"},{"id":"406307684","predicate":"inputEncryptedFileEmpty","params":[],"type":"InputEncryptedFile"},{"id":"1690108678","predicate":"inputEncryptedFileUploaded","params":[{"name":"id","type":"long"},{"name":"parts","type":"int"},{"name":"md5_checksum","type":"string"},{"name":"key_fingerprint","type":"int"}],"type":"InputEncryptedFile"},{"id":"1511503333","predicate":"inputEncryptedFile","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputEncryptedFile"},{"id":"-182231723","predicate":"inputEncryptedFileLocation","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputFileLocation"},{"id":"-317144808","predicate":"encryptedMessage","params":[{"name":"random_id","type":"long"},{"name":"chat_id","type":"int"},{"name":"date","type":"int"},{"name":"bytes","type":"bytes"},{"name":"file","type":"EncryptedFile"}],"type":"EncryptedMessage"},{"id":"594758406","predicate":"encryptedMessageService","params":[{"name":"random_id","type":"long"},{"name":"chat_id","type":"int"},{"name":"date","type":"int"},{"name":"bytes","type":"bytes"}],"type":"EncryptedMessage"},{"id":"-1717290801","predicate":"decryptedMessageLayer","params":[{"name":"layer","type":"int"},{"name":"message","type":"DecryptedMessage"}],"type":"DecryptedMessageLayer"},{"id":"528568095","predicate":"decryptedMessage","params":[{"name":"random_id","type":"long"},{"name":"random_bytes","type":"bytes"},{"name":"message","type":"string"},{"name":"media","type":"DecryptedMessageMedia"}],"type":"DecryptedMessage"},{"id":"-1438109059","predicate":"decryptedMessageService","params":[{"name":"random_id","type":"long"},{"name":"random_bytes","type":"bytes"},{"name":"action","type":"DecryptedMessageAction"}],"type":"DecryptedMessage"},{"id":"144661578","predicate":"decryptedMessageMediaEmpty","params":[],"type":"DecryptedMessageMedia"},{"id":"846826124","predicate":"decryptedMessageMediaPhoto","params":[{"name":"thumb","type":"bytes"},{"name":"thumb_w","type":"int"},{"name":"thumb_h","type":"int"},{"name":"w","type":"int"},{"name":"h","type":"int"},{"name":"size","type":"int"},{"name":"key","type":"bytes"},{"name":"iv","type":"bytes"}],"type":"DecryptedMessageMedia"},{"id":"1290694387","predicate":"decryptedMessageMediaVideo","params":[{"name":"thumb","type":"bytes"},{"name":"thumb_w","type":"int"},{"name":"thumb_h","type":"int"},{"name":"duration","type":"int"},{"name":"w","type":"int"},{"name":"h","type":"int"},{"name":"size","type":"int"},{"name":"key","type":"bytes"},{"name":"iv","type":"bytes"}],"type":"DecryptedMessageMedia"},{"id":"893913689","predicate":"decryptedMessageMediaGeoPoint","params":[{"name":"lat","type":"double"},{"name":"long","type":"double"}],"type":"DecryptedMessageMedia"},{"id":"1485441687","predicate":"decryptedMessageMediaContact","params":[{"name":"phone_number","type":"string"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"},{"name":"user_id","type":"int"}],"type":"DecryptedMessageMedia"},{"id":"-1586283796","predicate":"decryptedMessageActionSetMessageTTL","params":[{"name":"ttl_seconds","type":"int"}],"type":"DecryptedMessageAction"},{"id":"-1058912715","predicate":"messages.dhConfigNotModified","params":[{"name":"random","type":"bytes"}],"type":"messages.DhConfig"},{"id":"740433629","predicate":"messages.dhConfig","params":[{"name":"g","type":"int"},{"name":"p","type":"bytes"},{"name":"version","type":"int"},{"name":"random","type":"bytes"}],"type":"messages.DhConfig"},{"id":"1443858741","predicate":"messages.sentEncryptedMessage","params":[{"name":"date","type":"int"}],"type":"messages.SentEncryptedMessage"},{"id":"-1802240206","predicate":"messages.sentEncryptedFile","params":[{"name":"date","type":"int"},{"name":"file","type":"EncryptedFile"}],"type":"messages.SentEncryptedMessage"},{"id":"-95482955","predicate":"inputFileBig","params":[{"name":"id","type":"long"},{"name":"parts","type":"int"},{"name":"name","type":"string"}],"type":"InputFile"},{"id":"767652808","predicate":"inputEncryptedFileBigUploaded","params":[{"name":"id","type":"long"},{"name":"parts","type":"int"},{"name":"key_fingerprint","type":"int"}],"type":"InputEncryptedFile"},{"id":"974056226","predicate":"updateChatParticipantAdd","params":[{"name":"chat_id","type":"int"},{"name":"user_id","type":"int"},{"name":"inviter_id","type":"int"},{"name":"version","type":"int"}],"type":"Update"},{"id":"1851755554","predicate":"updateChatParticipantDelete","params":[{"name":"chat_id","type":"int"},{"name":"user_id","type":"int"},{"name":"version","type":"int"}],"type":"Update"},{"id":"-1906403213","predicate":"updateDcOptions","params":[{"name":"dc_options","type":"Vector"}],"type":"Update"},{"id":"1638323254","predicate":"inputMediaUploadedAudio","params":[{"name":"file","type":"InputFile"},{"name":"duration","type":"int"}],"type":"InputMedia"},{"id":"-1986820223","predicate":"inputMediaAudio","params":[{"name":"id","type":"InputAudio"}],"type":"InputMedia"},{"id":"887592125","predicate":"inputMediaUploadedDocument","params":[{"name":"file","type":"InputFile"},{"name":"file_name","type":"string"},{"name":"mime_type","type":"string"}],"type":"InputMedia"},{"id":"1044831837","predicate":"inputMediaUploadedThumbDocument","params":[{"name":"file","type":"InputFile"},{"name":"thumb","type":"InputFile"},{"name":"file_name","type":"string"},{"name":"mime_type","type":"string"}],"type":"InputMedia"},{"id":"-779818943","predicate":"inputMediaDocument","params":[{"name":"id","type":"InputDocument"}],"type":"InputMedia"},{"id":"802824708","predicate":"messageMediaDocument","params":[{"name":"document","type":"Document"}],"type":"MessageMedia"},{"id":"-961117440","predicate":"messageMediaAudio","params":[{"name":"audio","type":"Audio"}],"type":"MessageMedia"},{"id":"-648356732","predicate":"inputAudioEmpty","params":[],"type":"InputAudio"},{"id":"2010398975","predicate":"inputAudio","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputAudio"},{"id":"1928391342","predicate":"inputDocumentEmpty","params":[],"type":"InputDocument"},{"id":"410618194","predicate":"inputDocument","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputDocument"},{"id":"1960591437","predicate":"inputAudioFileLocation","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputFileLocation"},{"id":"1313188841","predicate":"inputDocumentFileLocation","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"}],"type":"InputFileLocation"},{"id":"-1332395189","predicate":"decryptedMessageMediaDocument","params":[{"name":"thumb","type":"bytes"},{"name":"thumb_w","type":"int"},{"name":"thumb_h","type":"int"},{"name":"file_name","type":"string"},{"name":"mime_type","type":"string"},{"name":"size","type":"int"},{"name":"key","type":"bytes"},{"name":"iv","type":"bytes"}],"type":"DecryptedMessageMedia"},{"id":"1619031439","predicate":"decryptedMessageMediaAudio","params":[{"name":"duration","type":"int"},{"name":"size","type":"int"},{"name":"key","type":"bytes"},{"name":"iv","type":"bytes"}],"type":"DecryptedMessageMedia"},{"id":"1483311320","predicate":"audioEmpty","params":[{"name":"id","type":"long"}],"type":"Audio"},{"id":"1114908135","predicate":"audio","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"},{"name":"user_id","type":"int"},{"name":"date","type":"int"},{"name":"duration","type":"int"},{"name":"size","type":"int"},{"name":"dc_id","type":"int"}],"type":"Audio"},{"id":"922273905","predicate":"documentEmpty","params":[{"name":"id","type":"long"}],"type":"Document"},{"id":"-1627626714","predicate":"document","params":[{"name":"id","type":"long"},{"name":"access_hash","type":"long"},{"name":"user_id","type":"int"},{"name":"date","type":"int"},{"name":"file_name","type":"string"},{"name":"mime_type","type":"string"},{"name":"size","type":"int"},{"name":"thumb","type":"PhotoSize"},{"name":"dc_id","type":"int"}],"type":"Document"}],"methods":[{"id":"-878758099","method":"invokeAfterMsg","params":[{"name":"msg_id","type":"long"},{"name":"query","type":"!X"}],"type":"X"},{"id":"1036301552","method":"invokeAfterMsgs","params":[{"name":"msg_ids","type":"Vector"},{"name":"query","type":"!X"}],"type":"X"},{"id":"1401115413","method":"invokeWithLayer1","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"1877286395","method":"auth.checkPhone","params":[{"name":"phone_number","type":"string"}],"type":"auth.CheckedPhone"},{"id":"1988976461","method":"auth.sendCode","params":[{"name":"phone_number","type":"string"},{"name":"sms_type","type":"int"},{"name":"api_id","type":"int"},{"name":"api_hash","type":"string"},{"name":"lang_code","type":"string"}],"type":"auth.SentCode"},{"id":"63247716","method":"auth.sendCall","params":[{"name":"phone_number","type":"string"},{"name":"phone_code_hash","type":"string"}],"type":"Bool"},{"id":"453408308","method":"auth.signUp","params":[{"name":"phone_number","type":"string"},{"name":"phone_code_hash","type":"string"},{"name":"phone_code","type":"string"},{"name":"first_name","type":"string"},{"name":"last_name","type":"string"}],"type":"auth.Authorization"},{"id":"-1126886015","method":"auth.signIn","params":[{"name":"phone_number","type":"string"},{"name":"phone_code_hash","type":"string"},{"name":"phone_code","type":"string"}],"type":"auth.Authorization"},{"id":"1461180992","method":"auth.logOut","params":[],"type":"Bool"},{"id":"-1616179942","method":"auth.resetAuthorizations","params":[],"type":"Bool"},{"id":"1998331287","method":"auth.sendInvites","params":[{"name":"phone_numbers","type":"Vector"},{"name":"message","type":"string"}],"type":"Bool"},{"id":"-440401971","method":"auth.exportAuthorization","params":[{"name":"dc_id","type":"int"}],"type":"auth.ExportedAuthorization"},{"id":"-470837741","method":"auth.importAuthorization","params":[{"name":"id","type":"int"},{"name":"bytes","type":"bytes"}],"type":"auth.Authorization"},{"id":"1147957548","method":"account.registerDevice","params":[{"name":"token_type","type":"int"},{"name":"token","type":"string"},{"name":"device_model","type":"string"},{"name":"system_version","type":"string"},{"name":"app_version","type":"string"},{"name":"app_sandbox","type":"Bool"},{"name":"lang_code","type":"string"}],"type":"Bool"},{"id":"1707432768","method":"account.unregisterDevice","params":[{"name":"token_type","type":"int"},{"name":"token","type":"string"}],"type":"Bool"},{"id":"-2067899501","method":"account.updateNotifySettings","params":[{"name":"peer","type":"InputNotifyPeer"},{"name":"settings","type":"InputPeerNotifySettings"}],"type":"Bool"},{"id":"313765169","method":"account.getNotifySettings","params":[{"name":"peer","type":"InputNotifyPeer"}],"type":"PeerNotifySettings"},{"id":"-612493497","method":"account.resetNotifySettings","params":[],"type":"Bool"},{"id":"-259486360","method":"account.updateProfile","params":[{"name":"first_name","type":"string"},{"name":"last_name","type":"string"}],"type":"User"},{"id":"1713919532","method":"account.updateStatus","params":[{"name":"offline","type":"Bool"}],"type":"Bool"},{"id":"-1068696894","method":"account.getWallPapers","params":[],"type":"Vector"},{"id":"227648840","method":"users.getUsers","params":[{"name":"id","type":"Vector"}],"type":"Vector"},{"id":"-902781519","method":"users.getFullUser","params":[{"name":"id","type":"InputUser"}],"type":"UserFull"},{"id":"-995929106","method":"contacts.getStatuses","params":[],"type":"Vector"},{"id":"583445000","method":"contacts.getContacts","params":[{"name":"hash","type":"string"}],"type":"contacts.Contacts"},{"id":"-634342611","method":"contacts.importContacts","params":[{"name":"contacts","type":"Vector"},{"name":"replace","type":"Bool"}],"type":"contacts.ImportedContacts"},{"id":"301470424","method":"contacts.search","params":[{"name":"q","type":"string"},{"name":"limit","type":"int"}],"type":"contacts.Found"},{"id":"-847825880","method":"contacts.getSuggested","params":[{"name":"limit","type":"int"}],"type":"contacts.Suggested"},{"id":"-1902823612","method":"contacts.deleteContact","params":[{"name":"id","type":"InputUser"}],"type":"contacts.Link"},{"id":"1504393374","method":"contacts.deleteContacts","params":[{"name":"id","type":"Vector"}],"type":"Bool"},{"id":"858475004","method":"contacts.block","params":[{"name":"id","type":"InputUser"}],"type":"Bool"},{"id":"-448724803","method":"contacts.unblock","params":[{"name":"id","type":"InputUser"}],"type":"Bool"},{"id":"-176409329","method":"contacts.getBlocked","params":[{"name":"offset","type":"int"},{"name":"limit","type":"int"}],"type":"contacts.Blocked"},{"id":"1109588596","method":"messages.getMessages","params":[{"name":"id","type":"Vector"}],"type":"messages.Messages"},{"id":"-321970698","method":"messages.getDialogs","params":[{"name":"offset","type":"int"},{"name":"max_id","type":"int"},{"name":"limit","type":"int"}],"type":"messages.Dialogs"},{"id":"-1834885329","method":"messages.getHistory","params":[{"name":"peer","type":"InputPeer"},{"name":"offset","type":"int"},{"name":"max_id","type":"int"},{"name":"limit","type":"int"}],"type":"messages.Messages"},{"id":"132772523","method":"messages.search","params":[{"name":"peer","type":"InputPeer"},{"name":"q","type":"string"},{"name":"filter","type":"MessagesFilter"},{"name":"min_date","type":"int"},{"name":"max_date","type":"int"},{"name":"offset","type":"int"},{"name":"max_id","type":"int"},{"name":"limit","type":"int"}],"type":"messages.Messages"},{"id":"-1336990448","method":"messages.readHistory","params":[{"name":"peer","type":"InputPeer"},{"name":"max_id","type":"int"},{"name":"offset","type":"int"}],"type":"messages.AffectedHistory"},{"id":"-185009311","method":"messages.deleteHistory","params":[{"name":"peer","type":"InputPeer"},{"name":"offset","type":"int"}],"type":"messages.AffectedHistory"},{"id":"351460618","method":"messages.deleteMessages","params":[{"name":"id","type":"Vector"}],"type":"Vector"},{"id":"962567550","method":"messages.restoreMessages","params":[{"name":"id","type":"Vector"}],"type":"Vector"},{"id":"682347368","method":"messages.receivedMessages","params":[{"name":"max_id","type":"int"}],"type":"Vector"},{"id":"1905801705","method":"messages.setTyping","params":[{"name":"peer","type":"InputPeer"},{"name":"typing","type":"Bool"}],"type":"Bool"},{"id":"1289620139","method":"messages.sendMessage","params":[{"name":"peer","type":"InputPeer"},{"name":"message","type":"string"},{"name":"random_id","type":"long"}],"type":"messages.SentMessage"},{"id":"-1547149962","method":"messages.sendMedia","params":[{"name":"peer","type":"InputPeer"},{"name":"media","type":"InputMedia"},{"name":"random_id","type":"long"}],"type":"messages.StatedMessage"},{"id":"1363988751","method":"messages.forwardMessages","params":[{"name":"peer","type":"InputPeer"},{"name":"id","type":"Vector"}],"type":"messages.StatedMessages"},{"id":"1013621127","method":"messages.getChats","params":[{"name":"id","type":"Vector"}],"type":"messages.Chats"},{"id":"998448230","method":"messages.getFullChat","params":[{"name":"chat_id","type":"int"}],"type":"messages.ChatFull"},{"id":"-1262720843","method":"messages.editChatTitle","params":[{"name":"chat_id","type":"int"},{"name":"title","type":"string"}],"type":"messages.StatedMessage"},{"id":"-662601187","method":"messages.editChatPhoto","params":[{"name":"chat_id","type":"int"},{"name":"photo","type":"InputChatPhoto"}],"type":"messages.StatedMessage"},{"id":"787082910","method":"messages.addChatUser","params":[{"name":"chat_id","type":"int"},{"name":"user_id","type":"InputUser"},{"name":"fwd_limit","type":"int"}],"type":"messages.StatedMessage"},{"id":"-1010447069","method":"messages.deleteChatUser","params":[{"name":"chat_id","type":"int"},{"name":"user_id","type":"InputUser"}],"type":"messages.StatedMessage"},{"id":"1100847854","method":"messages.createChat","params":[{"name":"users","type":"Vector"},{"name":"title","type":"string"}],"type":"messages.StatedMessage"},{"id":"-304838614","method":"updates.getState","params":[],"type":"updates.State"},{"id":"168039573","method":"updates.getDifference","params":[{"name":"pts","type":"int"},{"name":"date","type":"int"},{"name":"qts","type":"int"}],"type":"updates.Difference"},{"id":"-285902432","method":"photos.updateProfilePhoto","params":[{"name":"id","type":"InputPhoto"},{"name":"crop","type":"InputPhotoCrop"}],"type":"UserProfilePhoto"},{"id":"-720397176","method":"photos.uploadProfilePhoto","params":[{"name":"file","type":"InputFile"},{"name":"caption","type":"string"},{"name":"geo_point","type":"InputGeoPoint"},{"name":"crop","type":"InputPhotoCrop"}],"type":"photos.Photo"},{"id":"-1291540959","method":"upload.saveFilePart","params":[{"name":"file_id","type":"long"},{"name":"file_part","type":"int"},{"name":"bytes","type":"bytes"}],"type":"Bool"},{"id":"-475607115","method":"upload.getFile","params":[{"name":"location","type":"InputFileLocation"},{"name":"offset","type":"int"},{"name":"limit","type":"int"}],"type":"upload.File"},{"id":"-990308245","method":"help.getConfig","params":[],"type":"Config"},{"id":"531836966","method":"help.getNearestDc","params":[],"type":"NearestDc"},{"id":"-938300290","method":"help.getAppUpdate","params":[{"name":"device_model","type":"string"},{"name":"system_version","type":"string"},{"name":"app_version","type":"string"},{"name":"lang_code","type":"string"}],"type":"help.AppUpdate"},{"id":"1862465352","method":"help.saveAppLog","params":[{"name":"events","type":"Vector"}],"type":"Bool"},{"id":"-1532407418","method":"help.getInviteText","params":[{"name":"lang_code","type":"string"}],"type":"help.InviteText"},{"id":"-1209117380","method":"photos.getUserPhotos","params":[{"name":"user_id","type":"InputUser"},{"name":"offset","type":"int"},{"name":"max_id","type":"int"},{"name":"limit","type":"int"}],"type":"photos.Photos"},{"id":"681431542","method":"invokeWithLayer2","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"66319602","method":"messages.forwardMessage","params":[{"name":"peer","type":"InputPeer"},{"name":"id","type":"int"},{"name":"random_id","type":"long"}],"type":"messages.StatedMessage"},{"id":"1102776690","method":"messages.sendBroadcast","params":[{"name":"contacts","type":"Vector"},{"name":"message","type":"string"},{"name":"media","type":"InputMedia"}],"type":"messages.StatedMessages"},{"id":"-1220062616","method":"invokeWithLayer3","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"2132356495","method":"geochats.getLocated","params":[{"name":"geo_point","type":"InputGeoPoint"},{"name":"radius","type":"int"},{"name":"limit","type":"int"}],"type":"geochats.Located"},{"id":"-515735953","method":"geochats.getRecents","params":[{"name":"offset","type":"int"},{"name":"limit","type":"int"}],"type":"geochats.Messages"},{"id":"1437853947","method":"geochats.checkin","params":[{"name":"peer","type":"InputGeoChat"}],"type":"geochats.StatedMessage"},{"id":"1730338159","method":"geochats.getFullChat","params":[{"name":"peer","type":"InputGeoChat"}],"type":"messages.ChatFull"},{"id":"1284383347","method":"geochats.editChatTitle","params":[{"name":"peer","type":"InputGeoChat"},{"name":"title","type":"string"},{"name":"address","type":"string"}],"type":"geochats.StatedMessage"},{"id":"903355029","method":"geochats.editChatPhoto","params":[{"name":"peer","type":"InputGeoChat"},{"name":"photo","type":"InputChatPhoto"}],"type":"geochats.StatedMessage"},{"id":"-808598451","method":"geochats.search","params":[{"name":"peer","type":"InputGeoChat"},{"name":"q","type":"string"},{"name":"filter","type":"MessagesFilter"},{"name":"min_date","type":"int"},{"name":"max_date","type":"int"},{"name":"offset","type":"int"},{"name":"max_id","type":"int"},{"name":"limit","type":"int"}],"type":"geochats.Messages"},{"id":"-1254131096","method":"geochats.getHistory","params":[{"name":"peer","type":"InputGeoChat"},{"name":"offset","type":"int"},{"name":"max_id","type":"int"},{"name":"limit","type":"int"}],"type":"geochats.Messages"},{"id":"146319145","method":"geochats.setTyping","params":[{"name":"peer","type":"InputGeoChat"},{"name":"typing","type":"Bool"}],"type":"Bool"},{"id":"102432836","method":"geochats.sendMessage","params":[{"name":"peer","type":"InputGeoChat"},{"name":"message","type":"string"},{"name":"random_id","type":"long"}],"type":"geochats.StatedMessage"},{"id":"-1192173825","method":"geochats.sendMedia","params":[{"name":"peer","type":"InputGeoChat"},{"name":"media","type":"InputMedia"},{"name":"random_id","type":"long"}],"type":"geochats.StatedMessage"},{"id":"235482646","method":"geochats.createGeoChat","params":[{"name":"title","type":"string"},{"name":"geo_point","type":"InputGeoPoint"},{"name":"address","type":"string"},{"name":"venue","type":"string"}],"type":"geochats.StatedMessage"},{"id":"-559885264","method":"invokeWithLayer4","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"1098536878","method":"invokeWithLayer5","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"979686733","method":"invokeWithLayer6","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"-1514252589","method":"invokeWithLayer7","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"651135312","method":"messages.getDhConfig","params":[{"name":"version","type":"int"},{"name":"random_length","type":"int"}],"type":"messages.DhConfig"},{"id":"-162681021","method":"messages.requestEncryption","params":[{"name":"user_id","type":"InputUser"},{"name":"random_id","type":"int"},{"name":"g_a","type":"bytes"}],"type":"EncryptedChat"},{"id":"1035731989","method":"messages.acceptEncryption","params":[{"name":"peer","type":"InputEncryptedChat"},{"name":"g_b","type":"bytes"},{"name":"key_fingerprint","type":"long"}],"type":"EncryptedChat"},{"id":"-304536635","method":"messages.discardEncryption","params":[{"name":"chat_id","type":"int"}],"type":"Bool"},{"id":"2031374829","method":"messages.setEncryptedTyping","params":[{"name":"peer","type":"InputEncryptedChat"},{"name":"typing","type":"Bool"}],"type":"Bool"},{"id":"2135648522","method":"messages.readEncryptedHistory","params":[{"name":"peer","type":"InputEncryptedChat"},{"name":"max_date","type":"int"}],"type":"Bool"},{"id":"-1451792525","method":"messages.sendEncrypted","params":[{"name":"peer","type":"InputEncryptedChat"},{"name":"random_id","type":"long"},{"name":"data","type":"bytes"}],"type":"messages.SentEncryptedMessage"},{"id":"-1701831834","method":"messages.sendEncryptedFile","params":[{"name":"peer","type":"InputEncryptedChat"},{"name":"random_id","type":"long"},{"name":"data","type":"bytes"},{"name":"file","type":"InputEncryptedFile"}],"type":"messages.SentEncryptedMessage"},{"id":"852769188","method":"messages.sendEncryptedService","params":[{"name":"peer","type":"InputEncryptedChat"},{"name":"random_id","type":"long"},{"name":"data","type":"bytes"}],"type":"messages.SentEncryptedMessage"},{"id":"1436924774","method":"messages.receivedQueue","params":[{"name":"max_qts","type":"int"}],"type":"Vector"},{"id":"-374613507","method":"invokeWithLayer8","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"-562337987","method":"upload.saveBigFilePart","params":[{"name":"file_id","type":"long"},{"name":"file_part","type":"int"},{"name":"file_total_parts","type":"int"},{"name":"bytes","type":"bytes"}],"type":"Bool"},{"id":"1769565673","method":"initConnection","params":[{"name":"api_id","type":"int"},{"name":"device_model","type":"string"},{"name":"system_version","type":"string"},{"name":"app_version","type":"string"},{"name":"lang_code","type":"string"},{"name":"query","type":"!X"}],"type":"X"},{"id":"1987140195","method":"invokeWithLayer9","params":[{"name":"query","type":"!X"}],"type":"X"},{"id":"962726977","method":"invokeWithLayer10","params":[{"name":"query","type":"!X"}],"type":"X"}]}; + +Config.Schema.API.layer = 10; + +Config.Emoji = {"00a9":["\u00A9",["copyright"]],"00ae":["\u00AE",["registered"]],"203c":["\u203C",["bangbang"]],"2049":["\u2049",["interrobang"]],"2122":["\u2122",["tm"]],"2139":["\u2139",["information_source"]],"2194":["\u2194",["left_right_arrow"]],"2195":["\u2195",["arrow_up_down"]],"2196":["\u2196",["arrow_upper_left"]],"2197":["\u2197",["arrow_upper_right"]],"2198":["\u2198",["arrow_lower_right"]],"2199":["\u2199",["arrow_lower_left"]],"21a9":["\u21A9",["leftwards_arrow_with_hook"]],"21aa":["\u21AA",["arrow_right_hook"]],"231a":["\u231A",["watch"]],"231b":["\u231B",["hourglass"]],"23e9":["\u23E9",["fast_forward"]],"23ea":["\u23EA",["rewind"]],"23eb":["\u23EB",["arrow_double_up"]],"23ec":["\u23EC",["arrow_double_down"]],"23f0":["\u23F0",["alarm_clock"]],"23f3":["\u23F3",["hourglass_flowing_sand"]],"24c2":["\u24C2",["m"]],"25aa":["\u25AA",["black_small_square"]],"25ab":["\u25AB",["white_small_square"]],"25b6":["\u25B6",["arrow_forward"]],"25c0":["\u25C0",["arrow_backward"]],"25fb":["\u25FB",["white_medium_square"]],"25fc":["\u25FC",["black_medium_square"]],"25fd":["\u25FD",["white_medium_small_square"]],"25fe":["\u25FE",["black_medium_small_square"]],"2600":["\u2600",["sunny"]],"2601":["\u2601",["cloud"]],"260e":["\u260E",["phone","telephone"]],"2611":["\u2611",["ballot_box_with_check"]],"2614":["\u2614",["umbrella"]],"2615":["\u2615",["coffee"]],"261d":["\u261D",["point_up"]],"263a":["\u263A",["relaxed"]],"2648":["\u2648",["aries"]],"2649":["\u2649",["taurus"]],"264a":["\u264A",["gemini"]],"264b":["\u264B",["cancer"]],"264c":["\u264C",["leo"]],"264d":["\u264D",["virgo"]],"264e":["\u264E",["libra"]],"264f":["\u264F",["scorpius"]],"2650":["\u2650",["sagittarius"]],"2651":["\u2651",["capricorn"]],"2652":["\u2652",["aquarius"]],"2653":["\u2653",["pisces"]],"2660":["\u2660",["spades"]],"2663":["\u2663",["clubs"]],"2665":["\u2665",["hearts"]],"2666":["\u2666",["diamonds"]],"2668":["\u2668",["hotsprings"]],"267b":["\u267B",["recycle"]],"267f":["\u267F",["wheelchair"]],"2693":["\u2693",["anchor"]],"26a0":["\u26A0",["warning"]],"26a1":["\u26A1",["zap"]],"26aa":["\u26AA",["white_circle"]],"26ab":["\u26AB",["black_circle"]],"26bd":["\u26BD",["soccer"]],"26be":["\u26BE",["baseball"]],"26c4":["\u26C4",["snowman"]],"26c5":["\u26C5",["partly_sunny"]],"26ce":["\u26CE",["ophiuchus"]],"26d4":["\u26D4",["no_entry"]],"26ea":["\u26EA",["church"]],"26f2":["\u26F2",["fountain"]],"26f3":["\u26F3",["golf"]],"26f5":["\u26F5",["boat","sailboat"]],"26fa":["\u26FA",["tent"]],"26fd":["\u26FD",["fuelpump"]],"2702":["\u2702",["scissors"]],"2705":["\u2705",["white_check_mark"]],"2708":["\u2708",["airplane"]],"2709":["\u2709",["email","envelope"]],"270a":["\u270A",["fist"]],"270b":["\u270B",["hand","raised_hand"]],"270c":["\u270C",["v"]],"270f":["\u270F",["pencil2"]],"2712":["\u2712",["black_nib"]],"2714":["\u2714",["heavy_check_mark"]],"2716":["\u2716",["heavy_multiplication_x"]],"2728":["\u2728",["sparkles"]],"2733":["\u2733",["eight_spoked_asterisk"]],"2734":["\u2734",["eight_pointed_black_star"]],"2744":["\u2744",["snowflake"]],"2747":["\u2747",["sparkle"]],"274c":["\u274C",["x"]],"274e":["\u274E",["negative_squared_cross_mark"]],"2753":["\u2753",["question"]],"2754":["\u2754",["grey_question"]],"2755":["\u2755",["grey_exclamation"]],"2757":["\u2757",["exclamation","heavy_exclamation_mark"]],"2764":["\u2764",["heart"],"<3"],"2795":["\u2795",["heavy_plus_sign"]],"2796":["\u2796",["heavy_minus_sign"]],"2797":["\u2797",["heavy_division_sign"]],"27a1":["\u27A1",["arrow_right"]],"27b0":["\u27B0",["curly_loop"]],"27bf":["\u27BF",["loop"]],"2934":["\u2934",["arrow_heading_up"]],"2935":["\u2935",["arrow_heading_down"]],"2b05":["\u2B05",["arrow_left"]],"2b06":["\u2B06",["arrow_up"]],"2b07":["\u2B07",["arrow_down"]],"2b1b":["\u2B1B",["black_large_square"]],"2b1c":["\u2B1C",["white_large_square"]],"2b50":["\u2B50",["star"]],"2b55":["\u2B55",["o"]],"3030":["\u3030",["wavy_dash"]],"303d":["\u303D",["part_alternation_mark"]],"3297":["\u3297",["congratulations"]],"3299":["\u3299",["secret"]],"1f004":["\uD83C\uDC04",["mahjong"]],"1f0cf":["\uD83C\uDCCF",["black_joker"]],"1f170":["\uD83C\uDD70",["a"]],"1f171":["\uD83C\uDD71",["b"]],"1f17e":["\uD83C\uDD7E",["o2"]],"1f17f":["\uD83C\uDD7F",["parking"]],"1f18e":["\uD83C\uDD8E",["ab"]],"1f191":["\uD83C\uDD91",["cl"]],"1f192":["\uD83C\uDD92",["cool"]],"1f193":["\uD83C\uDD93",["free"]],"1f194":["\uD83C\uDD94",["id"]],"1f195":["\uD83C\uDD95",["new"]],"1f196":["\uD83C\uDD96",["ng"]],"1f197":["\uD83C\uDD97",["ok"]],"1f198":["\uD83C\uDD98",["sos"]],"1f199":["\uD83C\uDD99",["up"]],"1f19a":["\uD83C\uDD9A",["vs"]],"1f201":["\uD83C\uDE01",["koko"]],"1f202":["\uD83C\uDE02",["sa"]],"1f21a":["\uD83C\uDE1A",["u7121"]],"1f22f":["\uD83C\uDE2F",["u6307"]],"1f232":["\uD83C\uDE32",["u7981"]],"1f233":["\uD83C\uDE33",["u7a7a"]],"1f234":["\uD83C\uDE34",["u5408"]],"1f235":["\uD83C\uDE35",["u6e80"]],"1f236":["\uD83C\uDE36",["u6709"]],"1f237":["\uD83C\uDE37",["u6708"]],"1f238":["\uD83C\uDE38",["u7533"]],"1f239":["\uD83C\uDE39",["u5272"]],"1f23a":["\uD83C\uDE3A",["u55b6"]],"1f250":["\uD83C\uDE50",["ideograph_advantage"]],"1f251":["\uD83C\uDE51",["accept"]],"1f300":["\uD83C\uDF00",["cyclone"]],"1f301":["\uD83C\uDF01",["foggy"]],"1f302":["\uD83C\uDF02",["closed_umbrella"]],"1f303":["\uD83C\uDF03",["stars"]],"1f304":["\uD83C\uDF04",["sunrise_over_mountains"]],"1f305":["\uD83C\uDF05",["sunrise"]],"1f306":["\uD83C\uDF06",["city_sunset"]],"1f307":["\uD83C\uDF07",["city_sunrise"]],"1f308":["\uD83C\uDF08",["rainbow"]],"1f309":["\uD83C\uDF09",["bridge_at_night"]],"1f30a":["\uD83C\uDF0A",["ocean"]],"1f30b":["\uD83C\uDF0B",["volcano"]],"1f30c":["\uD83C\uDF0C",["milky_way"]],"1f30d":["\uD83C\uDF0D",["earth_africa"]],"1f30e":["\uD83C\uDF0E",["earth_americas"]],"1f30f":["\uD83C\uDF0F",["earth_asia"]],"1f310":["\uD83C\uDF10",["globe_with_meridians"]],"1f311":["\uD83C\uDF11",["new_moon"]],"1f312":["\uD83C\uDF12",["waxing_crescent_moon"]],"1f313":["\uD83C\uDF13",["first_quarter_moon"]],"1f314":["\uD83C\uDF14",["moon","waxing_gibbous_moon"]],"1f315":["\uD83C\uDF15",["full_moon"]],"1f316":["\uD83C\uDF16",["waning_gibbous_moon"]],"1f317":["\uD83C\uDF17",["last_quarter_moon"]],"1f318":["\uD83C\uDF18",["waning_crescent_moon"]],"1f319":["\uD83C\uDF19",["crescent_moon"]],"1f31a":["\uD83C\uDF1A",["new_moon_with_face"]],"1f31b":["\uD83C\uDF1B",["first_quarter_moon_with_face"]],"1f31c":["\uD83C\uDF1C",["last_quarter_moon_with_face"]],"1f31d":["\uD83C\uDF1D",["full_moon_with_face"]],"1f31e":["\uD83C\uDF1E",["sun_with_face"]],"1f31f":["\uD83C\uDF1F",["star2"]],"1f330":["\uD83C\uDF30",["chestnut"]],"1f331":["\uD83C\uDF31",["seedling"]],"1f332":["\uD83C\uDF32",["evergreen_tree"]],"1f333":["\uD83C\uDF33",["deciduous_tree"]],"1f334":["\uD83C\uDF34",["palm_tree"]],"1f335":["\uD83C\uDF35",["cactus"]],"1f337":["\uD83C\uDF37",["tulip"]],"1f338":["\uD83C\uDF38",["cherry_blossom"]],"1f339":["\uD83C\uDF39",["rose"]],"1f33a":["\uD83C\uDF3A",["hibiscus"]],"1f33b":["\uD83C\uDF3B",["sunflower"]],"1f33c":["\uD83C\uDF3C",["blossom"]],"1f33d":["\uD83C\uDF3D",["corn"]],"1f33e":["\uD83C\uDF3E",["ear_of_rice"]],"1f33f":["\uD83C\uDF3F",["herb"]],"1f340":["\uD83C\uDF40",["four_leaf_clover"]],"1f341":["\uD83C\uDF41",["maple_leaf"]],"1f342":["\uD83C\uDF42",["fallen_leaf"]],"1f343":["\uD83C\uDF43",["leaves"]],"1f344":["\uD83C\uDF44",["mushroom"]],"1f345":["\uD83C\uDF45",["tomato"]],"1f346":["\uD83C\uDF46",["eggplant"]],"1f347":["\uD83C\uDF47",["grapes"]],"1f348":["\uD83C\uDF48",["melon"]],"1f349":["\uD83C\uDF49",["watermelon"]],"1f34a":["\uD83C\uDF4A",["tangerine"]],"1f34b":["\uD83C\uDF4B",["lemon"]],"1f34c":["\uD83C\uDF4C",["banana"]],"1f34d":["\uD83C\uDF4D",["pineapple"]],"1f34e":["\uD83C\uDF4E",["apple"]],"1f34f":["\uD83C\uDF4F",["green_apple"]],"1f350":["\uD83C\uDF50",["pear"]],"1f351":["\uD83C\uDF51",["peach"]],"1f352":["\uD83C\uDF52",["cherries"]],"1f353":["\uD83C\uDF53",["strawberry"]],"1f354":["\uD83C\uDF54",["hamburger"]],"1f355":["\uD83C\uDF55",["pizza"]],"1f356":["\uD83C\uDF56",["meat_on_bone"]],"1f357":["\uD83C\uDF57",["poultry_leg"]],"1f358":["\uD83C\uDF58",["rice_cracker"]],"1f359":["\uD83C\uDF59",["rice_ball"]],"1f35a":["\uD83C\uDF5A",["rice"]],"1f35b":["\uD83C\uDF5B",["curry"]],"1f35c":["\uD83C\uDF5C",["ramen"]],"1f35d":["\uD83C\uDF5D",["spaghetti"]],"1f35e":["\uD83C\uDF5E",["bread"]],"1f35f":["\uD83C\uDF5F",["fries"]],"1f360":["\uD83C\uDF60",["sweet_potato"]],"1f361":["\uD83C\uDF61",["dango"]],"1f362":["\uD83C\uDF62",["oden"]],"1f363":["\uD83C\uDF63",["sushi"]],"1f364":["\uD83C\uDF64",["fried_shrimp"]],"1f365":["\uD83C\uDF65",["fish_cake"]],"1f366":["\uD83C\uDF66",["icecream"]],"1f367":["\uD83C\uDF67",["shaved_ice"]],"1f368":["\uD83C\uDF68",["ice_cream"]],"1f369":["\uD83C\uDF69",["doughnut"]],"1f36a":["\uD83C\uDF6A",["cookie"]],"1f36b":["\uD83C\uDF6B",["chocolate_bar"]],"1f36c":["\uD83C\uDF6C",["candy"]],"1f36d":["\uD83C\uDF6D",["lollipop"]],"1f36e":["\uD83C\uDF6E",["custard"]],"1f36f":["\uD83C\uDF6F",["honey_pot"]],"1f370":["\uD83C\uDF70",["cake"]],"1f371":["\uD83C\uDF71",["bento"]],"1f372":["\uD83C\uDF72",["stew"]],"1f373":["\uD83C\uDF73",["egg"]],"1f374":["\uD83C\uDF74",["fork_and_knife"]],"1f375":["\uD83C\uDF75",["tea"]],"1f376":["\uD83C\uDF76",["sake"]],"1f377":["\uD83C\uDF77",["wine_glass"]],"1f378":["\uD83C\uDF78",["cocktail"]],"1f379":["\uD83C\uDF79",["tropical_drink"]],"1f37a":["\uD83C\uDF7A",["beer"]],"1f37b":["\uD83C\uDF7B",["beers"]],"1f37c":["\uD83C\uDF7C",["baby_bottle"]],"1f380":["\uD83C\uDF80",["ribbon"]],"1f381":["\uD83C\uDF81",["gift"]],"1f382":["\uD83C\uDF82",["birthday"]],"1f383":["\uD83C\uDF83",["jack_o_lantern"]],"1f384":["\uD83C\uDF84",["christmas_tree"]],"1f385":["\uD83C\uDF85",["santa"]],"1f386":["\uD83C\uDF86",["fireworks"]],"1f387":["\uD83C\uDF87",["sparkler"]],"1f388":["\uD83C\uDF88",["balloon"]],"1f389":["\uD83C\uDF89",["tada"]],"1f38a":["\uD83C\uDF8A",["confetti_ball"]],"1f38b":["\uD83C\uDF8B",["tanabata_tree"]],"1f38c":["\uD83C\uDF8C",["crossed_flags"]],"1f38d":["\uD83C\uDF8D",["bamboo"]],"1f38e":["\uD83C\uDF8E",["dolls"]],"1f38f":["\uD83C\uDF8F",["flags"]],"1f390":["\uD83C\uDF90",["wind_chime"]],"1f391":["\uD83C\uDF91",["rice_scene"]],"1f392":["\uD83C\uDF92",["school_satchel"]],"1f393":["\uD83C\uDF93",["mortar_board"]],"1f3a0":["\uD83C\uDFA0",["carousel_horse"]],"1f3a1":["\uD83C\uDFA1",["ferris_wheel"]],"1f3a2":["\uD83C\uDFA2",["roller_coaster"]],"1f3a3":["\uD83C\uDFA3",["fishing_pole_and_fish"]],"1f3a4":["\uD83C\uDFA4",["microphone"]],"1f3a5":["\uD83C\uDFA5",["movie_camera"]],"1f3a6":["\uD83C\uDFA6",["cinema"]],"1f3a7":["\uD83C\uDFA7",["headphones"]],"1f3a8":["\uD83C\uDFA8",["art"]],"1f3a9":["\uD83C\uDFA9",["tophat"]],"1f3aa":["\uD83C\uDFAA",["circus_tent"]],"1f3ab":["\uD83C\uDFAB",["ticket"]],"1f3ac":["\uD83C\uDFAC",["clapper"]],"1f3ad":["\uD83C\uDFAD",["performing_arts"]],"1f3ae":["\uD83C\uDFAE",["video_game"]],"1f3af":["\uD83C\uDFAF",["dart"]],"1f3b0":["\uD83C\uDFB0",["slot_machine"]],"1f3b1":["\uD83C\uDFB1",["8ball"]],"1f3b2":["\uD83C\uDFB2",["game_die"]],"1f3b3":["\uD83C\uDFB3",["bowling"]],"1f3b4":["\uD83C\uDFB4",["flower_playing_cards"]],"1f3b5":["\uD83C\uDFB5",["musical_note"]],"1f3b6":["\uD83C\uDFB6",["notes"]],"1f3b7":["\uD83C\uDFB7",["saxophone"]],"1f3b8":["\uD83C\uDFB8",["guitar"]],"1f3b9":["\uD83C\uDFB9",["musical_keyboard"]],"1f3ba":["\uD83C\uDFBA",["trumpet"]],"1f3bb":["\uD83C\uDFBB",["violin"]],"1f3bc":["\uD83C\uDFBC",["musical_score"]],"1f3bd":["\uD83C\uDFBD",["running_shirt_with_sash"]],"1f3be":["\uD83C\uDFBE",["tennis"]],"1f3bf":["\uD83C\uDFBF",["ski"]],"1f3c0":["\uD83C\uDFC0",["basketball"]],"1f3c1":["\uD83C\uDFC1",["checkered_flag"]],"1f3c2":["\uD83C\uDFC2",["snowboarder"]],"1f3c3":["\uD83C\uDFC3",["runner","running"]],"1f3c4":["\uD83C\uDFC4",["surfer"]],"1f3c6":["\uD83C\uDFC6",["trophy"]],"1f3c7":["\uD83C\uDFC7",["horse_racing"]],"1f3c8":["\uD83C\uDFC8",["football"]],"1f3c9":["\uD83C\uDFC9",["rugby_football"]],"1f3ca":["\uD83C\uDFCA",["swimmer"]],"1f3e0":["\uD83C\uDFE0",["house"]],"1f3e1":["\uD83C\uDFE1",["house_with_garden"]],"1f3e2":["\uD83C\uDFE2",["office"]],"1f3e3":["\uD83C\uDFE3",["post_office"]],"1f3e4":["\uD83C\uDFE4",["european_post_office"]],"1f3e5":["\uD83C\uDFE5",["hospital"]],"1f3e6":["\uD83C\uDFE6",["bank"]],"1f3e7":["\uD83C\uDFE7",["atm"]],"1f3e8":["\uD83C\uDFE8",["hotel"]],"1f3e9":["\uD83C\uDFE9",["love_hotel"]],"1f3ea":["\uD83C\uDFEA",["convenience_store"]],"1f3eb":["\uD83C\uDFEB",["school"]],"1f3ec":["\uD83C\uDFEC",["department_store"]],"1f3ed":["\uD83C\uDFED",["factory"]],"1f3ee":["\uD83C\uDFEE",["izakaya_lantern","lantern"]],"1f3ef":["\uD83C\uDFEF",["japanese_castle"]],"1f3f0":["\uD83C\uDFF0",["european_castle"]],"1f400":["\uD83D\uDC00",["rat"]],"1f401":["\uD83D\uDC01",["mouse2"]],"1f402":["\uD83D\uDC02",["ox"]],"1f403":["\uD83D\uDC03",["water_buffalo"]],"1f404":["\uD83D\uDC04",["cow2"]],"1f405":["\uD83D\uDC05",["tiger2"]],"1f406":["\uD83D\uDC06",["leopard"]],"1f407":["\uD83D\uDC07",["rabbit2"]],"1f408":["\uD83D\uDC08",["cat2"]],"1f409":["\uD83D\uDC09",["dragon"]],"1f40a":["\uD83D\uDC0A",["crocodile"]],"1f40b":["\uD83D\uDC0B",["whale2"]],"1f40c":["\uD83D\uDC0C",["snail"]],"1f40d":["\uD83D\uDC0D",["snake"]],"1f40e":["\uD83D\uDC0E",["racehorse"]],"1f40f":["\uD83D\uDC0F",["ram"]],"1f410":["\uD83D\uDC10",["goat"]],"1f411":["\uD83D\uDC11",["sheep"]],"1f412":["\uD83D\uDC12",["monkey"]],"1f413":["\uD83D\uDC13",["rooster"]],"1f414":["\uD83D\uDC14",["chicken"]],"1f415":["\uD83D\uDC15",["dog2"]],"1f416":["\uD83D\uDC16",["pig2"]],"1f417":["\uD83D\uDC17",["boar"]],"1f418":["\uD83D\uDC18",["elephant"]],"1f419":["\uD83D\uDC19",["octopus"]],"1f41a":["\uD83D\uDC1A",["shell"]],"1f41b":["\uD83D\uDC1B",["bug"]],"1f41c":["\uD83D\uDC1C",["ant"]],"1f41d":["\uD83D\uDC1D",["bee","honeybee"]],"1f41e":["\uD83D\uDC1E",["beetle"]],"1f41f":["\uD83D\uDC1F",["fish"]],"1f420":["\uD83D\uDC20",["tropical_fish"]],"1f421":["\uD83D\uDC21",["blowfish"]],"1f422":["\uD83D\uDC22",["turtle"]],"1f423":["\uD83D\uDC23",["hatching_chick"]],"1f424":["\uD83D\uDC24",["baby_chick"]],"1f425":["\uD83D\uDC25",["hatched_chick"]],"1f426":["\uD83D\uDC26",["bird"]],"1f427":["\uD83D\uDC27",["penguin"]],"1f428":["\uD83D\uDC28",["koala"]],"1f429":["\uD83D\uDC29",["poodle"]],"1f42a":["\uD83D\uDC2A",["dromedary_camel"]],"1f42b":["\uD83D\uDC2B",["camel"]],"1f42c":["\uD83D\uDC2C",["dolphin","flipper"]],"1f42d":["\uD83D\uDC2D",["mouse"]],"1f42e":["\uD83D\uDC2E",["cow"]],"1f42f":["\uD83D\uDC2F",["tiger"]],"1f430":["\uD83D\uDC30",["rabbit"]],"1f431":["\uD83D\uDC31",["cat"]],"1f432":["\uD83D\uDC32",["dragon_face"]],"1f433":["\uD83D\uDC33",["whale"]],"1f434":["\uD83D\uDC34",["horse"]],"1f435":["\uD83D\uDC35",["monkey_face"]],"1f436":["\uD83D\uDC36",["dog"]],"1f437":["\uD83D\uDC37",["pig"]],"1f438":["\uD83D\uDC38",["frog"]],"1f439":["\uD83D\uDC39",["hamster"]],"1f43a":["\uD83D\uDC3A",["wolf"]],"1f43b":["\uD83D\uDC3B",["bear"]],"1f43c":["\uD83D\uDC3C",["panda_face"]],"1f43d":["\uD83D\uDC3D",["pig_nose"]],"1f43e":["\uD83D\uDC3E",["feet","paw_prints"]],"1f440":["\uD83D\uDC40",["eyes"]],"1f442":["\uD83D\uDC42",["ear"]],"1f443":["\uD83D\uDC43",["nose"]],"1f444":["\uD83D\uDC44",["lips"]],"1f445":["\uD83D\uDC45",["tongue"]],"1f446":["\uD83D\uDC46",["point_up_2"]],"1f447":["\uD83D\uDC47",["point_down"]],"1f448":["\uD83D\uDC48",["point_left"]],"1f449":["\uD83D\uDC49",["point_right"]],"1f44a":["\uD83D\uDC4A",["facepunch","punch"]],"1f44b":["\uD83D\uDC4B",["wave"]],"1f44c":["\uD83D\uDC4C",["ok_hand"]],"1f44d":["\uD83D\uDC4D",["+1","thumbsup"]],"1f44e":["\uD83D\uDC4E",["-1","thumbsdown"]],"1f44f":["\uD83D\uDC4F",["clap"]],"1f450":["\uD83D\uDC50",["open_hands"]],"1f451":["\uD83D\uDC51",["crown"]],"1f452":["\uD83D\uDC52",["womans_hat"]],"1f453":["\uD83D\uDC53",["eyeglasses"]],"1f454":["\uD83D\uDC54",["necktie"]],"1f455":["\uD83D\uDC55",["shirt","tshirt"]],"1f456":["\uD83D\uDC56",["jeans"]],"1f457":["\uD83D\uDC57",["dress"]],"1f458":["\uD83D\uDC58",["kimono"]],"1f459":["\uD83D\uDC59",["bikini"]],"1f45a":["\uD83D\uDC5A",["womans_clothes"]],"1f45b":["\uD83D\uDC5B",["purse"]],"1f45c":["\uD83D\uDC5C",["handbag"]],"1f45d":["\uD83D\uDC5D",["pouch"]],"1f45e":["\uD83D\uDC5E",["mans_shoe","shoe"]],"1f45f":["\uD83D\uDC5F",["athletic_shoe"]],"1f460":["\uD83D\uDC60",["high_heel"]],"1f461":["\uD83D\uDC61",["sandal"]],"1f462":["\uD83D\uDC62",["boot"]],"1f463":["\uD83D\uDC63",["footprints"]],"1f464":["\uD83D\uDC64",["bust_in_silhouette"]],"1f465":["\uD83D\uDC65",["busts_in_silhouette"]],"1f466":["\uD83D\uDC66",["boy"]],"1f467":["\uD83D\uDC67",["girl"]],"1f468":["\uD83D\uDC68",["man"]],"1f469":["\uD83D\uDC69",["woman"]],"1f46a":["\uD83D\uDC6A",["family"]],"1f46b":["\uD83D\uDC6B",["couple"]],"1f46c":["\uD83D\uDC6C",["two_men_holding_hands"]],"1f46d":["\uD83D\uDC6D",["two_women_holding_hands"]],"1f46e":["\uD83D\uDC6E",["cop"]],"1f46f":["\uD83D\uDC6F",["dancers"]],"1f470":["\uD83D\uDC70",["bride_with_veil"]],"1f471":["\uD83D\uDC71",["person_with_blond_hair"]],"1f472":["\uD83D\uDC72",["man_with_gua_pi_mao"]],"1f473":["\uD83D\uDC73",["man_with_turban"]],"1f474":["\uD83D\uDC74",["older_man"]],"1f475":["\uD83D\uDC75",["older_woman"]],"1f476":["\uD83D\uDC76",["baby"]],"1f477":["\uD83D\uDC77",["construction_worker"]],"1f478":["\uD83D\uDC78",["princess"]],"1f479":["\uD83D\uDC79",["japanese_ogre"]],"1f47a":["\uD83D\uDC7A",["japanese_goblin"]],"1f47b":["\uD83D\uDC7B",["ghost"]],"1f47c":["\uD83D\uDC7C",["angel"]],"1f47d":["\uD83D\uDC7D",["alien"]],"1f47e":["\uD83D\uDC7E",["space_invader"]],"1f47f":["\uD83D\uDC7F",["imp"]],"1f480":["\uD83D\uDC80",["skull"]],"1f481":["\uD83D\uDC81",["information_desk_person"]],"1f482":["\uD83D\uDC82",["guardsman"]],"1f483":["\uD83D\uDC83",["dancer"]],"1f484":["\uD83D\uDC84",["lipstick"]],"1f485":["\uD83D\uDC85",["nail_care"]],"1f486":["\uD83D\uDC86",["massage"]],"1f487":["\uD83D\uDC87",["haircut"]],"1f488":["\uD83D\uDC88",["barber"]],"1f489":["\uD83D\uDC89",["syringe"]],"1f48a":["\uD83D\uDC8A",["pill"]],"1f48b":["\uD83D\uDC8B",["kiss"]],"1f48c":["\uD83D\uDC8C",["love_letter"]],"1f48d":["\uD83D\uDC8D",["ring"]],"1f48e":["\uD83D\uDC8E",["gem"]],"1f48f":["\uD83D\uDC8F",["couplekiss"]],"1f490":["\uD83D\uDC90",["bouquet"]],"1f491":["\uD83D\uDC91",["couple_with_heart"]],"1f492":["\uD83D\uDC92",["wedding"]],"1f493":["\uD83D\uDC93",["heartbeat"]],"1f494":["\uD83D\uDC94",["broken_heart"],"<\/3"],"1f495":["\uD83D\uDC95",["two_hearts"]],"1f496":["\uD83D\uDC96",["sparkling_heart"]],"1f497":["\uD83D\uDC97",["heartpulse"]],"1f498":["\uD83D\uDC98",["cupid"]],"1f499":["\uD83D\uDC99",["blue_heart"],"<3"],"1f49a":["\uD83D\uDC9A",["green_heart"],"<3"],"1f49b":["\uD83D\uDC9B",["yellow_heart"],"<3"],"1f49c":["\uD83D\uDC9C",["purple_heart"],"<3"],"1f49d":["\uD83D\uDC9D",["gift_heart"]],"1f49e":["\uD83D\uDC9E",["revolving_hearts"]],"1f49f":["\uD83D\uDC9F",["heart_decoration"]],"1f4a0":["\uD83D\uDCA0",["diamond_shape_with_a_dot_inside"]],"1f4a1":["\uD83D\uDCA1",["bulb"]],"1f4a2":["\uD83D\uDCA2",["anger"]],"1f4a3":["\uD83D\uDCA3",["bomb"]],"1f4a4":["\uD83D\uDCA4",["zzz"]],"1f4a5":["\uD83D\uDCA5",["boom","collision"]],"1f4a6":["\uD83D\uDCA6",["sweat_drops"]],"1f4a7":["\uD83D\uDCA7",["droplet"]],"1f4a8":["\uD83D\uDCA8",["dash"]],"1f4a9":["\uD83D\uDCA9",["hankey","poop","shit"]],"1f4aa":["\uD83D\uDCAA",["muscle"]],"1f4ab":["\uD83D\uDCAB",["dizzy"]],"1f4ac":["\uD83D\uDCAC",["speech_balloon"]],"1f4ad":["\uD83D\uDCAD",["thought_balloon"]],"1f4ae":["\uD83D\uDCAE",["white_flower"]],"1f4af":["\uD83D\uDCAF",["100"]],"1f4b0":["\uD83D\uDCB0",["moneybag"]],"1f4b1":["\uD83D\uDCB1",["currency_exchange"]],"1f4b2":["\uD83D\uDCB2",["heavy_dollar_sign"]],"1f4b3":["\uD83D\uDCB3",["credit_card"]],"1f4b4":["\uD83D\uDCB4",["yen"]],"1f4b5":["\uD83D\uDCB5",["dollar"]],"1f4b6":["\uD83D\uDCB6",["euro"]],"1f4b7":["\uD83D\uDCB7",["pound"]],"1f4b8":["\uD83D\uDCB8",["money_with_wings"]],"1f4b9":["\uD83D\uDCB9",["chart"]],"1f4ba":["\uD83D\uDCBA",["seat"]],"1f4bb":["\uD83D\uDCBB",["computer"]],"1f4bc":["\uD83D\uDCBC",["briefcase"]],"1f4bd":["\uD83D\uDCBD",["minidisc"]],"1f4be":["\uD83D\uDCBE",["floppy_disk"]],"1f4bf":["\uD83D\uDCBF",["cd"]],"1f4c0":["\uD83D\uDCC0",["dvd"]],"1f4c1":["\uD83D\uDCC1",["file_folder"]],"1f4c2":["\uD83D\uDCC2",["open_file_folder"]],"1f4c3":["\uD83D\uDCC3",["page_with_curl"]],"1f4c4":["\uD83D\uDCC4",["page_facing_up"]],"1f4c5":["\uD83D\uDCC5",["date"]],"1f4c6":["\uD83D\uDCC6",["calendar"]],"1f4c7":["\uD83D\uDCC7",["card_index"]],"1f4c8":["\uD83D\uDCC8",["chart_with_upwards_trend"]],"1f4c9":["\uD83D\uDCC9",["chart_with_downwards_trend"]],"1f4ca":["\uD83D\uDCCA",["bar_chart"]],"1f4cb":["\uD83D\uDCCB",["clipboard"]],"1f4cc":["\uD83D\uDCCC",["pushpin"]],"1f4cd":["\uD83D\uDCCD",["round_pushpin"]],"1f4ce":["\uD83D\uDCCE",["paperclip"]],"1f4cf":["\uD83D\uDCCF",["straight_ruler"]],"1f4d0":["\uD83D\uDCD0",["triangular_ruler"]],"1f4d1":["\uD83D\uDCD1",["bookmark_tabs"]],"1f4d2":["\uD83D\uDCD2",["ledger"]],"1f4d3":["\uD83D\uDCD3",["notebook"]],"1f4d4":["\uD83D\uDCD4",["notebook_with_decorative_cover"]],"1f4d5":["\uD83D\uDCD5",["closed_book"]],"1f4d6":["\uD83D\uDCD6",["book","open_book"]],"1f4d7":["\uD83D\uDCD7",["green_book"]],"1f4d8":["\uD83D\uDCD8",["blue_book"]],"1f4d9":["\uD83D\uDCD9",["orange_book"]],"1f4da":["\uD83D\uDCDA",["books"]],"1f4db":["\uD83D\uDCDB",["name_badge"]],"1f4dc":["\uD83D\uDCDC",["scroll"]],"1f4dd":["\uD83D\uDCDD",["memo","pencil"]],"1f4de":["\uD83D\uDCDE",["telephone_receiver"]],"1f4df":["\uD83D\uDCDF",["pager"]],"1f4e0":["\uD83D\uDCE0",["fax"]],"1f4e1":["\uD83D\uDCE1",["satellite"]],"1f4e2":["\uD83D\uDCE2",["loudspeaker"]],"1f4e3":["\uD83D\uDCE3",["mega"]],"1f4e4":["\uD83D\uDCE4",["outbox_tray"]],"1f4e5":["\uD83D\uDCE5",["inbox_tray"]],"1f4e6":["\uD83D\uDCE6",["package"]],"1f4e7":["\uD83D\uDCE7",["e-mail"]],"1f4e8":["\uD83D\uDCE8",["incoming_envelope"]],"1f4e9":["\uD83D\uDCE9",["envelope_with_arrow"]],"1f4ea":["\uD83D\uDCEA",["mailbox_closed"]],"1f4eb":["\uD83D\uDCEB",["mailbox"]],"1f4ec":["\uD83D\uDCEC",["mailbox_with_mail"]],"1f4ed":["\uD83D\uDCED",["mailbox_with_no_mail"]],"1f4ee":["\uD83D\uDCEE",["postbox"]],"1f4ef":["\uD83D\uDCEF",["postal_horn"]],"1f4f0":["\uD83D\uDCF0",["newspaper"]],"1f4f1":["\uD83D\uDCF1",["iphone"]],"1f4f2":["\uD83D\uDCF2",["calling"]],"1f4f3":["\uD83D\uDCF3",["vibration_mode"]],"1f4f4":["\uD83D\uDCF4",["mobile_phone_off"]],"1f4f5":["\uD83D\uDCF5",["no_mobile_phones"]],"1f4f6":["\uD83D\uDCF6",["signal_strength"]],"1f4f7":["\uD83D\uDCF7",["camera"]],"1f4f9":["\uD83D\uDCF9",["video_camera"]],"1f4fa":["\uD83D\uDCFA",["tv"]],"1f4fb":["\uD83D\uDCFB",["radio"]],"1f4fc":["\uD83D\uDCFC",["vhs"]],"1f500":["\uD83D\uDD00",["twisted_rightwards_arrows"]],"1f501":["\uD83D\uDD01",["repeat"]],"1f502":["\uD83D\uDD02",["repeat_one"]],"1f503":["\uD83D\uDD03",["arrows_clockwise"]],"1f504":["\uD83D\uDD04",["arrows_counterclockwise"]],"1f505":["\uD83D\uDD05",["low_brightness"]],"1f506":["\uD83D\uDD06",["high_brightness"]],"1f507":["\uD83D\uDD07",["mute"]],"1f509":["\uD83D\uDD09",["sound"]],"1f50a":["\uD83D\uDD0A",["speaker"]],"1f50b":["\uD83D\uDD0B",["battery"]],"1f50c":["\uD83D\uDD0C",["electric_plug"]],"1f50d":["\uD83D\uDD0D",["mag"]],"1f50e":["\uD83D\uDD0E",["mag_right"]],"1f50f":["\uD83D\uDD0F",["lock_with_ink_pen"]],"1f510":["\uD83D\uDD10",["closed_lock_with_key"]],"1f511":["\uD83D\uDD11",["key"]],"1f512":["\uD83D\uDD12",["lock"]],"1f513":["\uD83D\uDD13",["unlock"]],"1f514":["\uD83D\uDD14",["bell"]],"1f515":["\uD83D\uDD15",["no_bell"]],"1f516":["\uD83D\uDD16",["bookmark"]],"1f517":["\uD83D\uDD17",["link"]],"1f518":["\uD83D\uDD18",["radio_button"]],"1f519":["\uD83D\uDD19",["back"]],"1f51a":["\uD83D\uDD1A",["end"]],"1f51b":["\uD83D\uDD1B",["on"]],"1f51c":["\uD83D\uDD1C",["soon"]],"1f51d":["\uD83D\uDD1D",["top"]],"1f51e":["\uD83D\uDD1E",["underage"]],"1f51f":["\uD83D\uDD1F",["keycap_ten"]],"1f520":["\uD83D\uDD20",["capital_abcd"]],"1f521":["\uD83D\uDD21",["abcd"]],"1f522":["\uD83D\uDD22",["1234"]],"1f523":["\uD83D\uDD23",["symbols"]],"1f524":["\uD83D\uDD24",["abc"]],"1f525":["\uD83D\uDD25",["fire"]],"1f526":["\uD83D\uDD26",["flashlight"]],"1f527":["\uD83D\uDD27",["wrench"]],"1f528":["\uD83D\uDD28",["hammer"]],"1f529":["\uD83D\uDD29",["nut_and_bolt"]],"1f52a":["\uD83D\uDD2A",["hocho"]],"1f52b":["\uD83D\uDD2B",["gun"]],"1f52c":["\uD83D\uDD2C",["microscope"]],"1f52d":["\uD83D\uDD2D",["telescope"]],"1f52e":["\uD83D\uDD2E",["crystal_ball"]],"1f52f":["\uD83D\uDD2F",["six_pointed_star"]],"1f530":["\uD83D\uDD30",["beginner"]],"1f531":["\uD83D\uDD31",["trident"]],"1f532":["\uD83D\uDD32",["black_square_button"]],"1f533":["\uD83D\uDD33",["white_square_button"]],"1f534":["\uD83D\uDD34",["red_circle"]],"1f535":["\uD83D\uDD35",["large_blue_circle"]],"1f536":["\uD83D\uDD36",["large_orange_diamond"]],"1f537":["\uD83D\uDD37",["large_blue_diamond"]],"1f538":["\uD83D\uDD38",["small_orange_diamond"]],"1f539":["\uD83D\uDD39",["small_blue_diamond"]],"1f53a":["\uD83D\uDD3A",["small_red_triangle"]],"1f53b":["\uD83D\uDD3B",["small_red_triangle_down"]],"1f53c":["\uD83D\uDD3C",["arrow_up_small"]],"1f53d":["\uD83D\uDD3D",["arrow_down_small"]],"1f550":["\uD83D\uDD50",["clock1"]],"1f551":["\uD83D\uDD51",["clock2"]],"1f552":["\uD83D\uDD52",["clock3"]],"1f553":["\uD83D\uDD53",["clock4"]],"1f554":["\uD83D\uDD54",["clock5"]],"1f555":["\uD83D\uDD55",["clock6"]],"1f556":["\uD83D\uDD56",["clock7"]],"1f557":["\uD83D\uDD57",["clock8"]],"1f558":["\uD83D\uDD58",["clock9"]],"1f559":["\uD83D\uDD59",["clock10"]],"1f55a":["\uD83D\uDD5A",["clock11"]],"1f55b":["\uD83D\uDD5B",["clock12"]],"1f55c":["\uD83D\uDD5C",["clock130"]],"1f55d":["\uD83D\uDD5D",["clock230"]],"1f55e":["\uD83D\uDD5E",["clock330"]],"1f55f":["\uD83D\uDD5F",["clock430"]],"1f560":["\uD83D\uDD60",["clock530"]],"1f561":["\uD83D\uDD61",["clock630"]],"1f562":["\uD83D\uDD62",["clock730"]],"1f563":["\uD83D\uDD63",["clock830"]],"1f564":["\uD83D\uDD64",["clock930"]],"1f565":["\uD83D\uDD65",["clock1030"]],"1f566":["\uD83D\uDD66",["clock1130"]],"1f567":["\uD83D\uDD67",["clock1230"]],"1f5fb":["\uD83D\uDDFB",["mount_fuji"]],"1f5fc":["\uD83D\uDDFC",["tokyo_tower"]],"1f5fd":["\uD83D\uDDFD",["statue_of_liberty"]],"1f5fe":["\uD83D\uDDFE",["japan"]],"1f5ff":["\uD83D\uDDFF",["moyai"]],"1f600":["\uD83D\uDE00",["grinning"]],"1f601":["\uD83D\uDE01",["grin"]],"1f602":["\uD83D\uDE02",["joy"]],"1f603":["\uD83D\uDE03",["smiley"],":)"],"1f604":["\uD83D\uDE04",["smile"],":)"],"1f605":["\uD83D\uDE05",["sweat_smile"]],"1f606":["\uD83D\uDE06",["laughing","satisfied"]],"1f607":["\uD83D\uDE07",["innocent"]],"1f608":["\uD83D\uDE08",["smiling_imp"]],"1f609":["\uD83D\uDE09",["wink"],";)"],"1f60a":["\uD83D\uDE0A",["blush"]],"1f60b":["\uD83D\uDE0B",["yum"]],"1f60c":["\uD83D\uDE0C",["relieved"]],"1f60d":["\uD83D\uDE0D",["heart_eyes"]],"1f60e":["\uD83D\uDE0E",["sunglasses"]],"1f60f":["\uD83D\uDE0F",["smirk"]],"1f610":["\uD83D\uDE10",["neutral_face"]],"1f611":["\uD83D\uDE11",["expressionless"]],"1f612":["\uD83D\uDE12",["unamused"]],"1f613":["\uD83D\uDE13",["sweat"]],"1f614":["\uD83D\uDE14",["pensive"]],"1f615":["\uD83D\uDE15",["confused"]],"1f616":["\uD83D\uDE16",["confounded"]],"1f617":["\uD83D\uDE17",["kissing"]],"1f618":["\uD83D\uDE18",["kissing_heart"]],"1f619":["\uD83D\uDE19",["kissing_smiling_eyes"]],"1f61a":["\uD83D\uDE1A",["kissing_closed_eyes"]],"1f61b":["\uD83D\uDE1B",["stuck_out_tongue"]],"1f61c":["\uD83D\uDE1C",["stuck_out_tongue_winking_eye"],";p"],"1f61d":["\uD83D\uDE1D",["stuck_out_tongue_closed_eyes"]],"1f61e":["\uD83D\uDE1E",["disappointed"],":("],"1f61f":["\uD83D\uDE1F",["worried"]],"1f620":["\uD83D\uDE20",["angry"]],"1f621":["\uD83D\uDE21",["rage"]],"1f622":["\uD83D\uDE22",["cry"],":'("],"1f623":["\uD83D\uDE23",["persevere"]],"1f624":["\uD83D\uDE24",["triumph"]],"1f625":["\uD83D\uDE25",["disappointed_relieved"]],"1f626":["\uD83D\uDE26",["frowning"]],"1f627":["\uD83D\uDE27",["anguished"]],"1f628":["\uD83D\uDE28",["fearful"]],"1f629":["\uD83D\uDE29",["weary"]],"1f62a":["\uD83D\uDE2A",["sleepy"]],"1f62b":["\uD83D\uDE2B",["tired_face"]],"1f62c":["\uD83D\uDE2C",["grimacing"]],"1f62d":["\uD83D\uDE2D",["sob"],":'("],"1f62e":["\uD83D\uDE2E",["open_mouth"]],"1f62f":["\uD83D\uDE2F",["hushed"]],"1f630":["\uD83D\uDE30",["cold_sweat"]],"1f631":["\uD83D\uDE31",["scream"]],"1f632":["\uD83D\uDE32",["astonished"]],"1f633":["\uD83D\uDE33",["flushed"]],"1f634":["\uD83D\uDE34",["sleeping"]],"1f635":["\uD83D\uDE35",["dizzy_face"]],"1f636":["\uD83D\uDE36",["no_mouth"]],"1f637":["\uD83D\uDE37",["mask"]],"1f638":["\uD83D\uDE38",["smile_cat"]],"1f639":["\uD83D\uDE39",["joy_cat"]],"1f63a":["\uD83D\uDE3A",["smiley_cat"]],"1f63b":["\uD83D\uDE3B",["heart_eyes_cat"]],"1f63c":["\uD83D\uDE3C",["smirk_cat"]],"1f63d":["\uD83D\uDE3D",["kissing_cat"]],"1f63e":["\uD83D\uDE3E",["pouting_cat"]],"1f63f":["\uD83D\uDE3F",["crying_cat_face"]],"1f640":["\uD83D\uDE40",["scream_cat"]],"1f645":["\uD83D\uDE45",["no_good"]],"1f646":["\uD83D\uDE46",["ok_woman"]],"1f647":["\uD83D\uDE47",["bow"]],"1f648":["\uD83D\uDE48",["see_no_evil"]],"1f649":["\uD83D\uDE49",["hear_no_evil"]],"1f64a":["\uD83D\uDE4A",["speak_no_evil"]],"1f64b":["\uD83D\uDE4B",["raising_hand"]],"1f64c":["\uD83D\uDE4C",["raised_hands"]],"1f64d":["\uD83D\uDE4D",["person_frowning"]],"1f64e":["\uD83D\uDE4E",["person_with_pouting_face"]],"1f64f":["\uD83D\uDE4F",["pray"]],"1f680":["\uD83D\uDE80",["rocket"]],"1f681":["\uD83D\uDE81",["helicopter"]],"1f682":["\uD83D\uDE82",["steam_locomotive"]],"1f683":["\uD83D\uDE83",["railway_car","train"]],"1f684":["\uD83D\uDE84",["bullettrain_side"]],"1f685":["\uD83D\uDE85",["bullettrain_front"]],"1f686":["\uD83D\uDE86",["train2"]],"1f687":["\uD83D\uDE87",["metro"]],"1f688":["\uD83D\uDE88",["light_rail"]],"1f689":["\uD83D\uDE89",["station"]],"1f68a":["\uD83D\uDE8A",["tram"]],"1f68c":["\uD83D\uDE8C",["bus"]],"1f68d":["\uD83D\uDE8D",["oncoming_bus"]],"1f68e":["\uD83D\uDE8E",["trolleybus"]],"1f68f":["\uD83D\uDE8F",["busstop"]],"1f690":["\uD83D\uDE90",["minibus"]],"1f691":["\uD83D\uDE91",["ambulance"]],"1f692":["\uD83D\uDE92",["fire_engine"]],"1f693":["\uD83D\uDE93",["police_car"]],"1f694":["\uD83D\uDE94",["oncoming_police_car"]],"1f695":["\uD83D\uDE95",["taxi"]],"1f696":["\uD83D\uDE96",["oncoming_taxi"]],"1f697":["\uD83D\uDE97",["car","red_car"]],"1f698":["\uD83D\uDE98",["oncoming_automobile"]],"1f699":["\uD83D\uDE99",["blue_car"]],"1f69a":["\uD83D\uDE9A",["truck"]],"1f69b":["\uD83D\uDE9B",["articulated_lorry"]],"1f69c":["\uD83D\uDE9C",["tractor"]],"1f69d":["\uD83D\uDE9D",["monorail"]],"1f69e":["\uD83D\uDE9E",["mountain_railway"]],"1f69f":["\uD83D\uDE9F",["suspension_railway"]],"1f6a0":["\uD83D\uDEA0",["mountain_cableway"]],"1f6a1":["\uD83D\uDEA1",["aerial_tramway"]],"1f6a2":["\uD83D\uDEA2",["ship"]],"1f6a3":["\uD83D\uDEA3",["rowboat"]],"1f6a4":["\uD83D\uDEA4",["speedboat"]],"1f6a5":["\uD83D\uDEA5",["traffic_light"]],"1f6a6":["\uD83D\uDEA6",["vertical_traffic_light"]],"1f6a7":["\uD83D\uDEA7",["construction"]],"1f6a8":["\uD83D\uDEA8",["rotating_light"]],"1f6a9":["\uD83D\uDEA9",["triangular_flag_on_post"]],"1f6aa":["\uD83D\uDEAA",["door"]],"1f6ab":["\uD83D\uDEAB",["no_entry_sign"]],"1f6ac":["\uD83D\uDEAC",["smoking"]],"1f6ad":["\uD83D\uDEAD",["no_smoking"]],"1f6ae":["\uD83D\uDEAE",["put_litter_in_its_place"]],"1f6af":["\uD83D\uDEAF",["do_not_litter"]],"1f6b0":["\uD83D\uDEB0",["potable_water"]],"1f6b1":["\uD83D\uDEB1",["non-potable_water"]],"1f6b2":["\uD83D\uDEB2",["bike"]],"1f6b3":["\uD83D\uDEB3",["no_bicycles"]],"1f6b4":["\uD83D\uDEB4",["bicyclist"]],"1f6b5":["\uD83D\uDEB5",["mountain_bicyclist"]],"1f6b6":["\uD83D\uDEB6",["walking"]],"1f6b7":["\uD83D\uDEB7",["no_pedestrians"]],"1f6b8":["\uD83D\uDEB8",["children_crossing"]],"1f6b9":["\uD83D\uDEB9",["mens"]],"1f6ba":["\uD83D\uDEBA",["womens"]],"1f6bb":["\uD83D\uDEBB",["restroom"]],"1f6bc":["\uD83D\uDEBC",["baby_symbol"]],"1f6bd":["\uD83D\uDEBD",["toilet"]],"1f6be":["\uD83D\uDEBE",["wc"]],"1f6bf":["\uD83D\uDEBF",["shower"]],"1f6c0":["\uD83D\uDEC0",["bath"]],"1f6c1":["\uD83D\uDEC1",["bathtub"]],"1f6c2":["\uD83D\uDEC2",["passport_control"]],"1f6c3":["\uD83D\uDEC3",["customs"]],"1f6c4":["\uD83D\uDEC4",["baggage_claim"]],"1f6c5":["\uD83D\uDEC5",["left_luggage"]],"0023":["\u0023\u20E3",["hash"]],"0030":["\u0030\u20E3",["zero"]],"0031":["\u0031\u20E3",["one"]],"0032":["\u0032\u20E3",["two"]],"0033":["\u0033\u20E3",["three"]],"0034":["\u0034\u20E3",["four"]],"0035":["\u0035\u20E3",["five"]],"0036":["\u0036\u20E3",["six"]],"0037":["\u0037\u20E3",["seven"]],"0038":["\u0038\u20E3",["eight"]],"0039":["\u0039\u20E3",["nine"]],"1f1e8-1f1f3":["\uD83C\uDDE8\uD83C\uDDF3",["cn"]],"1f1e9-1f1ea":["\uD83C\uDDE9\uD83C\uDDEA",["de"]],"1f1ea-1f1f8":["\uD83C\uDDEA\uD83C\uDDF8",["es"]],"1f1eb-1f1f7":["\uD83C\uDDEB\uD83C\uDDF7",["fr"]],"1f1ec-1f1e7":["\uD83C\uDDEC\uD83C\uDDE7",["gb","uk"]],"1f1ee-1f1f9":["\uD83C\uDDEE\uD83C\uDDF9",["it"]],"1f1ef-1f1f5":["\uD83C\uDDEF\uD83C\uDDF5",["jp"]],"1f1f0-1f1f7":["\uD83C\uDDF0\uD83C\uDDF7",["kr"]],"1f1f7-1f1fa":["\uD83C\uDDF7\uD83C\uDDFA",["ru"]],"1f1fa-1f1f8":["\uD83C\uDDFA\uD83C\uDDF8",["us"]]} diff --git a/app/js/lib/mtproto.js b/app/js/lib/mtproto.js new file mode 100644 index 00000000..9d58eda6 --- /dev/null +++ b/app/js/lib/mtproto.js @@ -0,0 +1,2612 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +var _logTimer = (new Date()).getTime(); +function dLog () { + try { + var t = '[' + (((new Date()).getTime() - _logTimer) / 1000).toFixed(3) + '] '; + if (window.console && console.log) { + var args = Array.prototype.slice.call(arguments); + args.unshift(t); + console.log.apply(console, args); + } + } catch (e) {} + + return true; +} + +function bigint (num) { + return new BigInteger(num.toString(16), 16); +} + +function dHexDump (bytes) { + var arr = []; + for (var i = 0; i < bytes.length; i++) { + if (i && !(i % 2)) { + if (!(i % 16)) { + arr.push("\n"); + } else if (!(i % 4)) { + arr.push(' '); + } else { + arr.push(' '); + } + } + arr.push((bytes[i] < 16 ? '0' : '') + bytes[i].toString(16)); + } + + console.log(arr.join('')); +} + +function bytesToHex (bytes) { + var arr = []; + for (var i = 0; i < bytes.length; i++) { + arr.push((bytes[i] < 16 ? '0' : '') + bytes[i].toString(16)); + } + return arr.join(''); +} + +function bytesFromHex (hexString) { + var len = hexString.length, + i, + bytes = []; + + for (i = 0; i < len; i += 2) { + bytes.push(parseInt(hexString.substr(i, 2), 16)); + } + + return bytes; +} + +function bytesCmp (bytes1, bytes2) { + var len = bytes1.length; + if (len != bytes2.length) { + return false; + } + + for (var i = 0; i < len; i++) { + if (bytes1[i] != bytes2[i]) { + return false; + } + } + return true; +} + +function bytesXor (bytes1, bytes2) { + var len = bytes1.length, + bytes = []; + + for (var i = 0; i < len; ++i) { + bytes[i] = bytes1[i] ^ bytes2[i]; + } + + return bytes; +} + +function bytesToWords (bytes) { + var len = bytes.length, + words = []; + + for (var i = 0; i < len; i++) { + words[i >>> 2] |= bytes[i] << (24 - (i % 4) * 8); + } + + return new CryptoJS.lib.WordArray.init(words, len); +} + +function bytesFromWords (wordArray) { + var words = wordArray.words, + sigBytes = wordArray.sigBytes, + bytes = []; + + for (var i = 0; i < sigBytes; i++) { + bytes.push((words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff); + } + + return bytes; +} + +function bytesFromBigInt (bigInt, len) { + var bytes = bigInt.toByteArray(); + + while (!bytes[0] && (!len || bytes.length > len)) { + bytes = bytes.slice(1); + } + + return bytes; +} + +function bytesToArrayBuffer (b) { + var len = b.length, + array = new Uint8Array(len); + + for (var i = 0; i < len; ++i) { + array[i] = b[i]; + } + + return array.buffer; +} + +function bytesFromArrayBuffer (buffer) { + var len = buffer.byteLength, + byteView = new Uint8Array(buffer), + bytes = []; + + for (var i = 0; i < len; ++i) { + bytes[i] = byteView[i]; + } + + return bytes; +} + +function longToInts (sLong) { + var divRem = new BigInteger(sLong, 10).divideAndRemainder(bigint(0x100000000)); + + return [divRem[0].intValue(), divRem[1].intValue()]; +} + +function longToBytes (sLong) { + return bytesFromWords({words: longToInts(sLong), sigBytes: 8}).reverse(); +} + +function longFromInts (high, low) { + return bigint(high).shiftLeft(32).add(bigint(low)).toString(10); +} + +function intToUint (val) { + val = parseInt(val); + if (val < 0) { + val = val + 4294967296; + } + return val; +} + +function uintToInt (val) { + if (val > 2147483647) { + val = val - 4294967296; + } + return val; +} + +function sha1Hash (bytes) { + // dLog('SHA-1 hash start'); + var hashBytes = sha1.hash(bytes, true); + // dLog('SHA-1 hash finish'); + + return hashBytes; +} + + + +function rsaEncrypt (publicKey, bytes) { + var needPadding = 255 - bytes.length; + if (needPadding > 0) { + var padding = new Array(needPadding); + (new SecureRandom()).nextBytes(padding); + + bytes = bytes.concat(padding); + } + + // dLog('RSA encrypt start'); + var N = new BigInteger(publicKey.modulus, 16), + E = new BigInteger(publicKey.exponent, 16), + X = new BigInteger(bytes), + encryptedBigInt = X.modPowInt(E, N), + encryptedBytes = bytesFromBigInt(encryptedBigInt, 256); + + // dLog('RSA encrypt finish'); + + return encryptedBytes; +} + +function aesEncrypt (bytes, keyBytes, ivBytes) { + // dLog('AES encrypt start', bytes.length/*, bytesToHex(keyBytes), bytesToHex(ivBytes)*/); + + var needPadding = 16 - (bytes.length % 16); + if (needPadding > 0 && needPadding < 16) { + var padding = new Array(needPadding); + (new SecureRandom()).nextBytes(padding); + + bytes = bytes.concat(padding); + } + + var encryptedWords = CryptoJS.AES.encrypt(bytesToWords(bytes), bytesToWords(keyBytes), { + iv: bytesToWords(ivBytes), + padding: CryptoJS.pad.NoPadding, + mode: CryptoJS.mode.IGE + }).ciphertext; + + var encryptedBytes = bytesFromWords(encryptedWords); + + // dLog('AES encrypt finish'); + + return encryptedBytes; +} + +function aesDecrypt (encryptedBytes, keyBytes, ivBytes) { + dLog('AES decrypt start', encryptedBytes.length/*, bytesToHex(keyBytes), bytesToHex(ivBytes)*/); + + var decryptedWords = CryptoJS.AES.decrypt({ciphertext: bytesToWords(encryptedBytes)}, bytesToWords(keyBytes), { + iv: bytesToWords(ivBytes), + padding: CryptoJS.pad.NoPadding, + mode: CryptoJS.mode.IGE + }); + + var bytes = bytesFromWords(decryptedWords); + + dLog('AES decrypt finish'); + + return bytes; +} + +function gzipUncompress (bytes) { + // dLog('Gzip uncompress start'); + var result = (new Zlib.Gunzip(bytes)).decompress(); + // dLog('Gzip uncompress finish'); + return result; +} + +function nextRandomInt (maxValue) { + return Math.floor(Math.random() * maxValue); +}; + +function pqPrimeFactorization (pqBytes) { + dLog('PQ start'); + + var what = new BigInteger(pqBytes), + g; + + var it = 0; + for (var i = 0; i < 3; i++) { + var q = (nextRandomInt(128) & 15) + 17, + x = bigint(nextRandomInt(1000000000) + 1), + y = x.clone(), + lim = 1 << (i + 18); + + for (var j = 1; j < lim; j++) { + ++it; + var a = x.clone(), + b = x.clone(), + c = bigint(q); + + while (!b.equals(BigInteger.ZERO)) { + if (!b.and(BigInteger.ONE).equals(BigInteger.ZERO)) { + c = c.add(a); + if (c.compareTo(what) > 0) { + c = c.subtract(what); + } + } + a = a.add(a); + if (a.compareTo(what) > 0) { + a = a.subtract(what); + } + b = b.shiftRight(1); + } + + x = c.clone(); + var z = x.compareTo(y) < 0 ? y.subtract(x) : x.subtract(y); + g = z.gcd(what); + if (!g.equals(BigInteger.ONE)) { + break; + } + if ((j & (j - 1)) == 0) { + y = x.clone(); + } + } + if (g.compareTo(BigInteger.ONE) > 0) { + break; + } + } + + var f = what.divide(g), P, Q; + + if (g.compareTo(f) > 0) { + P = f; + Q = g; + } else { + P = g; + Q = f; + } + + dLog('PQ finish', it + ' iterations'); + + return [bytesFromBigInt(P), bytesFromBigInt(Q)]; +} + + +function TLSerialization (options) { + options = options || {}; + this.maxLength = options.startMaxLength || 2048; // 2Kb + this.offset = 0; // in bytes + + this.createBuffer(); + + // this.debug = options.debug !== undefined ? options.debug : true; + this.mtproto = options.mtproto || false; + return this; +} + +TLSerialization.prototype.createBuffer = function () { + this.buffer = new ArrayBuffer(this.maxLength); + this.intView = new Int32Array(this.buffer); + this.byteView = new Uint8Array(this.buffer); +}; + +TLSerialization.prototype.getArray = function () { + var resultBuffer = new ArrayBuffer(this.offset); + var resultArray = new Int32Array(resultBuffer); + + resultArray.set(this.intView.subarray(0, this.offset / 4)); + + return resultArray; +}; + +TLSerialization.prototype.getBuffer = function () { + return this.getArray().buffer; +}; + +TLSerialization.prototype.getBytes = function () { + var bytes = []; + for (var i = 0; i < this.offset; i++) { + bytes.push(this.byteView[i]); + } + return bytes; +}; + +TLSerialization.prototype.checkLength = function (needBytes) { + if (this.offset + needBytes < this.maxLength) { + return; + } + + dLog('Increase buffer', this.offset, needBytes, this.maxLength); + console.trace(); + this.maxLength = Math.max(this.maxLength * 2, this.offset + needBytes + 16); + var previousBuffer = this.buffer, + previousArray = new Int32Array(previousBuffer); + + this.createBuffer(); + + new Int32Array(this.buffer).set(previousArray); +}; + +TLSerialization.prototype.writeInt = function (i, field) { + this.debug && dLog('>>>', i.toString(16), i, field); + + this.checkLength(4); + this.intView[this.offset / 4] = i; + this.offset += 4; +}; + +TLSerialization.prototype.storeInt = function (i, field) { + this.writeInt(i, (field || '') + ':int'); +}; + +TLSerialization.prototype.storeBool = function (i, field) { + if (i) { + this.writeInt(0x997275b5, (field || '') + ':bool'); + } else { + this.writeInt(0xbc799737, (field || '') + ':bool'); + } +}; + +TLSerialization.prototype.storeLongP = function (iHigh, iLow, field) { + this.writeInt(iLow, (field || '') + ':long[low]'); + this.writeInt(iHigh, (field || '') + ':long[high]'); +}; + +TLSerialization.prototype.storeLong = function (sLong, field) { + if (angular.isArray(sLong)) { + if (sLong.length == 2) { + return this.storeLongP(sLong[0], sLong[1], field); + } else { + return this.storeIntBytes(sLong, 64, field); + } + } + + var divRem = new BigInteger(sLong, 10).divideAndRemainder(bigint(0x100000000)); + + this.writeInt(intToUint(divRem[1].intValue()), (field || '') + ':long[low]'); + this.writeInt(intToUint(divRem[0].intValue()), (field || '') + ':long[high]'); +}; + +TLSerialization.prototype.storeDouble = function (f) { + var buffer = new ArrayBuffer(8); + var intView = new Int32Array(buffer); + var doubleView = new Float64Array(buffer); + + doubleView[0] = f; + + this.writeInt(intView[0], (field || '') + ':double[low]'); + this.writeInt(intView[1], (field || '') + ':double[high]'); +}; + +TLSerialization.prototype.storeString = function (s, field) { + this.debug && dLog('>>>', s, (field || '') + ':string'); + + var sUTF8 = unescape(encodeURIComponent(s)); + + this.checkLength(sUTF8.length + 8); + + + var len = sUTF8.length; + if (len <= 253) { + this.byteView[this.offset++] = len; + } else { + this.byteView[this.offset++] = 254; + this.byteView[this.offset++] = len & 0xFF; + this.byteView[this.offset++] = (len & 0xFF00) >> 8; + this.byteView[this.offset++] = (len & 0xFF0000) >> 16; + } + for (var i = 0; i < len; i++) { + this.byteView[this.offset++] = sUTF8.charCodeAt(i); + } + + // Padding + while (this.offset % 4) { + this.byteView[this.offset++] = 0; + } +} + + +TLSerialization.prototype.storeBytes = function (bytes, field) { + this.debug && dLog('>>>', bytesToHex(bytes), (field || '') + ':bytes'); + + this.checkLength(bytes.length + 8); + + var len = bytes.length; + if (len <= 253) { + this.byteView[this.offset++] = len; + } else { + this.byteView[this.offset++] = 254; + this.byteView[this.offset++] = len & 0xFF; + this.byteView[this.offset++] = (len & 0xFF00) >> 8; + this.byteView[this.offset++] = (len & 0xFF0000) >> 16; + } + for (var i = 0; i < len; i++) { + this.byteView[this.offset++] = bytes[i]; + } + + // Padding + while (this.offset % 4) { + this.byteView[this.offset++] = 0; + } +} + +TLSerialization.prototype.storeIntBytes = function (bytes, bits, field) { + var len = bytes.length; + if ((bits % 32) || (len * 8) != bits) { + throw new Error('Invalid bits: ' + bits + ', ' + bytes.length); + } + + this.debug && dLog('>>>', bytesToHex(bytes), (field || '') + ':int' + bits); + this.checkLength(len); + + for (var i = 0; i < len; i++) { + this.byteView[this.offset++] = bytes[i]; + } +}; + +TLSerialization.prototype.storeRawBytes = function (bytes, field) { + var len = bytes.length; + + this.debug && dLog('>>>', bytesToHex(bytes), (field || '')); + this.checkLength(len); + + for (var i = 0; i < len; i++) { + this.byteView[this.offset++] = bytes[i]; + } +}; + + +TLSerialization.prototype.storeMethod = function (methodName, params) { + var schema = this.mtproto ? Config.Schema.MTProto : Config.Schema.API, + methodData = false, + i; + + for (i = 0; i < schema.methods.length; i++) { + if (schema.methods[i].method == methodName) { + methodData = schema.methods[i]; + break + } + } + if (!methodData) { + throw new Error('No method ' + methodName + ' found'); + } + + this.storeInt(intToUint(methodData.id), methodName + '[id]'); + + var self = this; + angular.forEach(methodData.params, function (param) { + self.storeObject(params[param.name], param.type, methodName + '[' + param.name + ']'); + }); +}; + +TLSerialization.prototype.storeObject = function (obj, type, field) { + switch (type) { + case 'int': return this.storeInt(obj, field); + case 'long': return this.storeLong(obj, field); + case 'int128': return this.storeIntBytes(obj, 128, field); + case 'int256': return this.storeIntBytes(obj, 256, field); + case 'int512': return this.storeIntBytes(obj, 512, field); + case 'string': return this.storeString(obj, field); + case 'bytes': return this.storeBytes(obj, field); + case 'double': return this.storeDouble(obj, field); + case 'Bool': return this.storeBool(obj, field); + } + + if (angular.isArray(obj)) { + if (type.substr(0, 6) == 'Vector') { + this.writeInt(0x1cb5c415, field + '[id]'); + } + else if (type.substr(0, 6) != 'vector') { + throw new Error('Invalid vector type ' + type); + } + var itemType = type.substr(7, type.length - 8); // for "Vector" + this.writeInt(obj.length, field + '[count]'); + for (var i = 0; i < obj.length; i++) { + this.storeObject(obj[i], itemType, field + '[' + i + ']'); + } + return true; + } + else if (type.substr(0, 6).toLowerCase() == 'vector') { + throw new Error('Invalid vector object'); + } + + if (!angular.isObject(obj)) { + throw new Error('Invalid object for type ' + type); + } + + var schema = this.mtproto ? Config.Schema.MTProto : Config.Schema.API, + predicate = obj['_'], + isBare = false, + constructorData = false, + i; + + if (isBare = (type.charAt(0) == '%')) { + type = type.substr(1); + } + + for (i = 0; i < schema.constructors.length; i++) { + if (schema.constructors[i].predicate == predicate) { + constructorData = schema.constructors[i]; + break + } + } + if (!constructorData) { + throw new Error('No predicate ' + predicate + ' found'); + } + + if (predicate == type) { + isBare = true; + } + + if (!isBare) { + this.writeInt(intToUint(constructorData.id), field + '[' + predicate + '][id]'); + } + + var self = this; + angular.forEach(constructorData.params, function (param) { + self.storeObject(obj[param.name], param.type, field + '[' + predicate + '][' + param.name + ']'); + }); +}; + + + +function TLDeserialization (buffer, options) { + options = options || {}; + + this.offset = 0; // in bytes + + this.buffer = buffer; + this.intView = new Uint32Array(this.buffer); + this.byteView = new Uint8Array(this.buffer); + + // this.debug = options.debug !== undefined ? options.debug : true; + this.mtproto = options.mtproto || false; + return this; +} + +TLDeserialization.prototype.readInt = function (field) { + if (this.offset >= this.intView.length * 4) { + throw new Error('Nothing to fetch'); + } + + var i = this.intView[this.offset / 4]; + + this.debug && dLog('<<<', i.toString(16), i, field); + + this.offset += 4; + + return i; +}; + +TLDeserialization.prototype.fetchInt = function (field) { + return this.readInt((field || '') + ':int'); +} + +TLDeserialization.prototype.fetchDouble = function (field) { + var buffer = new ArrayBuffer(8); + var intView = new Int32Array(buffer); + var doubleView = new Float64Array(buffer); + + intView[0] = this.readInt((field || '') + ':double[low]'), + intView[1] = this.readInt((field || '') + ':double[high]'); + + return doubleView[0]; +}; + +TLDeserialization.prototype.fetchLong = function (field) { + var iLow = this.readInt((field || '') + ':long[low]'), + iHigh = this.readInt((field || '') + ':long[high]'); + + var longDec = bigint(iHigh).shiftLeft(32).add(bigint(iLow)).toString(); + + return longDec; +} + +TLDeserialization.prototype.fetchBool = function (field) { + var i = this.readInt((field || '') + ':bool'); + if (i == 0x997275b5) { + return true; + } else if (i == 0xbc799737) { + return false + } + throw new Error('Unknown Bool constructor ' + i); +} + +TLDeserialization.prototype.fetchString = function (field) { + var len = this.byteView[this.offset++]; + + if (len == 254) { + var len = this.byteView[this.offset++] | + (this.byteView[this.offset++] << 8) | + (this.byteView[this.offset++] << 16); + } + + var sUTF8 = ''; + for (var i = 0; i < len; i++) { + sUTF8 += String.fromCharCode(this.byteView[this.offset++]); + } + + // Padding + while (this.offset % 4) { + this.offset++; + } + + try { + var s = decodeURIComponent(escape(sUTF8)); + } catch (e) { + var s = sUTF8; + } + + this.debug && dLog('<<<', s, (field || '') + ':string'); + + return s; +} + + +TLDeserialization.prototype.fetchBytes = function (field) { + var len = this.byteView[this.offset++]; + + if (len == 254) { + var len = this.byteView[this.offset++] | + (this.byteView[this.offset++] << 8) | + (this.byteView[this.offset++] << 16); + } + + var bytes = []; + for (var i = 0; i < len; i++) { + bytes.push(this.byteView[this.offset++]); + } + + // Padding + while (this.offset % 4) { + this.offset++; + } + + this.debug && dLog('<<<', bytesToHex(bytes), (field || '') + ':bytes'); + + return bytes; +} + +TLDeserialization.prototype.fetchIntBytes = function (bits, field) { + if (bits % 32) { + throw new Error('Invalid bits: ' + bits); + } + + var len = bits / 8; + var bytes = []; + for (var i = 0; i < len; i++) { + bytes.push(this.byteView[this.offset++]); + } + + this.debug && dLog('<<<', bytesToHex(bytes), (field || '') + ':int' + bits); + + return bytes; +}; + + +TLDeserialization.prototype.fetchRawBytes = function (len, field) { + if (len === false) { + len = this.readInt((field || '') + '_length'); + } + + var bytes = []; + for (var i = 0; i < len; i++) { + bytes.push(this.byteView[this.offset++]); + } + + this.debug && dLog('<<<', bytesToHex(bytes), (field || '')); + + return bytes; +}; + +TLDeserialization.prototype.fetchObject = function (type, field) { + switch (type) { + case 'int': return this.fetchInt(field); + case 'long': return this.fetchLong(field); + case 'int128': return this.fetchIntBytes(128, field); + case 'int256': return this.fetchIntBytes(256, field); + case 'int512': return this.fetchIntBytes(512, field); + case 'string': return this.fetchString(field); + case 'bytes': return this.fetchBytes(field); + case 'double': return this.fetchDouble(field); + case 'Bool': return this.fetchBool(field); + } + + field = field || type || 'Object'; + + if (type.substr(0, 6) == 'Vector' || type.substr(0, 6) == 'vector') { + if (type.charAt(0) == 'V') { + var constructor = this.readInt(field + '[id]'); + if (constructor != 0x1cb5c415) { + throw new Error('Invalid vector constructor ' + constructor); + } + } + var len = this.readInt(field + '[count]'); + var result = []; + if (len > 0) { + var itemType = type.substr(7, type.length - 8); // for "Vector" + for (var i = 0; i < len; i++) { + result.push(this.fetchObject(itemType, field + '[' + i + ']')) + } + } + + return result; + } + + var schema = this.mtproto ? Config.Schema.MTProto : Config.Schema.API, + predicate = false, + constructorData = false; + + if (type.charAt(0) == '%') { + var checkType = type.substr(1); + for (i = 0; i < schema.constructors.length; i++) { + if (schema.constructors[i].type == checkType) { + constructorData = schema.constructors[i]; + break + } + } + if (!constructorData) { + throw new Error('Constructor not found for type: ' + type); + } + } + else if (type.charAt(0) >= 97 && type.charAt(0) <= 122) { + for (i = 0; i < schema.constructors.length; i++) { + if (schema.constructors[i].predicate == type) { + constructorData = schema.constructors[i]; + break + } + } + if (!constructorData) { + throw new Error('Constructor not found for predicate: ' + type); + } + } + else { + var constructor = this.readInt(field + '[id]'), + constructorCmp = uintToInt(constructor); + + if (constructorCmp == 0x3072cfa1) { // Gzip packed + var compressed = this.fetchBytes(field + '[packed_string]'), + uncompressed = gzipUncompress(compressed), + buffer = bytesToArrayBuffer(uncompressed), + newDeserializer = (new TLDeserialization(buffer)); + + return newDeserializer.fetchObject(type, field); + } + + for (i = 0; i < schema.constructors.length; i++) { + if (schema.constructors[i].id == constructorCmp) { + constructorData = schema.constructors[i]; + break; + } + } + + var fallback = false; + if (!constructorData && this.mtproto) { + var schemaFallback = Config.Schema.API; + for (i = 0; i < schemaFallback.constructors.length; i++) { + if (schemaFallback.constructors[i].id == constructorCmp) { + constructorData = schemaFallback.constructors[i]; + + delete this.mtproto; + fallback = true; + break; + } + } + } + if (!constructorData) { + throw new Error('Constructor not found: ' + constructor); + } + } + + predicate = constructorData.predicate; + + var result = {'_': predicate}; + + var self = this; + angular.forEach(constructorData.params, function (param) { + result[param.name] = self.fetchObject(param.type, field + '[' + predicate + '][' + param.name + ']'); + }); + + if (fallback) { + this.mtproto = true; + } + + return result; +}; + +TLDeserialization.prototype.getOffset = function () { + return this.offset; +}; + +TLDeserialization.prototype.fetchEnd = function () { + if (this.offset != this.byteView.length) { + throw new Error('Fetch end with non-empty buffer'); + } + return true; +}; + +if (typeof angular != 'undefined') angular.module('mtproto.services', ['myApp.services']). + +factory('MtpDcConfigurator', function () { + var dcOptions = window._testMode + ? [ + {id: 1, host: '173.240.5.253', port: 80}, + {id: 2, host: '95.142.192.65', port: 80}, + {id: 3, host: '174.140.142.5', port: 80} + ] + : [ + {id: 1, host: '173.240.5.1', port: 80}, + {id: 2, host: '95.142.192.66', port: 80}, + {id: 3, host: '174.140.142.6', port: 80}, + {id: 4, host: '31.210.235.12', port: 80}, + {id: 5, host: '116.51.22.2', port: 80}, + ]; + + var chosenServers = {}; + + function chooseServer(dcID) { + if (chosenServers[dcID] === undefined) { + var chosenServer = false, + i, dcOption; + for (i = 0; i < dcOptions.length; i++) { + dcOption = dcOptions[i]; + if (dcOption.id == dcID) { + chosenServer = dcOption.host + ':' + dcOption.port; + } + } + chosenServers[dcID] = chosenServer; + } + + return chosenServers[dcID]; + } + + return { + chooseServer: chooseServer + }; +}). + +factory('MtpRsaKeysManager', function () { + +/** +* Server public key, obtained from here: https://core.telegram.org/api/obtaining_api_id +* +* -----BEGIN RSA PUBLIC KEY----- +* MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6 +* lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS +* an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw +* Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+ +* 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n +* Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB +* -----END RSA PUBLIC KEY----- +*/ + + var publisKeysHex = [{ + modulus: 'c150023e2f70db7985ded064759cfecf0af328e69a41daf4d6f01b538135a6f91f8f8b2a0ec9ba9720ce352efcf6c5680ffc424bd634864902de0b4bd6d49f4e580230e3ae97d95c8b19442b3c0a10d8f5633fecedd6926a7f6dab0ddb7d457f9ea81b8465fcd6fffeed114011df91c059caedaf97625f6c96ecc74725556934ef781d866b34f011fce4d835a090196e9a5f0e4449af7eb697ddb9076494ca5f81104a305b6dd27665722c46b60e5df680fb16b210607ef217652e60236c255f6a28315f4083a96791d7214bf64c1df4fd0db1944fb26a2a57031b32eee64ad15a8ba68885cde74a5bfc920f6abf59ba5c75506373e7130f9042da922179251f', + exponent: '010001' + }]; + + var publicKeysParsed = {}; + var prepared = false; + + function prepareRsaKeys () { + if (prepared) { + return; + } + + for (var i = 0; i < publisKeysHex.length; i++) { + var keyParsed = publisKeysHex[i]; + + var RSAPublicKey = new TLSerialization(); + RSAPublicKey.storeBytes(bytesFromHex(keyParsed.modulus), 'n'); + RSAPublicKey.storeBytes(bytesFromHex(keyParsed.exponent), 'e'); + + var buffer = RSAPublicKey.getBuffer(); + + var fingerprintBytes = sha1Hash(buffer).slice(-8); + fingerprintBytes.reverse(); + + var fingerprint = new BigInteger(fingerprintBytes).toString(16); + + publicKeysParsed[fingerprint] = { + modulus: keyParsed.modulus, + exponent: keyParsed.exponent + }; + } + + prepared = true; + }; + + function selectRsaKeyByFingerPrint (fingerprints) { + prepareRsaKeys(); + + var fingerprintHex, foundKey, i; + for (i = 0; i < fingerprints.length; i++) { + fingerprintHex = new BigInteger(fingerprints[i], 10).toString(16); + if (foundKey = publicKeysParsed[fingerprintHex]) { + return angular.extend({fingerprint: fingerprints[i]}, foundKey); + } + } + + return false; + }; + + return { + prepare: prepareRsaKeys, + select: selectRsaKeyByFingerPrint + }; +}). + +service('MtpSecureRandom', SecureRandom). + +factory('MtpMessageIdGenerator', function (AppConfigManager) { + var lastMessageID = [0, 0], + timeOffset = 0; + + AppConfigManager.get('server_time_offset').then(function (to) { + if (to) { + timeOffset = to; + } + }); + + function generateMessageID () { + var timeTicks = +new Date() + timeOffset, + timeSec = Math.floor(timeTicks / 1000), + timeMSec = timeTicks % 1000, + random = nextRandomInt(0xFFFF); + + var messageID = [timeSec, (timeMSec << 21) | (random << 3) | 4]; + if (lastMessageID[0] > messageID[0] || + lastMessageID[0] == messageID[0] && lastMessageID[1] >= messageID[1]) { + + messageID = [lastMessageID[0], lastMessageID[1] + 4]; + } + + lastMessageID = messageID; + + // dLog('generated msg id', messageID); + + return longFromInts(messageID[0], messageID[1]); + }; + + function applyServerTime (serverTime, localTime) { + timeOffset = serverTime - Math.floor((localTime || +new Date()) / 1000); + AppConfigManager.set({server_time_offset: timeOffset}); + }; + + return { + generateID: generateMessageID, + applyServerTime: applyServerTime + }; +}). + +factory('MtpAuthorizer', function (MtpDcConfigurator, MtpRsaKeysManager, MtpSecureRandom, MtpMessageIdGenerator, $http, $q, $timeout) { + + function mtpSendPlainRequest (dcID, requestBuffer) { + var requestLength = requestBuffer.byteLength, + requestArray = new Int32Array(requestBuffer); + + var header = new TLSerialization(); + header.storeLongP(0, 0, 'auth_key_id'); // Auth key + header.storeLong(MtpMessageIdGenerator.generateID(), 'msg_id'); // Msg_id + header.storeInt(requestLength, 'request_length'); + + var headerBuffer = header.getBuffer(), + headerArray = new Int32Array(headerBuffer), + headerLength = headerBuffer.byteLength; + + var resultBuffer = new ArrayBuffer(headerLength + requestLength), + resultArray = new Int32Array(resultBuffer); + + resultArray.set(headerArray); + resultArray.set(requestArray, headerArray.length); + + delete $http.defaults.headers.post['Content-Type']; + delete $http.defaults.headers.common['Accept']; + + return $http.post('http://' + MtpDcConfigurator.chooseServer(dcID) + '/apiw1', resultArray, { + responseType: 'arraybuffer', + transformRequest: null, + transformResponse: function (responseBuffer) { + var deserializer = new TLDeserialization(responseBuffer, {mtproto: true}); + + var auth_key_id = deserializer.fetchLong('auth_key_id'); + var msg_id = deserializer.fetchLong('msg_id'); + var msg_len = deserializer.fetchInt('msg_len'); + + rng_seed_time(); + + return deserializer; + } + }); + }; + + function mtpSendReqPQ (auth) { + var deferred = auth.deferred; + + var request = new TLSerialization({mtproto: true}); + + request.storeMethod('req_pq', {nonce: auth.nonce}); + + mtpSendPlainRequest(auth.dcID, request.getBuffer()).then(function (result) { + var deserializer = result.data; + var response = deserializer.fetchObject('ResPQ'); + + if (response._ != 'resPQ') { + throw new Error('resPQ response invalid: ' + response._); + } + + if (!bytesCmp (auth.nonce, response.nonce)) { + throw new Error('resPQ nonce mismatch'); + } + + auth.serverNonce = response.server_nonce; + auth.pq = response.pq; + auth.fingerprints = response.server_public_key_fingerprints; + + dLog('ResPQ', bytesToHex(auth.serverNonce), bytesToHex(auth.pq), auth.fingerprints); + + auth.publicKey = MtpRsaKeysManager.select(auth.fingerprints); + + if (!auth.publicKey) { + throw new Error('No public key found'); + } + + if (!!window.Worker) { + var worker = new Worker('js/lib/pq_worker.js'); + + worker.onmessage = function (e) { + auth.p = e.data[0]; + auth.q = e.data[1]; + mtpSendReqDhParams(auth); + }; + worker.onerror = function(error) { + dLog('Worker error', error); + deferred.reject(error); + }; + worker.postMessage(auth.pq) + } else { + var pAndQ = pqPrimeFactorization(auth.pq); + auth.p = pAndQ[0]; + auth.q = pAndQ[1]; + + mtpSendReqDhParams(auth); + } + }, function (error) { + deferred.reject(error); + }); + + $timeout(function () { + MtpRsaKeysManager.prepare(); + }); + }; + + function mtpSendReqDhParams (auth) { + var deferred = auth.deferred; + + auth.newNonce = new Array(32); + MtpSecureRandom.nextBytes(auth.newNonce); + + var data = new TLSerialization({mtproto: true}); + data.storeObject({ + _: 'p_q_inner_data', + pq: auth.pq, + p: auth.p, + q: auth.q, + nonce: auth.nonce, + server_nonce: auth.serverNonce, + new_nonce: auth.newNonce + }, 'P_Q_inner_data', 'DECRYPTED_DATA'); + + var dataWithHash = sha1Hash(data.getBuffer()).concat(data.getBytes()); + + var request = new TLSerialization({mtproto: true}); + request.storeMethod('req_DH_params', { + nonce: auth.nonce, + server_nonce: auth.serverNonce, + p: auth.p, + q: auth.q, + public_key_fingerprint: auth.publicKey.fingerprint, + encrypted_data: rsaEncrypt(auth.publicKey, dataWithHash) + }); + + mtpSendPlainRequest(auth.dcID, request.getBuffer()).then(function (result) { + var deserializer = result.data; + var response = deserializer.fetchObject('Server_DH_Params', 'RESPONSE'); + + if (response._ != 'server_DH_params_fail' && response._ != 'server_DH_params_ok') { + deferred.reject(new Error('Server_DH_Params response invalid: ' + response._)); + return false; + } + + if (!bytesCmp (auth.nonce, response.nonce)) { + deferred.reject(new Error('Server_DH_Params nonce mismatch')); + return false; + } + + if (!bytesCmp (auth.serverNonce, response.server_nonce)) { + deferred.reject(new Error('Server_DH_Params server_nonce mismatch')); + return false; + } + + if (response._ == 'server_DH_params_fail') { + var newNonceHash = sha1Hash(auth.newNonce).slice(-16) + if (!bytesCmp (newNonceHash, response.new_nonce_hash)) { + deferred.reject(new Error('server_DH_params_fail new_nonce_hash mismatch')); + return false; + } + deferred.reject(new Error('server_DH_params_fail')); + return false; + } + + try { + mtpDecryptServerDhDataAnswer(auth, response.encrypted_answer); + } catch (e) { + deferred.reject(e); + return false; + } + + mtpSendSetClientDhParams(auth); + }, function (error) { + deferred.reject(error); + }); + }; + + function mtpDecryptServerDhDataAnswer (auth, encryptedAnswer) { + auth.localTime = +new Date(); + + auth.tmpAesKey = sha1Hash(auth.newNonce.concat(auth.serverNonce)).concat(sha1Hash(auth.serverNonce.concat(auth.newNonce)).slice(0, 12)); + auth.tmpAesIv = sha1Hash(auth.serverNonce.concat(auth.newNonce)).slice(12).concat(sha1Hash([].concat(auth.newNonce, auth.newNonce)), auth.newNonce.slice(0, 4)); + + var answerWithHash = aesDecrypt(encryptedAnswer, auth.tmpAesKey, auth.tmpAesIv); + + var hash = answerWithHash.slice(0, 20); + var answerWithPadding = answerWithHash.slice(20); + var buffer = bytesToArrayBuffer(answerWithPadding); + + var deserializer = new TLDeserialization(buffer, {mtproto: true}); + var response = deserializer.fetchObject('Server_DH_inner_data'); + + if (response._ != 'server_DH_inner_data') { + throw new Error('server_DH_inner_data response invalid: ' + constructor); + } + + if (!bytesCmp (auth.nonce, response.nonce)) { + throw new Error('server_DH_inner_data nonce mismatch'); + } + + if (!bytesCmp (auth.serverNonce, response.server_nonce)) { + throw new Error('server_DH_inner_data serverNonce mismatch'); + } + + auth.g = response.g; + auth.dhPrime = response.dh_prime; + auth.gA = response.g_a; + auth.serverTime = response.server_time; + auth.retry = 0; + + var offset = deserializer.getOffset(); + + if (!bytesCmp(hash, sha1Hash(answerWithPadding.slice(0, offset)))) { + throw new Error('server_DH_inner_data SHA1-hash mismatch'); + } + + MtpMessageIdGenerator.applyServerTime(auth.serverTime, auth.localTime); + }; + + function mtpSendSetClientDhParams(auth) { + var deferred = auth.deferred; + + auth.b = new Array(256); + MtpSecureRandom.nextBytes(auth.b); + + var bBigInt = new BigInteger(auth.b); + var dhPrimeBigInt = new BigInteger(auth.dhPrime); + + var gB = bytesFromBigInt(bigint(auth.g).modPow(bBigInt, dhPrimeBigInt)); + + var data = new TLSerialization({mtproto: true}); + data.storeObject({ + _: 'client_DH_inner_data', + nonce: auth.nonce, + server_nonce: auth.serverNonce, + retry_id: [0, auth.retry++], + g_b: gB, + }, 'Client_DH_Inner_Data'); + + var dataWithHash = sha1Hash(data.getBuffer()).concat(data.getBytes()); + + var encryptedData = aesEncrypt(dataWithHash, auth.tmpAesKey, auth.tmpAesIv); + + var request = new TLSerialization({mtproto: true}); + request.storeMethod('set_client_DH_params', { + nonce: auth.nonce, + server_nonce: auth.serverNonce, + encrypted_data: encryptedData + }); + + mtpSendPlainRequest(auth.dcID, request.getBuffer()).then(function (result) { + var deserializer = result.data; + var response = deserializer.fetchObject('Set_client_DH_params_answer'); + + if (response._ != 'dh_gen_ok' && response._ != 'dh_gen_retry' && response._ != 'dh_gen_fail') { + deferred.reject(new Error('Set_client_DH_params_answer response invalid: ' + response._)); + return false; + } + + if (!bytesCmp (auth.nonce, response.nonce)) { + deferred.reject(new Error('Set_client_DH_params_answer nonce mismatch')); + return false + } + + if (!bytesCmp (auth.serverNonce, response.server_nonce)) { + deferred.reject(new Error('Set_client_DH_params_answer server_nonce mismatch')); + return false; + } + + var bBigInt = new BigInteger(auth.b); + var dhPrimeBigInt = new BigInteger(auth.dhPrime); + + var authKey = bytesFromBigInt((new BigInteger(auth.gA)).modPow(bBigInt, dhPrimeBigInt)), + authKeyHash = sha1Hash(authKey), + authKeyAux = authKeyHash.slice(0, 8), + authKeyID = authKeyHash.slice(-8); + + switch (response._) { + case 'dh_gen_ok': + var newNonceHash1 = sha1Hash(auth.newNonce.concat([1], authKeyAux)).slice(-16); + + if (!bytesCmp(newNonceHash1, response.new_nonce_hash1)) { + deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash1 mismatch')); + return false; + } + + var serverSalt = bytesXor(auth.newNonce.slice(0, 8), auth.serverNonce.slice(0, 8)); + dLog('Auth successfull!', authKeyID, authKey, serverSalt); + + auth.authKeyID = authKeyID; + auth.authKey = authKey; + auth.serverSalt = serverSalt; + + deferred.resolve(auth); + break; + + case 'dh_gen_retry': + var newNonceHash2 = sha1Hash(auth.newNonce.concat([2], authKeyAux)).slice(-16); + if (!bytesCmp(newNonceHash2, response.new_nonce_hash2)) { + deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash2 mismatch')); + return false; + } + + return mtpSendSetClientDhParams(auth); + + case 'dh_gen_fail': + var newNonceHash3 = sha1Hash(auth.newNonce.concat([3], authKeyAux)).slice(-16); + if (!bytesCmp(newNonceHash3, response.new_nonce_hash3)) { + deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash3 mismatch')); + return false; + } + + deferred.reject(new Error('Set_client_DH_params_answer fail')); + return false; + } + + }, function (error) { + deferred.reject(error); + }); + }; + + var cached = {}; + + function mtpAuth (dcID) { + if (cached[dcID] !== undefined) { + return cached[dcID]; + } + + var nonce = []; + for (var i = 0; i < 16; i++) { + nonce.push(nextRandomInt(0xFF)); + } + + if (!MtpDcConfigurator.chooseServer(dcID)) { + return $q.reject(new Error('No server found for dc ' + dcID)); + } + + var auth = { + dcID: dcID, + nonce: nonce, + deferred: $q.defer() + }; + + $timeout(function () { + mtpSendReqPQ(auth); + }); + + return cached[dcID] = auth.deferred.promise; + }; + + return { + auth: mtpAuth + }; + +}). + +factory('MtpAesService', function ($q) { + if (!window.Worker/* || true*/) { + return { + encrypt: function (bytes, keyBytes, ivBytes) { + return $q.when(aesEncrypt(bytes, keyBytes, ivBytes)); + }, + decrypt: function (encryptedBytes, keyBytes, ivBytes) { + return $q.when(aesDecrypt(encryptedBytes, keyBytes, ivBytes)); + } + }; + } + + var worker = new Worker('js/lib/aes_worker.js'), + taskID = 0, + awaiting = {}; + + worker.onmessage = function (e) { + var deferred = awaiting[e.data.taskID]; + if (deferred !== undefined) { + deferred.resolve(e.data.result); + delete awaiting[e.data.taskID]; + } + // dLog('AES worker message', e.data, deferred); + }; + worker.onerror = function(error) { + dLog('AES Worker error', error); + }; + + return { + encrypt: function (bytes, keyBytes, ivBytes) { + var deferred = $q.defer(); + + awaiting[taskID] = deferred; + + // dLog('AES post message', {taskID: taskID, task: 'encrypt', bytes: bytes, keyBytes: keyBytes, ivBytes: ivBytes}) + worker.postMessage({taskID: taskID, task: 'encrypt', bytes: bytes, keyBytes: keyBytes, ivBytes: ivBytes}); + + taskID++ + + return deferred.promise; + }, + decrypt: function (encryptedBytes, keyBytes, ivBytes) { + var deferred = $q.defer(); + + awaiting[taskID] = deferred; + worker.postMessage({taskID: taskID, task: 'decrypt', encryptedBytes: encryptedBytes, keyBytes: keyBytes, ivBytes: ivBytes}); + + taskID++; + + return deferred.promise; + } + } +}). + + +factory('MtpSha1Service', function ($q) { + if (!window.Worker/* || true*/) { + return { + hash: function (bytes) { + return $q.when(sha1Hash(bytes)); + } + }; + } + + var worker = new Worker('js/lib/sha1_worker.js'), + taskID = 0, + awaiting = {}; + + worker.onmessage = function (e) { + var deferred = awaiting[e.data.taskID]; + if (deferred !== undefined) { + deferred.resolve(e.data.result); + delete awaiting[e.data.taskID]; + } + // dLog('sha1 got message', e.data, deferred); + }; + worker.onerror = function(error) { + dLog('SHA-1 Worker error', error); + }; + + return { + hash: function (bytes) { + var deferred = $q.defer(); + + awaiting[taskID] = deferred; + // dLog(11, taskID, bytes); + worker.postMessage({taskID: taskID, bytes: bytes}); + + taskID++; + + return deferred.promise; + } + } +}). + +factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerator, MtpSecureRandom, MtpSha1Service, MtpAesService, AppConfigManager, $http, $q, $timeout) { + + var updatesProcessor; + + function MtpNetworker(dcID, authKey, serverSalt) { + this.dcID = dcID; + + this.authKey = authKey; + this.authKeyID = sha1Hash(authKey).slice(-8); + + this.serverSalt = serverSalt; + + this.sessionID = new Array(8); + MtpSecureRandom.nextBytes(this.sessionID); + + if (true) { + this.sessionID[0] = 0xA; + this.sessionID[1] = 0xB; + this.sessionID[3] = 0xC; + this.sessionID[4] = 0xD; + } + + this.seqNo = 0; + this.currentRequests = 0; + + this.sentMessages = {}; + this.serverMessages = []; + this.clientMessages = []; + + this.pendingMessages = {}; + this.pendingAcks = []; + this.pendingResends = []; + this.connectionInited = false; + + this.pendingTimeouts = []; + + this.longPollInt = setInterval(this.checkLongPoll.bind(this), 10000); + this.checkLongPoll(); + }; + + + MtpNetworker.prototype.generateSeqNo = function (notContentRelated) { + var seqNo = this.seqNo * 2; + + if (!notContentRelated) { + seqNo++; + this.seqNo++; + } + + return seqNo; + } + + MtpNetworker.prototype.wrapMtpCall = function (method, params, options) { + var serializer = new TLSerialization({mtproto: true}); + + serializer.storeMethod(method, params); + + var messageID = MtpMessageIdGenerator.generateID(), + seqNo = this.generateSeqNo(), + message = { + msg_id: messageID, + seq_no: seqNo, + body: serializer.getBytes() + }; + + // dLog('MT call', method, params, messageID, seqNo); + + return this.pushMessage(message, options); + }; + + MtpNetworker.prototype.wrapMtpMessage = function (object, options) { + options = options || {}; + + var serializer = new TLSerialization({mtproto: true}); + serializer.storeObject(object, 'Object'); + + var messageID = MtpMessageIdGenerator.generateID(), + seqNo = this.generateSeqNo(options.notContentRelated), + message = { + msg_id: messageID, + seq_no: seqNo, + body: serializer.getBytes() + }; + + // dLog('MT message', object, messageID, seqNo); + + return this.pushMessage(message, options); + }; + + MtpNetworker.prototype.wrapApiCall = function (method, params, options) { + var serializer = new TLSerialization(options); + + if (!this.connectionInited) { + serializer.storeInt(962726977, 'InokeWithLayer10'); + serializer.storeInt(0x69796de9, 'initConnection'); + serializer.storeInt(777, 'api_id'); + serializer.storeString(navigator.userAgent, 'device_model'); + serializer.storeString(navigator.platform, 'system_version'); + serializer.storeString('0.1', 'app_version'); + serializer.storeString(navigator.language, 'lang_code'); + } + + serializer.storeMethod(method, params); + + var messageID = MtpMessageIdGenerator.generateID(), + seqNo = this.generateSeqNo(), + message = { + msg_id: messageID, + seq_no: seqNo, + body: serializer.getBytes(), + isAPI: true + }; + + dLog('Api call', method, messageID, seqNo); + // dLog('Api call', method, params, messageID, seqNo); + + return this.pushMessage(message, options); + }; + + MtpNetworker.prototype.checkLongPoll = function(force) { + // dLog('Check lp', this.longPollPending, (new Date().getTime())); + if (this.longPollPending && (new Date().getTime()) < this.longPollPending) { + return false; + } + this.sendLongPoll(); + }; + + MtpNetworker.prototype.sendLongPoll = function() { + var maxWait = 25000; + this.longPollPending = (new Date().getTime()) + maxWait; + // dLog('Set lp', this.longPollPending, (new Date().getTime())); + + this.wrapMtpCall('http_wait', {max_delay: 0, wait_after: 0, max_wait: maxWait}, {noResponse: true}). + then((function () { + delete this.longPollPending; + setTimeout(this.checkLongPoll.bind(this), 0); + }).bind(this)); + }; + + MtpNetworker.prototype.pushMessage = function(message, options) { + var deferred = $q.defer(); + + this.sentMessages[message.msg_id] = angular.extend(message, options || {}, {deferred: deferred}); + this.pendingMessages[message.msg_id] = 0; + + if (!options || !options.noShedule) { + this.sheduleRequest(); + } + + return deferred.promise; + }; + + MtpNetworker.prototype.pushResend = function(messageID, delay) { + var value = delay ? (new Date()).getTime() + delay : 0; + var sentMessage = this.sentMessages[messageID]; + if (sentMessage.container) { + for (var i = 0; i < sentMessage.inner.length; i++) { + this.pendingMessages[sentMessage.inner[i]] = value; + } + } else { + this.pendingMessages[messageID] = value; + } + + // dLog('Resend due', messageID, this.pendingMessages); + + this.sheduleRequest(delay); + }; + + MtpNetworker.prototype.getMsgKeyIv = function (msgKey, isOut) { + var authKey = this.authKey, + x = isOut ? 0 : 8; + + var promises = { + sha1a: MtpSha1Service.hash(msgKey.concat(authKey.slice(x, x + 32))), + sha1b: MtpSha1Service.hash(authKey.slice(32 + x, 48 + x).concat(msgKey, authKey.slice(48 + x, 64 + x))), + sha1c: MtpSha1Service.hash(authKey.slice(64 + x, 96 + x).concat(msgKey)), + sha1d: MtpSha1Service.hash(msgKey.concat(authKey.slice(96 + x, 128 + x))) + }; + + return $q.all(promises).then(function (result) { + var aesKey = result.sha1a.slice(0, 8).concat(result.sha1b.slice(8, 20), result.sha1c.slice(4, 16)); + var aesIv = result.sha1a.slice(8, 20).concat(result.sha1b.slice(0, 8), result.sha1c.slice(16, 20), result.sha1d.slice(0, 8)); + + return [aesKey, aesIv]; + }); + }; + + + MtpNetworker.prototype.performSheduledRequest = function() { + // dLog('start sheduled'); + delete this.nextReq; + if (this.pendingAcks.length) { + var ackMsgIDs = []; + for (var i = 0; i < this.pendingAcks.length; i++) { + ackMsgIDs.push(this.pendingAcks[i]); + } + // dLog('acking messages', ackMsgIDs); + this.wrapMtpMessage({_: 'msgs_ack', msg_ids: ackMsgIDs}, {notContentRelated: true, noShedule: true}); + } + + if (this.pendingResends.length) { + var resendMsgIDs = []; + for (var i = 0; i < this.pendingResends.length; i++) { + resendMsgIDs.push(this.pendingResends[i]); + } + // dLog('resendReq messages', resendMsgIDs); + this.wrapMtpMessage({_: 'msg_resend_req', msg_ids: resendMsgIDs}, {noShedule: true}); + } + + var messages = [], + message, + messagesByteLen = 0, + currentTime = (new Date()).getTime(), + self = this; + + angular.forEach(this.pendingMessages, function (value, messageID) { + if (!value || value >= currentTime) { + if (message = self.sentMessages[messageID]) { + messages.push(message); + messagesByteLen += message.body.length + 32; + } else { + // dLog(message, messageID); + } + delete self.pendingMessages[messageID]; + } + }); + + if (!messages.length) { + // dLog('no sheduled messages'); + return; + } + + var noResponseMsgs = []; + + if (messages.length > 1) { + var container = new TLSerialization({mtproto: true, startMaxLength: messagesByteLen + 64}); + container.storeInt(0x73f1f8dc, 'CONTAINER[id]'); + container.storeInt(messages.length, 'CONTAINER[count]'); + var onloads = []; + var innerMessages = []; + for (var i = 0; i < messages.length; i++) { + container.storeLong(messages[i].msg_id, 'CONTAINER[' + i + '][msg_id]'); + innerMessages.push(messages[i].msg_id); + container.storeInt(messages[i].seq_no, 'CONTAINER[' + i + '][seq_no]'); + container.storeInt(messages[i].body.length, 'CONTAINER[' + i + '][bytes]'); + container.storeRawBytes(messages[i].body, 'CONTAINER[' + i + '][body]'); + if (messages[i].noResponse) { + noResponseMsgs.push(messages[i].msg_id); + } + } + + var containerSentMessage = { + msg_id: MtpMessageIdGenerator.generateID(), + seq_no: this.generateSeqNo(true), + container: true, + inner: innerMessages + } + + message = angular.extend({body: container.getBytes()}, containerSentMessage); + + this.sentMessages[message.msg_id] = containerSentMessage; + + // dLog('Container', innerMessages, message.msg_id, message.seq_no); + } else { + if (message.noResponse) { + noResponseMsgs.push(message.msg_id); + } + this.sentMessages[message.msg_id] = message; + } + + this.pendingAcks = []; + var self = this; + + this.sendEncryptedRequest(message).then(function (result) { + self.parseResponse(result.data); + + if (noResponseMsgs.length) { + $timeout(function () { + angular.forEach(noResponseMsgs, function (msgID) { + if (self.sentMessages[msgID]) { + var deferred = self.sentMessages[msgID].deferred; + delete self.sentMessages[msgID]; + deferred.resolve(); + } + }); + }, 200); + } + }); + }; + + MtpNetworker.prototype.getEncryptedMessage = function (bytes) { + var self = this; + + // dLog('enc', bytes); + + return MtpSha1Service.hash(bytes).then(function (bytesHash) { + // dLog('bytesHash', bytesHash); + var msgKey = bytesHash.slice(-16); + return self.getMsgKeyIv(msgKey, true).then(function (keyIv) { + // dLog('keyIv', keyIv); + return MtpAesService.encrypt(bytes, keyIv[0], keyIv[1]).then(function (encryptedBytes) { + // dLog('encryptedBytes', encryptedBytes); + return { + bytes: encryptedBytes, + msgKey: msgKey + }; + }) + }) + }) + }; + + MtpNetworker.prototype.getDecryptedMessage = function (msgKey, encryptedData) { + return this.getMsgKeyIv(msgKey, false).then(function (keyIv) { + return MtpAesService.decrypt(encryptedData, keyIv[0], keyIv[1]); + }); + }; + + MtpNetworker.prototype.sendEncryptedRequest = function (message) { + var self = this; + // dLog('send encrypted', message); + // console.trace(); + var data = new TLSerialization({startMaxLength: message.body.length + 64}); + + data.storeIntBytes(this.serverSalt, 64, 'salt'); + data.storeIntBytes(this.sessionID, 64, 'session_id'); + + data.storeLong(message.msg_id, 'message_id'); + data.storeInt(message.seq_no, 'seq_no'); + + data.storeInt(message.body.length, 'message_data_length'); + data.storeRawBytes(message.body, 'message_data'); + + return this.getEncryptedMessage(data.getBytes()).then(function (encryptedResult) { + // dLog('got enc result', encryptedResult); + var request = new TLSerialization({startMaxLength: encryptedResult.bytes.length + 256}); + request.storeIntBytes(self.authKeyID, 64, 'auth_key_id'); + request.storeIntBytes(encryptedResult.msgKey, 128, 'msg_key'); + request.storeRawBytes(encryptedResult.bytes, 'encrypted_data'); + + delete $http.defaults.headers.post['Content-Type']; + delete $http.defaults.headers.common['Accept']; + + return $http.post('http://' + MtpDcConfigurator.chooseServer(self.dcID) + '/apiw1', request.getArray(), { + responseType: 'arraybuffer', + transformRequest: null + }); + }); + }; + + MtpNetworker.prototype.parseResponse = function (responseBuffer) { + var self = this; + + var deserializer = new TLDeserialization(responseBuffer); + + var authKeyID = deserializer.fetchIntBytes(64, 'auth_key_id'); + if (!bytesCmp(authKeyID, this.authKeyID)) { + throw new Error('Invalid server auth_key_id: ' + bytesToHex(authKeyID)); + } + var msgKey = deserializer.fetchIntBytes(128, 'msg_key'); + + var dataLength = responseBuffer.byteLength - deserializer.getOffset(); + var encryptedData = deserializer.fetchRawBytes(dataLength, 'encrypted_data'); + + this.getDecryptedMessage(msgKey, encryptedData).then(function (dataWithPadding) { + var buffer = bytesToArrayBuffer(dataWithPadding); + + var deserializer = new TLDeserialization(buffer, {mtproto: true}); + + var salt = deserializer.fetchIntBytes(64, 'salt'); + var sessionID = deserializer.fetchIntBytes(64, 'session_id'); + var messageID = deserializer.fetchLong('message_id'); + + var seqNo = deserializer.fetchInt('seq_no'); + + var messageBody = deserializer.fetchRawBytes(false, 'message_data'); + + var offset = deserializer.getOffset(); + + MtpSha1Service.hash(dataWithPadding.slice(0, offset)).then(function (dataHashed) { + if (!bytesCmp(msgKey, dataHashed.slice(-16))) { + throw new Error('server msgKey mismatch'); + } + + var buffer = bytesToArrayBuffer(messageBody); + var deserializer = new TLDeserialization(buffer, {mtproto: true}); + + var response = deserializer.fetchObject('', 'INPUT'); + + // dLog('Server response', response); + + self.processResponse(response, messageID, sessionID, seqNo); + }); + }); + }; + + MtpNetworker.prototype.applyServerSalt = function (newServerSalt) { + var serverSalt = longToBytes(newServerSalt); + + var storeObj = {}; + storeObj['dc' + this.dcID + '_server_salt'] = bytesToHex(serverSalt); + AppConfigManager.set(storeObj); + + this.serverSalt = serverSalt; + return true; + }; + + MtpNetworker.prototype.sheduleRequest = function (delay) { + var nextReq = new Date() + delay; + + if (delay && this.nextReq && this.nextReq <= nextReq) { + return false; + } + + // dLog('shedule req', delay); + // console.trace(); + + clearTimeout(this.nextReqTO); + + this.nextReqTO = setTimeout(this.performSheduledRequest.bind(this), delay || 0); + this.nextReq = nextReq; + }; + + MtpNetworker.prototype.onSessionCreate = function (sessionID, messageID) { + dLog('New session created', bytesToHex(sessionID)); + }; + + MtpNetworker.prototype.ackMessage = function (msgID) { + // dLog('ack message', msgID); + this.pendingAcks.push(msgID); + this.sheduleRequest(30000); + }; + + MtpNetworker.prototype.reqResendMessage = function (msgID) { + dLog('req resend', msgID); + this.pendingResends.push(msgID); + this.sheduleRequest(100); + }; + + MtpNetworker.prototype.processResponse = function (response, messageID, sessionID, seqNo) { + return this.processMessage(response, messageID, sessionID); + }; + + MtpNetworker.prototype.processMessageAck = function (messageID) { + var sentMessage = this.sentMessages[messageID]; + if (sentMessage && !sentMessage.acked) { + delete sentMessage.body; + sentMessage.acked = true; + + return true; + } + + return false; + }; + + MtpNetworker.prototype.processError = function (rawError) { + var matches = (rawError.error_message || '').match(/^([A-Z_0-9]+\b)(: (.+))?/) || []; + rawError.error_code = uintToInt(rawError.error_code); + + return { + code: !rawError.error_code || rawError.error_code <= 0 ? 500 : rawError.error_code, + type: matches[1] || 'UNKNOWN', + description: matches[3] || ('CODE#' + rawError.error_code + ' ' + rawError.error_message), + originalError: rawError + }; + }; + + + MtpNetworker.prototype.processMessage = function (message, messageID, sessionID) { + // dLog('process message', message, messageID, sessionID); + switch (message._) { + case 'msg_container': + var len = message.messages.length; + for (var i = 0; i < len; i++) { + this.processMessage(message.messages[i], messageID, sessionID); + } + break; + + case 'bad_server_salt': + var sentMsg = this.sentMessages[message.bad_msg_id]; + if (!sentMsg || sentMsg.seq_no != message.bad_msg_seqno) { + dLog(message.bad_msg_id, message.bad_msg_seqno); + throw new Error('Bad server salt for invalid message'); + } + + this.applyServerSalt(message.new_server_salt); + this.pushResend(message.bad_msg_id); + this.ackMessage(messageID); + break; + + case 'message': + this.serverMessages.push(message.msg_id); + this.processMessage(message.body, message.msg_id, sessionID); + break; + + case 'new_session_created': + this.ackMessage(messageID); + + this.processMessageAck(message.first_msg_id); + this.applyServerSalt(message.server_salt); + this.onSessionCreate(sessionID, messageID); + break; + + case 'msgs_ack': + for (var i = 0; i < message.msg_ids.length; i++) { + this.processMessageAck(message.msg_ids[i]); + } + break; + + case 'msg_detailed_info': + if (!this.sentMessages[message.msg_id]) { + this.ackMessage(message.answer_msg_id); + break; + } + case 'msg_new_detailed_info': + // this.ackMessage(message.answer_msg_id); + this.reqResendMessage(message.answer_msg_id); + break; + + case 'rpc_result': + this.ackMessage(messageID); + + var sentMessageID = message.req_msg_id, + sentMessage = this.sentMessages[sentMessageID]; + + this.processMessageAck(sentMessageID); + if (sentMessage) { + var deferred = sentMessage.deferred; + if (message.result._ == 'rpc_error') { + var error = this.processError(message.result); + dLog('rpc error', error) + if (deferred) { + deferred.reject(error) + } + } else { + if (deferred) { + dLog('rpc response', message.result); + sentMessage.deferred.resolve(message.result); + } + if (sentMessage.isAPI) { + this.connectionInited = true; + } + } + + delete this.sentMessages[sentMessageID]; + } + break; + + default: + this.ackMessage(messageID); + + // dLog('Update', message); + if (updatesProcessor) { + updatesProcessor(message); + } + break; + + } + }; + + return { + getNetworker: function (dcID, authKey, serverSalt) { + return new MtpNetworker(dcID, authKey, serverSalt); + }, + setUpdatesProcessor: function (callback) { + updatesProcessor = callback; + } + }; + +}). + +factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworkerFactory, $q) { + var cachedNetworkers = {}, + cachedExportPromise = {}, + baseDcID = false; + + AppConfigManager.get('dc').then(function (dcID) { + if (dcID) { + baseDcID = dcID; + } + }); + + function mtpSetUserAuth (dcID, userAuth) { + AppConfigManager.set({ + dc: dcID, + user_auth: angular.extend({dcID: dcID}, userAuth) + }); + + baseDcID = dcID; + } + + function mtpLogOut () { + return mtpInvokeApi('auth.logOut').then(function () { + AppConfigManager.remove('dc', 'user_auth'); + + baseDcID = false; + }); + } + + function mtpGetNetworker (dcID) { + if (!dcID) { + throw new Exception('get Networker without dcID'); + } + + if (cachedNetworkers[dcID] !== undefined) { + return $q.when(cachedNetworkers[dcID]); + } + + var deferred = $q.defer(), + ak = 'dc' + dcID + '_auth_key', + ssk = 'dc' + dcID + '_server_salt'; + + AppConfigManager.get(ak, ssk).then(function (result) { + + if (cachedNetworkers[dcID] !== undefined) { + return deferred.resolve(cachedNetworkers[dcID]); + } + + var authKeyHex = result[0], + serverSaltHex = result[1]; + // dLog('ass', dcID, authKeyHex, serverSaltHex); + if (authKeyHex && authKeyHex.length == 512) { + var authKey = bytesFromHex(authKeyHex); + var serverSalt = bytesFromHex(serverSaltHex); + + return deferred.resolve(cachedNetworkers[dcID] = MtpNetworkerFactory.getNetworker(dcID, authKey, serverSalt)); + } + + MtpAuthorizer.auth(dcID).then(function (auth) { + var storeObj = {}; + storeObj[ak] = bytesToHex(auth.authKey); + storeObj[ssk] = bytesToHex(auth.serverSalt); + AppConfigManager.set(storeObj); + + deferred.resolve( + cachedNetworkers[dcID] = MtpNetworkerFactory.getNetworker(dcID, auth.authKey, auth.serverSalt) + ); + }, function (error) { + dLog('Get networker error', error, error.stack); + deferred.reject(error); + }); + + }); + + return deferred.promise; + }; + + function mtpInvokeApi (method, params, options) { + var deferred = $q.defer(); + + options = options || {}; + var dcID = options.dcID || baseDcID || 1; + + var cachedNetworker; + + mtpGetNetworker(dcID).then(function (networker) { + return (cachedNetworker = networker).wrapApiCall(method, params, options).then( + function (result) { + deferred.resolve(result); + // setTimeout(function () { + // deferred.resolve(result); + // },1000); + }, + function (error) { + dLog('error', error.code, error.type, baseDcID, dcID); + if (error.code == 401 && error.type == 'AUTH_KEY_UNREGISTERED' && baseDcID && dcID != baseDcID) { + if (cachedExportPromise[dcID] === undefined) { + var exportDeferred = $q.defer(); + + mtpInvokeApi('auth.exportAuthorization', {dc_id: dcID}).then(function (exportedAuth) { + mtpInvokeApi('auth.importAuthorization', { + id: exportedAuth.id, + bytes: exportedAuth.bytes + }, {dcID: dcID}).then(function () { + exportDeferred.resolve(); + }, function (e) { + exportDeferred.reject(e); + }) + }, function (e) { + exportDeferred.reject(e) + }); + + cachedExportPromise[dcID] = exportDeferred.promise; + } + + // dLog('promise', cachedExportPromise[dcID]); + + cachedExportPromise[dcID] = cachedExportPromise[dcID].then(function () { + (cachedNetworker = networker).wrapApiCall(method, params, options).then(function (result) { + deferred.resolve(result); + }, function (error) { + deferred.reject(error); + }); + }, function (error) { + deferred.reject(error); + }); + } else { + deferred.reject(error); + } + }); + }); + + return deferred.promise; + }; + + function mtpGetUserID () { + var deferred = $q.defer(); + + AppConfigManager.get('user_auth').then(function (auth) { + deferred.resolve(auth.id || 0); + }); + + return deferred.promise; + } + + return { + getUserID: mtpGetUserID, + invokeApi: mtpInvokeApi, + setUserAuth: mtpSetUserAuth, + logOut: mtpLogOut + } +}). + + +factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { + + var cachedFS = false; + var apiUploadPromise = $q.when(); + var cachedSavePromises = {}; + var cachedDownloadPromises = {}; + + var downloadPull = []; + var downloadActive = 0; + var downloadLimit = 5; + + function downloadRequest(cb, activeDelta) { + var deferred = $q.defer(); + downloadPull.push({cb: cb, deferred: deferred, activeDelta: activeDelta}); + downloadCheck(); + + return deferred.promise; + }; + + var index = 0; + + function downloadCheck() { + if (downloadActive >= downloadLimit || !downloadPull.length) { + return false; + } + + var data = downloadPull.shift(), + activeDelta = data.activeDelta || 1; + + downloadActive += activeDelta; + + var a = index++; + data.cb() + .then(function (result) { + downloadActive -= activeDelta; + downloadCheck(); + + data.deferred.resolve(result); + + }, function (error) { + downloadActive -= activeDelta; + downloadCheck(); + + data.deferred.reject(error); + }) + }; + + function requestFS (argument) { + if (cachedFS) { + return $q.when(cachedFS); + } + + var deferred = $q.defer(); + + $window.requestFileSystem = $window.requestFileSystem || $window.webkitRequestFileSystem; + + $window.requestFileSystem($window.TEMPORARY, 5*1024*1024, function (fs) { + cachedFS = fs; + deferred.resolve(); + }, function (e) { + deferred.reject(e); + }); + + return deferred.promise; + }; + + function fileWriteBytes(fileWriter, bytes) { + var deferred = $q.defer(); + + fileWriter.onwriteend = function(e) { + deferred.resolve(); + }; + fileWriter.onerror = function (e) { + deferred.reject(); + }; + + if (false) { // is file bytes + fileWriter.write(bytes); + } else { + fileWriter.write(new Blob([bytesToArrayBuffer(bytes)])); + } + + return deferred.promise; + } + + function getFileName(location) { + switch (location._) { + case 'inputVideoFileLocation': + return 'video' + location.id + '.mp4'; + + case 'inputDocumentFileLocation': + return 'doc' + location.id; + } + return location.volume_id + '_' + location.local_id + '_' + location.secret + '.jpg'; + }; + + function getTempFileName(file) { + var size = file.size || -1; + var random = nextRandomInt(0xFFFFFFFF); + return '_temp' + random + '_' + size; + }; + + function getCachedFile (location) { + var fileName = getFileName(location); + + if (cachedSavePromises[fileName]) { + return cachedSavePromises[fileName]; + } + var deferred = $q.defer(), + errorHandler = function (error) { + deferred.reject(); + }; + + requestFS().then(function () { + cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) { + deferred.resolve(fileEntry.toURL()); + }, errorHandler); + }, errorHandler); + + return deferred.promise; + } + + function saveSmallFile (location, bytes) { + var fileName = getFileName(location); + + if (cachedSavePromises[fileName]) { + return cachedSavePromises[fileName]; + } + var deferred = $q.defer(), + cacheFileWriter, + errorHandler = function (error) { + deferred.reject(error); + if (cacheFileWriter) cacheFileWriter.truncate(); + }; + + requestFS().then(function () { + cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) { + deferred.resolve(fileEntry.toURL()); + }, function () { + cachedFS.root.getFile(fileName, {create: true}, function(fileEntry) { + fileEntry.createWriter(function (fileWriter) { + cacheFileWriter = fileWriter; + fileWriteBytes(fileWriter, bytes).then(function () { + deferred.resolve(fileEntry.toURL()); + }, errorHandler); + }, errorHandler); + }, errorHandler); + }); + }, errorHandler); + + return cachedSavePromises[fileName] = deferred.promise; + } + + function downloadSmallFile(location) { + // dLog('dload small', location); + var fileName = getFileName(location), + cachedPromise = cachedSavePromises[fileName] || cachedDownloadPromises[fileName]; + + if (cachedPromise) { + return cachedPromise; + } + + var deferred = $q.defer(), + cacheFileWriter, + errorHandler = function (error) { + deferred.reject(error); + if (cacheFileWriter) cacheFileWriter.truncate(); + }, + doDownload = function () { + cachedFS.root.getFile(fileName, {create: true}, function(fileEntry) { + var downloadPromise = downloadRequest(function () { + // dLog('next small promise'); + return MtpApiManager.invokeApi('upload.getFile', { + location: angular.extend({}, location, {_: 'inputFileLocation'}), + offset: 0, + limit: 0 + }, {dcID: location.dc_id}); + }); + + fileEntry.createWriter(function (fileWriter) { + cacheFileWriter = fileWriter; + downloadPromise.then(function (result) { + fileWriteBytes(fileWriter, result.bytes).then(function () { + // dLog('Success', location, fileEntry.toURL()); + deferred.resolve(fileEntry.toURL()); + }, errorHandler); + }, errorHandler); + }, errorHandler); + }, errorHandler); + }; + + requestFS().then(function () { + cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) { + fileEntry.file(function(file) { + if (file.size) { + deferred.resolve(fileEntry.toURL()); + } else { + dLog('Small file empty', file); + doDownload(); + } + }, errorHandler); + }, doDownload); + }, errorHandler); + + return cachedDownloadPromises[fileName] = deferred.promise; + } + + function downloadFile (dcID, location, size, fileEntry) { + dLog('dload file', dcID, location, size); + var fileName = getFileName(location), + cachedPromise = cachedSavePromises[fileName] || cachedDownloadPromises[fileName]; + + if (cachedPromise) { + return cachedPromise; + } + + var deferred = $q.defer(), + errorHandler = function (error) { + console.error(error); + // dLog('fail'); + deferred.reject(error); + if (cacheFileWriter) cacheFileWriter.truncate(); + }, + saveToFileEntry = function (fileEntry) { + fileEntry.createWriter(function (fileWriter) { + cacheFileWriter = fileWriter; + + // var limit = size > 102400 ? 65536 : 4096; + // var limit = size > 30400 ? 524288 : 4096; + var limit = size > 30400 ? 20480 : 4096; + var writeFilePromise = $q.when(), + writeFileDeferred; + for (var offset = 0; offset < size; offset += limit) { + writeFileDeferred = $q.defer(); + (function (isFinal, offset, writeFileDeferred, writeFilePromise) { + return downloadRequest(function () { + // dLog('next big promise'); + return MtpApiManager.invokeApi('upload.getFile', { + location: location, + offset: offset, + limit: limit + }, {dcID: dcID}); + + }, 6).then(function (result) { + + // dLog('waiting for file promise', offset); + writeFilePromise.then(function () { + // dLog('resolved file promise', offset); + + return fileWriteBytes(fileWriter, result.bytes).then(function () { + + // dLog('resolve file promise', offset); + writeFileDeferred.resolve(); + + }, errorHandler).then(function () { + + if (isFinal) { + deferred.resolve(fileEntry.toURL('image/jpeg')); + } else { + // dLog('notify', {done: offset + limit, total: size}); + deferred.notify({done: offset + limit, total: size}); + }; + + }); + + }); + + }); + + })(offset + limit >= size, offset, writeFileDeferred, writeFilePromise); + + writeFilePromise = writeFileDeferred.promise; + + } + }, errorHandler); + + }, + doDownload = function () { + cachedFS.root.getFile(fileName, {create: true}, saveToFileEntry, errorHandler); + }; + + if (fileEntry) { + saveToFileEntry(fileEntry); + } else { + requestFS().then(function () { + cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) { + fileEntry.file(function(file) { + dLog('check size', file.size, size); + if (file.size >= size && false) { + deferred.resolve(fileEntry.toURL()); + } else { + dLog('File bad size', file, size); + doDownload(); + } + }, errorHandler); + }, doDownload); + }, errorHandler); + } + + return cachedDownloadPromises[fileName] = deferred.promise; + } + + function writeFile (file) { + dLog('write file', file); + var fileName = getTempFileName(file); + + var deferred = $q.defer(), + cacheFileWriter, + errorHandler = function (error) { + dLog('fail'); + deferred.reject(error); + if (cacheFileWriter) cacheFileWriter.truncate(); + }; + + requestFS().then(function () { + cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) { + deferred.resolve(fileEntry); + }, function () { + cachedFS.root.getFile(fileName, {create: true}, function(fileEntry) { + fileEntry.createWriter(function (fileWriter) { + cacheFileWriter = fileWriter; + fileWriteBytes(fileWriter, file).then(function () { + deferred.resolve(fileEntry); + }, errorHandler); + }, errorHandler); + }); + }); + }); + }; + + function uploadFile (file) { + var fileSize = file.size, + // partSize = fileSize > 102400 ? 65536 : 4096, + partSize = fileSize > 102400 ? 524288 : 4096, + totalParts = Math.ceil(fileSize / partSize), + doneParts = 0; + + if (totalParts > 1500) { + return $q.reject({type: 'FILE_TOO_BIG'}); + } + + var fileID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)], + deferred = $q.defer(), + errorHandler = function (error) { + dLog('error', error); + deferred.reject(error); + }, + part = 0, + offset, + resultInputFile = { + _: 'inputFile', + id:fileID, + parts: totalParts, + name: file.name, + md5_checksum: '' + }; + + + var fileReadPromise = $q.when(); + + for (offset = 0; offset < fileSize; offset += partSize) { + (function (offset, part) { + fileReadPromise = fileReadPromise.then(function () { + var fileReadDeferred = $q.defer(); + + var reader = new FileReader(); + var blob = file.slice(offset, offset + partSize); + + reader.onloadend = function (e) { + if (e.target.readyState != FileReader.DONE) { + return; + } + var apiCurPromise = apiUploadPromise = apiUploadPromise.then(function () { + return MtpApiManager.invokeApi('upload.saveFilePart', { + file_id: fileID, + file_part: part, + bytes: bytesFromArrayBuffer(e.target.result) + }, {startMaxLength: partSize + 256}); + }, errorHandler); + + apiCurPromise.then(function (result) { + doneParts++; + fileReadDeferred.resolve(); + if (doneParts >= totalParts) { + deferred.resolve(resultInputFile); + } else { + dLog('Progress', doneParts * partSize / fileSize); + deferred.notify({done: doneParts * partSize, total: fileSize}); + } + }, errorHandler); + }; + + reader.readAsArrayBuffer(blob); + + return fileReadDeferred.promise; + }); + })(offset, part++); + } + + return deferred.promise; + } + + + return { + getCachedFile: getCachedFile, + downloadFile: downloadFile, + downloadSmallFile: downloadSmallFile, + saveSmallFile: saveSmallFile, + uploadFile: uploadFile + }; +}) + + + + + + diff --git a/app/js/lib/pq_worker.js b/app/js/lib/pq_worker.js new file mode 100644 index 00000000..3385fd8a --- /dev/null +++ b/app/js/lib/pq_worker.js @@ -0,0 +1,12 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +importScripts('mtproto.js', 'jsbn.js'); + +onmessage = function (e) { + postMessage(pqPrimeFactorization(e.data)); +} \ No newline at end of file diff --git a/app/js/lib/sha1_worker.js b/app/js/lib/sha1_worker.js new file mode 100644 index 00000000..44a35fb5 --- /dev/null +++ b/app/js/lib/sha1_worker.js @@ -0,0 +1,14 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +importScripts('mtproto.js', '../../vendor/cryptoJS/crypto.js'); + +onmessage = function (e) { + var taskID = e.data.taskID; + + postMessage({taskID: taskID, result: sha1Hash(e.data.bytes)}); +} \ No newline at end of file diff --git a/app/js/services.js b/app/js/services.js new file mode 100644 index 00000000..f2569107 --- /dev/null +++ b/app/js/services.js @@ -0,0 +1,1439 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +'use strict'; + +/* Services */ + +angular.module('myApp.services', []) + +.service('AppConfigManager', function ($q) { + var testPrefix = window._testMode ? 't_' : ''; + var cache = {}; + var useLs = !window.chrome || !chrome.storage || !chrome.storage.local; + + function getValue() { + var keys = Array.prototype.slice.call(arguments), + result = [], + single = keys.length == 1, + allFound = true; + + for (var i = 0; i < keys.length; i++) { + keys[i] = testPrefix + keys[i]; + } + + angular.forEach(keys, function (key) { + if (cache[key] !== undefined) { + result.push(cache[key]); + } + else if (useLs) { + var value = localStorage.getItem(key); + value = (value === undefined || value === null) ? false : JSON.parse(value); + result.push(cache[key] = value); + } + else { + allFound = false; + } + }); + + if (allFound) { + return $q.when(single ? result[0] : result); + } + + var deferred = $q.defer(); + + // dLog('get', keys); + chrome.storage.local.get(keys, function (resultObj) { + // dLog('got', resultObj); + result = []; + angular.forEach(keys, function (key) { + var value = resultObj[key]; + // dLog('p1', key, value); + value = value === undefined || value === null ? false : JSON.parse(value); + // dLog('p2', value); + result.push(cache[key] = value); + }); + + // dLog('got parsed', result); + deferred.resolve(single ? result[0] : result); + }); + + return deferred.promise; + }; + + function setValue(obj) { + var keyValues = {}; + angular.forEach(obj, function (value, key) { + keyValues[testPrefix + key] = JSON.stringify(value); + cache[testPrefix + key] = value; + }); + + if (useLs) { + angular.forEach(keyValues, function (value, key) { + localStorage.setItem(key, value); + }); + return $q.when(); + } + + var deferred = $q.defer(); + + chrome.storage.local.set(keyValues, function () { + deferred.resolve(); + }); + + return deferred.promise; + }; + + function removeValue () { + var keys = Array.prototype.slice.call(arguments); + + for (var i = 0; i < keys.length; i++) { + keys[i] = testPrefix + keys[i]; + } + + angular.forEach(keys, function(key){ + delete cache[key]; + }); + + if (useLs) { + angular.forEach(keys, function(key){ + localStorage.removeItem(key); + }); + + return $q.when(); + } + + var deferred = $q.defer(); + + chrome.storage.local.remove(keys, function () { + deferred.resolve(); + }); + + return deferred.promise; + }; + + return { + get: getValue, + set: setValue, + remove: removeValue + }; +}) + +.service('AppUsersManager', function ($rootScope, $modal, MtpApiFileManager, MtpApiManager, RichTextProcessor) { + var users = {}; + + function saveApiUsers (apiUsers) { + angular.forEach(apiUsers, saveApiUser); + }; + + function saveApiUser (apiUser) { + if (!angular.isObject(apiUser)) { + return; + } + + if (apiUser.first_name) { + apiUser.rFirstName = RichTextProcessor.wrapRichText(apiUser.first_name, {noLinks: true, noLinebreaks: true}); + apiUser.rFullName = RichTextProcessor.wrapRichText(apiUser.first_name + ' ' + (apiUser.last_name || ''), {noLinks: true, noLinebreaks: true}); + } else { + apiUser.rFirstName = RichTextProcessor.wrapRichText(apiUser.last_name, {noLinks: true, noLinebreaks: true}) || 'DELETED'; + apiUser.rFullName = RichTextProcessor.wrapRichText(apiUser.last_name, {noLinks: true, noLinebreaks: true}) || 'DELETED'; + } + + if (users[apiUser.id] === undefined) { + users[apiUser.id] = apiUser; + } else { + angular.extend(users[apiUser.id], apiUser); + } + }; + + function getUser (id) { + if (angular.isObject(id)) { + return id; + } + return users[id] || {id: id, deleted: true}; + } + + function getUserPhoto(id, placeholder) { + var user = getUser(id); + + return { + placeholder: 'img/placeholders/' + placeholder + 'Avatar'+((Math.abs(id) % 8) + 1)+'@2x.png', + location: user && user.photo && user.photo.photo_small + }; + } + + function getUserString (id) { + var user = getUser(id); + return 'u' + id + (user.access_hash ? '_' + user.access_hash : ''); + } + + function getUserInput (id) { + var user = getUser(id); + if (user._ == 'userSelf') { + return {_: 'inputUserSelf'}; + } + return { + _: 'inputUserForeign', + user_id: id, + access_hash: user.access_hash || 0 + }; + } + + function wrapForFull (id) { + var user = getUser(id); + + user.thumb = { + placeholder: 'img/placeholders/UserAvatar'+((Math.abs(id) % 8) + 1)+'@2x.png', + location: user && user.photo && user.photo.photo_small, + width: 120, + height: 120, + size: 0 + }; + user.peerString = getUserString(id); + + return user; + } + + function openUser (userID, accessHash) { + var scope = $rootScope.$new(); + scope.userID = userID; + + var modalInstance = $modal.open({ + templateUrl: 'partials/user_modal.html', + controller: 'UserModalController', + scope: scope, + windowClass: 'user_modal_window', + resolve: { + userFull: MtpApiManager.invokeApi('users.getFullUser', { + id: getUserInput(userID) + }).then(function (result) { + saveApiUser(result.user); + return result; + }) + } + }); + } + + $rootScope.openUser = openUser; + + $rootScope.$on('apiUpdate', function (e, update) { + // dLog('on apiUpdate', update); + switch (update._) { + case 'updateUserStatus': + var userID = update.user_id; + if (users[userID]) { + users[userID].status = update.status; + $rootScope.$broadcast('user_update', userID); + } + break; + + case 'updateUserPhoto': + var userID = update.user_id; + if (users[userID]) { + users[userID].photo = update.photo; + $rootScope.$broadcast('user_update', userID); + } + break; + } + }); + + + return { + saveApiUsers: saveApiUsers, + saveApiUser: saveApiUser, + getUser: getUser, + getUserPhoto: getUserPhoto, + getUserString: getUserString, + wrapForFull: wrapForFull, + openUser: openUser + } +}) + +.service('AppChatsManager', function ($rootScope, $modal, MtpApiFileManager, MtpApiManager, AppUsersManager, RichTextProcessor) { + var chats = {}; + + function saveApiChats (apiChats) { + angular.forEach(apiChats, saveApiChat); + }; + + function saveApiChat (apiChat) { + if (!angular.isObject(apiChat)) { + return; + } + apiChat.rTitle = RichTextProcessor.wrapRichText(apiChat.title, {noLinks: true, noLinebreaks: true}) || 'DELETED'; + if (chats[apiChat.id] === undefined) { + chats[apiChat.id] = apiChat; + } else { + angular.extend(chats[apiChat.id], apiChat); + } + }; + + function getChat (id) { + return chats[id] || {id: id, deleted: true}; + } + + function getChatPhoto(id, placeholder) { + var chat = getChat(id); + + return { + placeholder: 'img/placeholders/' + placeholder + 'Avatar'+((Math.abs(id) % 4) + 1)+'@2x.png', + location: chat && chat.photo && chat.photo.photo_small + }; + } + + function getChatString (id) { + var chat = getChat(id); + return 'g' + id; + } + + function wrapForFull (id, fullChat) { + var chatFull = angular.copy(fullChat), + chat = getChat(id); + + if (chatFull.participants._ == 'chatParticipants') { + angular.forEach(chatFull.participants.participants, function(participant){ + participant.user = AppUsersManager.getUser(participant.user_id); + participant.userPhoto = AppUsersManager.getUserPhoto(participant.user_id, 'User'); + participant.inviter = AppUsersManager.getUser(participant.inviter_id); + }); + } + + chatFull.thumb = { + placeholder: 'img/placeholders/GroupAvatar'+((Math.abs(id) % 4) + 1)+'@2x.png', + location: chat && chat.photo && chat.photo.photo_small, + width: 120, + height: 120, + size: 0 + }; + chatFull.peerString = getChatString(id); + chatFull.chat = chat; + + return chatFull; + } + + function openChat (chatID, accessHash) { + var scope = $rootScope.$new(); + scope.chatID = chatID; + + var modalInstance = $modal.open({ + templateUrl: 'partials/chat_modal.html', + controller: 'ChatModalController', + windowClass: 'chat_modal_window', + scope: scope, + resolve: { + fullChat: function () { + return MtpApiManager.invokeApi('messages.getFullChat', { + chat_id: chatID + }).then(function (result) { + saveApiChats(result.chats); + AppUsersManager.saveApiUsers(result.users); + return result.full_chat; + }) + } + } + }); + } + + $rootScope.openChat = openChat; + + + return { + saveApiChats: saveApiChats, + saveApiChat: saveApiChat, + getChat: getChat, + getChatPhoto: getChatPhoto, + getChatString: getChatString, + wrapForFull: wrapForFull, + openChat: openChat + } +}) + +.service('AppPeersManager', function (AppUsersManager, AppChatsManager) { + return { + getInputPeer: function (peerString) { + var isUser = peerString.charAt(0) == 'u', + peerParams = peerString.substr(1).split('_'); + + return isUser + ? {_: 'inputPeerForeign', user_id: peerParams[0], access_hash: peerParams[1]} + : {_: 'inputPeerChat', chat_id: peerParams[0]}; + }, + getInputPeerByID: function (peerID) { + if (peerID > 0) { + return { + _: 'inputPeerForeign', + user_id: peerID, + access_hash: AppUsersManager.getUser(peerID).access_hash || 0 + }; + } else if (peerID < 0) { + return { + _: 'inputPeerChat', + chat_id: -peerID + }; + } + }, + getOutputPeer: function (peerID) { + return peerID > 0 + ? {_: 'peerUser', user_id: peerID} + : {_: 'peerChat', chat_id: -peerID}; + }, + getPeerID: function (peerString) { + if (angular.isObject(peerString)) { + return peerString.user_id + ? peerString.user_id + : -peerString.chat_id; + } + var isUser = peerString.charAt(0) == 'u', + peerParams = peerString.substr(1).split('_'); + + return isUser ? peerParams[0] : -peerParams[0] || 0; + }, + getPeer: function (peerID) { + return peerID > 0 + ? AppUsersManager.getUser(peerID) + : AppChatsManager.getChat(-peerID); + }, + getPeerPhoto: function (peerID, userPlaceholder, chatPlaceholder) { + return peerID > 0 + ? AppUsersManager.getUserPhoto(peerID, userPlaceholder) + : AppChatsManager.getChatPhoto(-peerID, chatPlaceholder) + } + } +}) + +.service('AppMessagesManager', function ($q, $rootScope, $filter, $sanitize, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, MtpApiManager, RichTextProcessor) { + + var messagesStorage = {}; + var messagesForHistory = {}; + var historiesStorage = {}; + var dialogsStorage = {count: null, dialogs: []}; + + function getDialogs (offset, limit) { + if (dialogsStorage.count !== null && dialogsStorage.dialogs.length >= offset + limit) { + return $q.when({ + count: dialogsStorage.count, + dialogs: dialogsStorage.dialogs.slice(offset, offset + limit) + }); + } + + var deferred = $q.defer(); + + MtpApiManager.invokeApi('messages.getDialogs', { + offset: offset, + limit: limit, + max_id: 0 + }).then(function (dialogsResult) { + AppUsersManager.saveApiUsers(dialogsResult.users); + AppChatsManager.saveApiChats(dialogsResult.chats); + saveMessages(dialogsResult.messages); + + dialogsStorage.count = dialogsResult._ == 'messages.dialogsSlice' + ? dialogsResult.count + : dialogsResult.dialogs.length; + + angular.forEach(dialogsResult.dialogs, function (dialog) { + dialogsStorage.dialogs.push({ + peerID: AppPeersManager.getPeerID(dialog.peer), + top_message: dialog.top_message, + unread_count: dialog.unread_count + }); + }); + + deferred.resolve({ + count: dialogsStorage.count, + dialogs: dialogsStorage.dialogs.slice(offset, offset + limit) + }); + }, function (error) { + deferred.reject(error); + }); + + return deferred.promise; + } + + function getHistory (inputPeer, maxID, limit) { + + var peerID = AppPeersManager.getPeerID(inputPeer), + historyStorage = historiesStorage[peerID], + offset = 0; + + if (historyStorage === undefined) { + historyStorage = historiesStorage[peerID] = {count: null, history: []}; + } + + + if (maxID > 0) { + for (offset = 0; offset < historyStorage.history.length; offset++) { + if (maxID > historyStorage.history[offset]) { + break; + } + } + } + // dLog('history storage', angular.copy(historyStorage.history), maxID, offset); + + if (historyStorage.count !== null && historyStorage.history.length >= offset + limit) { + return $q.when({ + count: historyStorage.count, + history: historyStorage.history.slice(offset, offset + limit) + }); + } + + var deferred = $q.defer(); + + MtpApiManager.invokeApi('messages.getHistory', { + peer: inputPeer, + offset: offset, + limit: limit, + max_id: 0 + }).then(function (historyResult) { + AppUsersManager.saveApiUsers(historyResult.users); + AppChatsManager.saveApiChats(historyResult.chats); + saveMessages(historyResult.messages); + + historyStorage.count = historyResult._ == 'messages.messagesSlice' + ? historyResult.count + : historyResult.messages.length; + + offset = 0; + if (maxID > 0) { + for (offset = 0; offset < historyStorage.history.length; offset++) { + if (maxID > historyStorage.history[offset]) { + break; + } + } + } + + // dLog('history storage after', angular.copy(historyStorage.history), historyResult.messages, maxID, offset); + + historyStorage.history.splice(offset, historyStorage.history.length - offset); + angular.forEach(historyResult.messages, function (message) { + historyStorage.history.push(message.id); + }); + + deferred.resolve({ + count: historyStorage.count, + history: historyStorage.history.slice(offset, offset + limit) + }); + }, function (error) { + deferred.reject(error); + }); + + return deferred.promise; + } + + function processAffectedHistory (inputPeer, affectedHistory) { + if (!ApiUpdatesManager.saveSeq(affectedHistory.seq)) { + return false; + } + if (!affectedHistory.offset) { + return $q.when(); + } + + return MtpApiManager.invokeApi('messages.readHistory', { + peer: inputPeer, + offset: affectedHistory.offset, + max_id: 0 + }).then(function (affectedHistory) { + return processAffectedHistory(inputPeer, affectedHistory); + }); + } + + function readHistory (inputPeer) { + // dLog('start read'); + var peerID = AppPeersManager.getPeerID(inputPeer), + historyStorage = historiesStorage[peerID], + foundDialog = getDialogByPeerID(peerID); + + if (!historyStorage || + !historyStorage.history.length || + foundDialog[0] && !foundDialog[0].unread_count) { + // dLog('bad1'); + return false; + } + + var wasUnread = false; + // dLog(historyStorage); + for (i = 0; i < historyStorage.history.length; i++) { + messageID = historyStorage.history[i]; + message = messagesStorage[messageID]; + // dLog('ms', message); + if (message && !message.out) { + if (message.unread) { + // dLog('unread'); + wasUnread = true; + } else if (!wasUnread) { + // dLog('bad2'); + return false; + } + } + } + + var promise = MtpApiManager.invokeApi('messages.readHistory', { + peer: inputPeer, + offset: 0, + max_id: 0 + }).then(function (affectedHistory) { + return processAffectedHistory(inputPeer, affectedHistory); + }).then(function () { + if (foundDialog[0]) { + foundDialog[0].unread_count = 0; + $rootScope.$broadcast('dialog_unread', {peerID: peerID, count: 0}); + } + }); + + + var messageID, message, i, peerID, foundDialog, dialog; + for (i = 0; i < historyStorage.history.length; i++) { + messageID = historyStorage.history[i]; + message = messagesStorage[messageID]; + if (message && !message.out) { + message.unread = false; + if (messagesForHistory[messageID]) { + messagesForHistory[messageID].unread = false; + } + } + } + + return promise; + } + + function saveMessages (apiMessages) { + angular.forEach(apiMessages, function (apiMessage) { + messagesStorage[apiMessage.id] = apiMessage; + + if (apiMessage.media && apiMessage.media._ == 'messageMediaPhoto') { + AppPhotosManager.savePhoto(apiMessage.media.photo); + } + if (apiMessage.media && apiMessage.media._ == 'messageMediaVideo') { + AppVideoManager.saveVideo(apiMessage.media.video); + } + if (apiMessage.media && apiMessage.media._ == 'messageMediaDocument') { + AppDocsManager.saveDoc(apiMessage.media.document); + } + if (apiMessage.action && apiMessage.action._ == 'messageActionChatEditPhoto') { + AppPhotosManager.savePhoto(apiMessage.action.photo); + } + }); + } + + function getMessagePeer (message) { + var toID = message.to_id && AppPeersManager.getPeerID(message.to_id) || 0; + + if (toID < 0) { + return toID; + } else if (message.out) { + return toID + } + return message.from_id; + } + + function wrapForDialog (msgID, unreadCount) { + var message = angular.copy(messagesStorage[msgID]) || {id: msgID}; + + message.fromUser = AppUsersManager.getUser(message.from_id); + + if (message.chatID = message.to_id.chat_id) { + message.peerID = -message.chatID; + message.peerData = AppChatsManager.getChat(message.chatID); + message.peerString = AppChatsManager.getChatString(message.chatID); + } else { + message.peerID = message.out ? message.to_id.user_id : message.from_id; + message.peerData = AppUsersManager.getUser(message.peerID); + message.peerString = AppUsersManager.getUserString(message.peerID); + } + + message.peerPhoto = AppPeersManager.getPeerPhoto(message.peerID, 'User', 'Group'); + message.unreadCount = unreadCount; + + if (message._ == 'messageService' && message.action.user_id) { + message.action.user = AppUsersManager.getUser(message.action.user_id); + } + + if (message.message && message.message.length) { + message.richMessage = RichTextProcessor.wrapRichText(message.message.substr(0, 64), {noLinks: true, noLinebreaks: true}); + } + + + return message; + } + + function wrapForHistory (msgID) { + if (messagesForHistory[msgID] !== undefined) { + return messagesForHistory[msgID]; + } + + var message = angular.copy(messagesStorage[msgID]) || {id: msgID}; + + message.fromUser = AppUsersManager.getUser(message.from_id); + message.fromPhoto = AppUsersManager.getUserPhoto(message.from_id, 'User'); + + if (message.media) { + switch (message.media._) { + case 'messageMediaPhoto': + message.media.photo = AppPhotosManager.wrapForHistory(message.media.photo.id) + break; + + case 'messageMediaVideo': + message.media.video = AppVideoManager.wrapForHistory(message.media.video.id); + break; + } + + if (message.media.user_id) { + message.media.user = AppUsersManager.getUser(message.media.user_id); + message.media.userPhoto = AppUsersManager.getUserPhoto(message.media.user_id, 'User'); + } + } + else if (message.action) { + if (message.action._ == 'messageActionChatEditPhoto') { + message.action.photo = AppPhotosManager.wrapForHistory(message.action.photo.id); + } + + if (message.action.user_id) { + message.action.user = AppUsersManager.getUser(message.action.user_id); + message.action.userPhoto = AppUsersManager.getUserPhoto(message.action.user_id, 'User'); + } + } + + if (message.message && message.message.length) { + message.richMessage = RichTextProcessor.wrapRichText(message.message); + } + + return messagesForHistory[msgID] = message; + } + + function getDialogByPeerID (peerID) { + for (var i = 0; i < dialogsStorage.dialogs.length; i++) { + if (dialogsStorage.dialogs[i].peerID == peerID) { + return [dialogsStorage.dialogs[i], i]; + } + } + + return []; + } + + + $rootScope.$on('apiUpdate', function (e, update) { + dLog('on apiUpdate', update); + switch (update._) { + case 'updateNewMessage': + var message = update.message, + peerID = getMessagePeer(message), + historyStorage = historiesStorage[peerID]; + + if (historyStorage !== undefined) { + var topMsgID = historiesStorage[peerID].history[0]; + if (message.id <= topMsgID) { + return false; + } + } else { + historyStorage = historiesStorage[peerID] = {count: null, history: []}; + } + + saveMessages([message]); + + if (historyStorage.count !== null) { + historyStorage.count++; + } + historyStorage.history.unshift(message.id); + $rootScope.$broadcast('history_append', {peerID: peerID, messageID: message.id}); + + var foundDialog = getDialogByPeerID(peerID), + dialog; + + if (foundDialog.length) { + dialog = foundDialog[0]; + dialogsStorage.dialogs.splice(foundDialog[1], 1); + } else { + dialog = {peerID: peerID, unread_count: 0, top_message: false} + } + if (!message.out && message.unread) { + dialog.unread_count++; + } + dialog.top_message = message.id; + dialogsStorage.dialogs.unshift(dialog); + $rootScope.$broadcast('dialogs_update', dialog); + break; + + case 'updateReadMessages': + var dialogsUpdated = {}, + messageID, message, i, peerID, foundDialog, dialog; + for (i = 0; i < update.messages.length; i++) { + messageID = update.messages[i]; + message = messagesStorage[messageID]; + // dLog('read', messageID, message); + if (message) { + message.unread = false; + if (messagesForHistory[messageID]) { + messagesForHistory[messageID].unread = false; + } + peerID = getMessagePeer(message); + if (!message.out) { + foundDialog = getDialogByPeerID(peerID); + if (foundDialog) { + dialogsUpdated[peerID] = --foundDialog[0].unread_count; + } + } + } + } + + angular.forEach(dialogsUpdated, function(count, peerID) { + $rootScope.$broadcast('dialog_unread', {peerID: peerID, count: count}); + }); + break; + } + }); + + return { + getDialogs: getDialogs, + getHistory: getHistory, + readHistory: readHistory, + saveMessages: saveMessages, + getMessagePeer: getMessagePeer, + wrapForDialog: wrapForDialog, + wrapForHistory: wrapForHistory + } +}) + +.service('AppPhotosManager', function ($modal, $window, $rootScope, MtpApiFileManager, AppUsersManager) { + var photos = {}; + + function savePhoto (apiPhoto) { + photos[apiPhoto.id] = apiPhoto; + angular.forEach(apiPhoto.sizes, function (photoSize) { + if (photoSize._ == 'photoCachedSize') { + MtpApiFileManager.saveSmallFile(photoSize.location, photoSize.bytes); + + // Memory + photoSize.size = photoSize.bytes.length; + delete photoSize.bytes; + photoSize._ = 'photoSize'; + } + }); + }; + + function choosePhotoSize (photo, width, height) { + var bestPhotoSize = {_: 'photoSizeEmpty'}, + bestDiff = 0xFFFFFF; + + angular.forEach(photo.sizes, function (photoSize) { + var diff = Math.abs(photoSize.w * photoSize.h - width * height); + if (diff < bestDiff) { + bestPhotoSize = photoSize; + bestDiff = diff; + } + }); + + return bestPhotoSize; + } + + function wrapForHistory (photoID) { + var photo = angular.copy(photos[photoID]) || {_: 'photoEmpty'}, + width = 100, + height = 100, + thumbPhotoSize = choosePhotoSize(photo, width, height), + thumb = { + placeholder: 'img/placeholders/PhotoThumbConversation.jpg', + width: width, + height: height + }; + + // dLog('chosen photo size', photoID, thumbPhotoSize); + if (thumbPhotoSize && thumbPhotoSize._ != 'photoSizeEmpty') { + if (thumbPhotoSize.w > thumbPhotoSize.h) { + thumb.height = parseInt(thumbPhotoSize.h * width / thumbPhotoSize.w); + } else { + thumb.width = parseInt(thumbPhotoSize.w * height / thumbPhotoSize.h); + } + + thumb.location = thumbPhotoSize.location; + thumb.size = thumbPhotoSize.size; + } + + photo.thumb = thumb; + + return photo; + } + + function wrapForFull (photoID) { + var photo = wrapForHistory(photoID), + fullWidth = 542, + fullHeight = $($window).height() - 150, + fullPhotoSize = choosePhotoSize(photo, fullWidth, fullHeight), + full = { + placeholder: 'img/placeholders/PhotoThumbModal.jpg', + width: fullWidth, + height: fullHeight + }; + + if (fullPhotoSize && fullPhotoSize._ != 'photoSizeEmpty') { + if (fullPhotoSize.w > fullPhotoSize.h) { + full.height = parseInt(fullPhotoSize.h * fullWidth / fullPhotoSize.w); + } else { + full.width = parseInt(fullPhotoSize.w * fullHeight / fullPhotoSize.h); + if (full.width > fullWidth) { + full.height = parseInt(full.height * fullWidth / full.width); + full.width = fullWidth; + } + } + + full.location = fullPhotoSize.location; + full.size = fullPhotoSize.size; + } + + photo.full = full; + photo.fromUser = AppUsersManager.getUser(photo.user_id); + + return photo; + } + + function openPhoto (photoID, accessHash) { + var scope = $rootScope.$new(true); + scope.photoID = photoID; + + var modalInstance = $modal.open({ + templateUrl: 'partials/photo_modal.html', + controller: 'PhotoModalController', + scope: scope, + backdrop: 'static' + }); + } + + $rootScope.openPhoto = openPhoto; + + + return { + savePhoto: savePhoto, + wrapForHistory: wrapForHistory, + wrapForFull: wrapForFull, + openPhoto: openPhoto + } +}) + + +.service('AppVideoManager', function ($rootScope, $modal, $window, MtpApiFileManager, AppUsersManager) { + var videos = {}; + + function saveVideo (apiVideo) { + videos[apiVideo.id] = apiVideo; + + if (apiVideo.thumb && apiVideo.thumb._ == 'photoCachedSize') { + MtpApiFileManager.saveSmallFile(apiVideo.thumb.location, apiVideo.thumb.bytes); + + // Memory + apiVideo.thumb.size = apiVideo.thumb.bytes.length; + delete apiVideo.thumb.bytes; + apiVideo.thumb._ = 'photoSize'; + } + }; + + function wrapForHistory (videoID) { + var video = angular.copy(videos[videoID]), + width = 100, + height = 100, + thumbPhotoSize = video.thumb, + thumb = { + placeholder: 'img/placeholders/VideoThumbConversation.jpg', + width: width, + height: height + }; + + if (thumbPhotoSize && thumbPhotoSize._ != 'photoSizeEmpty') { + if (thumbPhotoSize.w > thumbPhotoSize.h) { + thumb.height = parseInt(thumbPhotoSize.h * width / thumbPhotoSize.w); + } else { + thumb.width = parseInt(thumbPhotoSize.w * height / thumbPhotoSize.h); + } + + thumb.location = thumbPhotoSize.location; + thumb.size = thumbPhotoSize.size; + } + + video.thumb = thumb; + + return video; + } + + function wrapForFull (videoID) { + var video = wrapForHistory(videoID), + fullWidth = 542, + fullHeight = $($window).height() - 150, + fullPhotoSize = video, + full = { + placeholder: 'img/placeholders/VideoThumbModal.jpg', + width: fullWidth, + height: fullHeight, + }; + + if (video.w > video.h) { + full.height = parseInt(video.h * fullWidth / video.w); + } else { + full.width = parseInt(video.w * fullHeight / video.h); + if (full.width > fullWidth) { + full.height = parseInt(full.height * fullWidth / full.width); + full.width = fullWidth; + } + } + + video.full = full; + video.fromUser = AppUsersManager.getUser(video.user_id); + + return video; + } + + function openVideo (videoID, accessHash) { + var scope = $rootScope.$new(true); + scope.videoID = videoID; + scope.progress = {enabled: false}; + scope.player = {}; + scope.close = function () { + modalInstance.close(); + } + + var modalInstance = $modal.open({ + templateUrl: 'partials/video_modal.html', + controller: 'VideoModalController', + scope: scope + }); + } + + $rootScope.openVideo = openVideo; + + return { + saveVideo: saveVideo, + wrapForHistory: wrapForHistory, + wrapForFull: wrapForFull, + openVideo: openVideo + } +}) + +.service('AppDocsManager', function ($rootScope, $modal, $window, $timeout, MtpApiFileManager, AppUsersManager) { + var docs = {}; + + function saveDoc (apiDoc) { + docs[apiDoc.id] = apiDoc; + + if (apiDoc.thumb && apiDoc.thumb._ == 'photoCachedSize') { + MtpApiFileManager.saveSmallFile(apiDoc.thumb.location, apiDoc.thumb.bytes); + + // Memory + apiDoc.thumb.size = apiDoc.thumb.bytes.length; + delete apiDoc.thumb.bytes; + apiDoc.thumb._ = 'photoSize'; + } + }; + + function wrapForHistory (docID) { + var doc = angular.copy(docs[docID]), + width = 100, + height = 100, + thumbPhotoSize = doc.thumb, + thumb = { + placeholder: 'img/placeholders/DocThumbConversation.jpg', + width: width, + height: height + }; + + if (thumbPhotoSize && thumbPhotoSize._ != 'photoSizeEmpty') { + if (thumbPhotoSize.w > thumbPhotoSize.h) { + thumb.height = parseInt(thumbPhotoSize.h * width / thumbPhotoSize.w); + } else { + thumb.width = parseInt(thumbPhotoSize.w * height / thumbPhotoSize.h); + } + + thumb.location = thumbPhotoSize.location; + thumb.size = thumbPhotoSize.size; + } + + doc.thumb = thumb; + + return doc; + } + + function openDoc (docID, accessHash) { + var doc = docs[docID], + inputFileLocation = { + _: 'inputDocumentFileLocation', + id: docID, + access_hash: accessHash || doc.access_hash + }, + scope = {}; + + scope.progress = {enabled: true, percent: 1}; + + + if (window.chrome && chrome.fileSystem && chrome.fileSystem.chooseEntry) { + var ext = (doc.file_name.split('.', 2) || [])[1] || '', + mime = doc.mime_type; + chrome.fileSystem.chooseEntry({ + type: 'saveFile', + suggestedName: doc.file_name, + accepts: [{ + mimeTypes: [mime], + extensions: [ext] + }] + }, function (writableFileEntry) { + MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size, writableFileEntry).then(function (url) { + dLog('file save done'); + }); + + }); + } else { + MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size).then(function (url) { + scope.progress.enabled = false; + + var a = $('Download').attr('href', url).attr('target', '_blank').attr('download', doc.file_name).appendTo('body'); + a[0].dataset.downloadurl = ['png', doc.file_name, url].join(':'); + a[0].click(); + $timeout(function () { + a.remove(); + }, 100); + }, function (e) { + dLog('document download failed', e); + }, function (progress) { + scope.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total)); + }); + } + } + + $rootScope.openDoc = openDoc; + + return { + saveDoc: saveDoc, + wrapForHistory: wrapForHistory, + openDoc: openDoc + } +}) + +.service('ExternalResourcesManager', function ($q, $http) { + var urlPromises = {}; + + function downloadImage (url) { + if (urlPromises[url] !== undefined) { + return urlPromises[url]; + } + + var deferred = $q.defer(); + + $http.get(url, {responseType: 'blob', transformRequest: null}) + .then( + function (response) { + deferred.resolve(window.webkitURL.createObjectURL(response.data)); + }, function (error) { + deferred.reject(error); + } + ); + + return urlPromises[url] = deferred.promise; + } + + return { + downloadImage: downloadImage + } +}) + + +.service('ApiUpdatesManager', function ($rootScope, MtpNetworkerFactory, AppUsersManager, AppChatsManager, AppPeersManager, MtpApiManager) { + + var curState = {invalid: true}; + + function processUpdateMessage (updateMessage) { + if (curState.invalid) { + return false; + } + + if (updateMessage.seq) { + if (!saveSeq(updateMessage.seq, updateMessage.seq_start)) { + return false; + } + if (updateMessage.date) { + curState.date = updateMessage.date; + } + } + + + switch (updateMessage._) { + case 'updatesTooLong': + getDifference(); + break; + + case 'updateShort': + saveUpdate(updateMessage.update); + break; + + case 'updatesCombined': + case 'updates': + AppUsersManager.saveApiUsers(updateMessage.users); + AppChatsManager.saveApiChats(updateMessage.chats); + + angular.forEach(updateMessage.updates, function (update) { + saveUpdate(update); + }); + break; + + case 'updateShortMessage': + var fromUser = AppUsersManager.getUser(updateMessage.from_id); + if (!fromUser || fromUser.deleted) { + getDifference(); + break; + } + saveUpdate({ + _: 'updateNewMessage', + message: { + _: 'message', + id: updateMessage.id, + from_id: updateMessage.from_id, + to_id: AppPeersManager.getOutputPeer(MtpApiManager.getUserID()), + out: false, + unread: true, + date: updateMessage.date, + message: updateMessage.message, + media: {_: 'messageMediaEmpty'} + }, + pts: updateMessage.pts + }); + break; + + case 'updateShortChatMessage': + var fromUser = AppUsersManager.getUser(updateMessage.from_id), + chat = AppChatsManager.getChat(updateMessage.chat_id); + + if (!fromUser || fromUser.deleted || !chat || chat.deleted) { + getDifference(); + break; + } + saveUpdate({ + _: 'updateNewMessage', + message: { + _: 'message', + id: updateMessage.id, + from_id: updateMessage.from_id, + to_id: AppPeersManager.getOutputPeer(-updateMessage.chat_id), + out: false, + unread: true, + date: updateMessage.date, + message: updateMessage.message, + media: {_: 'messageMediaEmpty'} + }, + pts: updateMessage.pts + }); + break; + } + } + + function getDifference (force) { + if (curState.invalid && !force) { + return false; + } + + curState.invalid = true; + MtpApiManager.invokeApi('updates.getDifference', {pts: curState.pts, date: curState.date, qts: 0}).then(function (differenceResult) { + if (differenceResult._ == 'updates.differenceEmpty') { + curState.date = differenceResult.date; + curState.seq = differenceResult.seq; + delete curState.invalid; + return false; + } + + AppUsersManager.saveApiUsers(differenceResult.users); + AppChatsManager.saveApiChats(differenceResult.chats); + + angular.forEach(differenceResult.new_messages, function (apiMessage) { + saveUpdate({ + _: 'updateNewMessage', + message: apiMessage, + pts: curState.pts + }, true); + }); + + angular.forEach(differenceResult.other_updates, function(update){ + saveUpdate(update, true); + }); + + var nextState = differenceResult.intermediate_state || differenceResult.state; + curState.seq = nextState.seq; + curState.pts = nextState.pts; + curState.date = nextState.date; + + if (differenceResult._ == 'updates.differenceSlice') { + getDifference(true); + } else { + delete curState.invalid; + } + }); + } + + function saveUpdate (update, force) { + if (curState.invalid && !force) { + return false; + } + if (update.pts) { + curState.pts = update.pts; + } + + $rootScope.$broadcast('apiUpdate', update); + } + + function saveSeq (seq, seqStart) { + // dLog('saving seq', curState.invalid, seq, seqStart, curState.seq); + + if (curState.invalid) { + return false; + } + + seqStart = seqStart || seq; + + if (seqStart != curState.seq + 1) { + // dLog('seq hole', seqStart, curState.seq); + if (seqStart != curState.seq) { + getDifference(); + } + return false; + } + + curState.seq = seq; + + return true; + } + + function attach () { + MtpNetworkerFactory.setUpdatesProcessor(processUpdateMessage); + MtpApiManager.invokeApi('updates.getState').then(function (stateResult) { + curState.seq = stateResult.seq; + curState.pts = stateResult.pts; + curState.date = stateResult.date; + delete curState.invalid; + }) + } + + + return { + saveUpdate: saveUpdate, + saveSeq: saveSeq, + attach: attach + } +}) + +.service('RichTextProcessor', function ($sce, $sanitize) { + + var emojiUtf = [], + emojiMap = {}, + emojiData = Config.Emoji, + emojiCode; + + for (emojiCode in emojiData) { + emojiUtf.push(emojiData[emojiCode][0]); + emojiMap[emojiData[emojiCode][0]] = emojiCode; + } + + var regExp = new RegExp('((?:(ftp|https?)://|(?:mailto:)?([A-Za-z0-9._%+-]+@))(\\S*\\.\\S*[^\\s.;,(){}<>"\']))|(\\n)|(' + emojiUtf.join('|') + ')', 'i'); + + // dLog(regExp); + + + return { + wrapRichText: wrapRichText + }; + + function encodeEntities(value) { + return value. + replace(/&/g, '&'). + replace(/([^\#-~| |!])/g, function (value) { // non-alphanumeric + return '&#' + value.charCodeAt(0) + ';'; + }). + replace(//g, '>'); + }; + + + function wrapRichText(text, options) { + if (!text || !text.length) { + return ''; + } + + options = options || {}; + + text = text.replace(/\ufe0f/g, '', text); + + var match, + raw = text, + html = [], + url, + emojiTitle, + emojiFound = false; + + + while ((match = raw.match(regExp))) { + // dLog(2, match); + html.push(encodeEntities(raw.substr(0, match.index))); + + if (match[1]) { // URL + if (!options.noLinks) { + if (match[3]) { + html.push( + '', + encodeEntities(match[3] + match[4]), + '' + ); + } else { + html.push( + '', + encodeEntities((match[2] != 'http' ? match[2] + '://' : '') + match[4]), + '' + ); + } + } else { + html.push(encodeEntities(match[0])); + } + } + else if (match[5]) { // New line + if (!options.noLinebreaks) { + html.push('
'); + } else { + html.push(' '); + } + } + else if (match[6]) { + + if (emojiCode = emojiMap[match[6]]) { + emojiFound = true; + emojiTitle = encodeEntities(emojiData[emojiCode][1][0]); + html.push( + ':', + emojiTitle, + ':' + ); + } else { + html.push(encodeEntities(match[6])); + } + } + raw = raw.substr(match.index + match[0].length); + } + + html.push(encodeEntities(raw)); + + text = $sanitize(html.join('')); + + // dLog(3, text, html); + + if (emojiFound) { + text = text.replace(//g, + ''); + } + + // dLog(4, text, html); + + return $sce.trustAs('html', text); + } + +}) diff --git a/app/js/util.js b/app/js/util.js new file mode 100644 index 00000000..e65c18d5 --- /dev/null +++ b/app/js/util.js @@ -0,0 +1,55 @@ +/*! + * Webogram v0.1 - messaging web application for MTProto + * https://github.com/zhukov/webogram + * Copyright (C) 2014 Igor Zhukov + * https://github.com/zhukov/webogram/blob/master/LICENSE + */ + +function checkClick (e, noprevent) { + if (e.which == 1 && (e.ctrlKey || e.metaKey) || e.which == 2) { + return true; + } + + if (!noprevent) { + e.preventDefault(); + } + + return false; +} + +function checkDragEvent(e) { + if (!e || e.target && (e.target.tagName == 'IMG' || e.target.tagName == 'A')) return false; + if (e.dataTransfer && e.dataTransfer.types) { + for (var i = 0; i < e.dataTransfer.types.length; i++) { + if (e.dataTransfer.types[i] == 'Files') { + return true; + } + } + } else { + return true; + } + + return false; +} + +function cancelEvent (event) { + event = event || window.event; + + event.stopPropagation && event.stopPropagation(); + event.preventDefault && event.preventDefault(); + + return false; +} + +function onCtrlEnter (textarea, cb) { + $(textarea).on('keydown', function (e) { + if (e.keyCode == 13 && (e.ctrlKey || e.metaKey)) { + cb(); + return cancelEvent(e); + } + }); +} + +function onContentLoaded (cb) { + setTimeout(cb, 0); +}; \ No newline at end of file diff --git a/app/manifest.json b/app/manifest.json new file mode 100644 index 00000000..7a13a6bb --- /dev/null +++ b/app/manifest.json @@ -0,0 +1,18 @@ +{ + "name": "Telegram UNOFFICIAL", + "version": "0.0.9", + "short_name": "Webogram", + "manifest_version": 2, + "app": { + "background": { + "scripts": ["vendor/angular/angular.js", "js/background.js"] + } + }, + "permissions": [ + "webview", + {"fileSystem": ["write"]}, + "storage" + ], + "icons": { "16": "img/icons/icon16.png", + "128": "img/icons/icon128.png" } +} \ No newline at end of file diff --git a/app/partials/chat_modal.html b/app/partials/chat_modal.html new file mode 100644 index 00000000..60855a4d --- /dev/null +++ b/app/partials/chat_modal.html @@ -0,0 +1,41 @@ +
+ + + + + +
\ No newline at end of file diff --git a/app/partials/dialog.html b/app/partials/dialog.html new file mode 100644 index 00000000..e81014e9 --- /dev/null +++ b/app/partials/dialog.html @@ -0,0 +1,73 @@ + + +
+
+ {{dialogMessage.date | dateOrTime}} +
+ + {{dialogMessage.unreadCount}} + +
+ +
+ +
+ +
+ +
+ + + + +
+ +
+ + You{{((dialogMessage.out || dialogMessage.peerID < 0) && (dialogMessage.message.length || dialogMessage.media && dialogMessage.media._ != 'messageMediaEmpty')) ? ':' : ''}} + + + + + Photo + + + Video + + + Document + + + Location + + + Contact + + + + + + created the group + + + changed group name + + + changed group photo + + + removed group photo + + + invited + + + kicked + + + + +
+ +
+
diff --git a/app/partials/head.html b/app/partials/head.html new file mode 100644 index 00000000..66c5f874 --- /dev/null +++ b/app/partials/head.html @@ -0,0 +1,17 @@ +
+ +
\ No newline at end of file diff --git a/app/partials/im.html b/app/partials/im.html new file mode 100644 index 00000000..c9bf9224 --- /dev/null +++ b/app/partials/im.html @@ -0,0 +1,118 @@ +
+ +
+ +
+ +
+ +
+
+
+ +
+
+
+
+ +
+
No history to display
+ +
+
+ +
+ +
+
+ +
+

+ + + + + + +

+
+ +
+

+ + + {{historyPeer.data | userStatus}} +

+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+ +
+
+ is typing.. +
+
+ +
+ +
+ +
+ +
+
+ + +
+
+ +
+
+ +
+
+
Drop photos here to send
+ + +
+ +
+ +
+ + +
+ + +
+
+ +
+
+ +
+ +
+ + +
+ diff --git a/app/partials/login.html b/app/partials/login.html new file mode 100644 index 00000000..0b616d4c --- /dev/null +++ b/app/partials/login.html @@ -0,0 +1,28 @@ +
+ + + \ No newline at end of file diff --git a/app/partials/message.html b/app/partials/message.html new file mode 100644 index 00000000..b5b832f4 --- /dev/null +++ b/app/partials/message.html @@ -0,0 +1,91 @@ +
+ +
+
+ + + + + + created the group «{{historyMessage.action.title}}» + + + changed group name to «{{historyMessage.action.title}}» + + + changed group photo + + + removed group photo + + + invited + + + kicked + + + + unsupported action {{historyMessage.action}} + + + +
+ + + + + +
+ +
+ + + + +
+ + {{historyMessage.date | dateOrTime}} +
+ +
+ +
+ +
+ + + + + + + +
+ {{historyMessage.media.video.duration | duration}} + +
+
+ + + +
{{historyMessage.media.document.file_name}} {{historyMessage.media.document.size | formatSize}}
+
+ + + + + +
+ + + +
{{historyMessage.media.first_name}} {{historyMessage.media.last_name}}
+
{{historyMessage.media.phone_number}}
+
+
+ +
+
+ +
+
diff --git a/app/partials/photo_modal.html b/app/partials/photo_modal.html new file mode 100644 index 00000000..02876897 --- /dev/null +++ b/app/partials/photo_modal.html @@ -0,0 +1,11 @@ +
+ + + +
\ No newline at end of file diff --git a/app/partials/user_modal.html b/app/partials/user_modal.html new file mode 100644 index 00000000..543c9d3c --- /dev/null +++ b/app/partials/user_modal.html @@ -0,0 +1,25 @@ +
+ + + + + + +
\ No newline at end of file diff --git a/app/partials/video_modal.html b/app/partials/video_modal.html new file mode 100644 index 00000000..3916660c --- /dev/null +++ b/app/partials/video_modal.html @@ -0,0 +1,11 @@ +
+ + + +
\ No newline at end of file diff --git a/app/partials/welcome.html b/app/partials/welcome.html new file mode 100644 index 00000000..7396c588 --- /dev/null +++ b/app/partials/welcome.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/app/vendor/README.md b/app/vendor/README.md new file mode 100644 index 00000000..07a91dcb --- /dev/null +++ b/app/vendor/README.md @@ -0,0 +1,70 @@ +## Third party libraries + +### [AngularJS](http://angularjs.org/) +**Author**: Google, Inc. +License - MIT, https://github.com/angular/angular.js/blob/master/LICENSE + +### [JSBN](http://www-cs-students.stanford.edu/~tjw/jsbn/) +**Author**: Tom Wu +**License**: BSD, http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE + +Biginteger for RSA, PQ prime factorization + + +### [jQuery Emojiarea](https://github.com/diy/jquery-emojiarea) +**Author**: diy +**License**: Apache, Version 2.0, https://github.com/diy/jquery-emojiarea#license + +Emoji keyboard and rich-textfield for composing messages with emoticons + + +### [UI Bootstrap](http://angular-ui.github.io/bootstrap/) +**Author**: AngularUI Team, https://github.com/organizations/angular-ui/teams/291112 +**License**: MIT, https://github.com/angular-ui/bootstrap/blob/master/LICENSE + +Modal windows + + +### [jQuery](https://github.com/jquery/jquery) +**Author**: jQuery Foundation and other contributors +**License**: MIT, https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt + +Dom manupulations. + +### [Bootstrap](https://github.com/twbs/bootstrap) +**Author**: Twitter, Inc +**License**: MIT, https://github.com/twbs/bootstrap/blob/master/LICENSE + +Normalize, CSS-framework + +### [nanoScrollerJS](https://github.com/jamesflorentino/nanoScrollerJS) +**Author**: James Florentino +**License**: MIT, https://github.com/jamesflorentino/nanoScrollerJS/blob/master/LICENSE-MIT + +Beautiful OS X Lion-like scrollbars + + +### [CryptoJS](https://code.google.com/p/crypto-js/) +**Author**: Jeff Mott +**License**: BSD-3-Clause, https://code.google.com/p/crypto-js/wiki/License + +AES, SHA-1 implementation + +### [zlib.js](https://github.com/imaya/zlib.js) +**Author**: imaya +**License**: MIT, https://github.com/imaya/zlib.js/blob/master/LICENSE + +GZIP for decompressing server responses + +### [emoji-data](https://github.com/iamcal/emoji-data) +**Author**: iamcal +**License**: not specified + +Build emoji list in apropriate format. Generate sheet in future, when needed. + + +### [gemoji](https://github.com/github/gemoji) +**Author**: GitHub Inc, 37signals, id Software, whynne@deviantart, Apple Inc. +**License**: https://github.com/github/gemoji/blob/master/LICENSE + +Emoji images \ No newline at end of file diff --git a/app/vendor/angular/angular-animate.js b/app/vendor/angular/angular-animate.js new file mode 100644 index 00000000..ce9a2d47 --- /dev/null +++ b/app/vendor/angular/angular-animate.js @@ -0,0 +1,1294 @@ +/** + * @license AngularJS v1.2.3 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/* jshint maxlen: false */ + +/** + * @ngdoc overview + * @name ngAnimate + * @description + * + * # ngAnimate + * + * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives. + * + * {@installModule animate} + * + *
+ * + * # Usage + * + * To see animations in action, all that is required is to define the appropriate CSS classes + * or to register a JavaScript animation via the myModule.animation() function. The directives that support animation automatically are: + * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation + * by using the `$animate` service. + * + * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives: + * + * | Directive | Supported Animations | + * |---------------------------------------------------------- |----------------------------------------------------| + * | {@link ng.directive:ngRepeat#usage_animations ngRepeat} | enter, leave and move | + * | {@link ngRoute.directive:ngView#usage_animations ngView} | enter and leave | + * | {@link ng.directive:ngInclude#usage_animations ngInclude} | enter and leave | + * | {@link ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave | + * | {@link ng.directive:ngIf#usage_animations ngIf} | enter and leave | + * | {@link ng.directive:ngClass#usage_animations ngClass} | add and remove | + * | {@link ng.directive:ngShow#usage_animations ngShow & ngHide} | add and remove (the ng-hide class value) | + * + * You can find out more information about animations upon visiting each directive page. + * + * Below is an example of how to apply animations to a directive that supports animation hooks: + * + *
+ * 
+ *
+ * 
+ * 
+ * 
+ * + * Keep in mind that if an animation is running, any child elements cannot be animated until the parent element's + * animation has completed. + * + *

CSS-defined Animations

+ * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes + * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported + * and can be used to play along with this naming structure. + * + * The following code below demonstrates how to perform animations using **CSS transitions** with Angular: + * + *
+ * 
+ *
+ * 
+ *
+ *
+ *
+ * + * The following code below demonstrates how to perform animations using **CSS animations** with Angular: + * + *
+ * 
+ *
+ * 
+ *
+ *
+ *
+ * + * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing. + * + * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add + * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically + * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be + * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end + * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element + * has no CSS transition/animation classes applied to it. + * + *

CSS Staggering Animations

+ * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a + * curtain-like effect. The ngAnimate module, as of 1.2.0, supports staggering animations and the stagger effect can be + * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for + * the animation. The style property expected within the stagger class can either be a **transition-delay** or an + * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). + * + *
+ * .my-animation.ng-enter {
+ *   /* standard transition code */
+ *   -webkit-transition: 1s linear all;
+ *   transition: 1s linear all;
+ *   opacity:0;
+ * }
+ * .my-animation.ng-enter-stagger {
+ *   /* this will have a 100ms delay between each successive leave animation */
+ *   -webkit-transition-delay: 0.1s;
+ *   transition-delay: 0.1s;
+ *
+ *   /* in case the stagger doesn't work then these two values
+ *    must be set to 0 to avoid an accidental CSS inheritance */
+ *   -webkit-transition-duration: 0s;
+ *   transition-duration: 0s;
+ * }
+ * .my-animation.ng-enter.ng-enter-active {
+ *   /* standard transition styles */
+ *   opacity:1;
+ * }
+ * 
+ * + * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations + * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this + * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation + * will also be reset if more than 10ms has passed after the last animation has been fired. + * + * The following code will issue the **ng-leave-stagger** event on the element provided: + * + *
+ * var kids = parent.children();
+ *
+ * $animate.leave(kids[0]); //stagger index=0
+ * $animate.leave(kids[1]); //stagger index=1
+ * $animate.leave(kids[2]); //stagger index=2
+ * $animate.leave(kids[3]); //stagger index=3
+ * $animate.leave(kids[4]); //stagger index=4
+ *
+ * $timeout(function() {
+ *   //stagger has reset itself
+ *   $animate.leave(kids[5]); //stagger index=0
+ *   $animate.leave(kids[6]); //stagger index=1
+ * }, 100, false);
+ * 
+ * + * Stagger animations are currently only supported within CSS-defined animations. + * + *

JavaScript-defined Animations

+ * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not + * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module. + * + *
+ * //!annotate="YourApp" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application.
+ * var ngModule = angular.module('YourApp', []);
+ * ngModule.animation('.my-crazy-animation', function() {
+ *   return {
+ *     enter: function(element, done) {
+ *       //run the animation here and call done when the animation is complete
+ *       return function(cancelled) {
+ *         //this (optional) function will be called when the animation
+ *         //completes or when the animation is cancelled (the cancelled
+ *         //flag will be set to true if cancelled).
+ *       }
+ *     }
+ *     leave: function(element, done) { },
+ *     move: function(element, done) { },
+ *
+ *     //animation that can be triggered before the class is added
+ *     beforeAddClass: function(element, className, done) { },
+ *
+ *     //animation that can be triggered after the class is added
+ *     addClass: function(element, className, done) { },
+ *
+ *     //animation that can be triggered before the class is removed
+ *     beforeRemoveClass: function(element, className, done) { },
+ *
+ *     //animation that can be triggered after the class is removed
+ *     removeClass: function(element, className, done) { }
+ *   }
+ * });
+ * 
+ * + * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run + * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits + * the element's CSS class attribute value and then run the matching animation event function (if found). + * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will + * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported). + * + * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned. + * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run, + * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation + * or transition code that is defined via a stylesheet). + * + */ + +angular.module('ngAnimate', ['ng']) + + /** + * @ngdoc object + * @name ngAnimate.$animateProvider + * @description + * + * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module. + * When an animation is triggered, the $animate service will query the $animate service to find any animations that match + * the provided name value. + * + * Requires the {@link ngAnimate `ngAnimate`} module to be installed. + * + * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. + * + */ + .config(['$provide', '$animateProvider', function($provide, $animateProvider) { + var noop = angular.noop; + var forEach = angular.forEach; + var selectors = $animateProvider.$$selectors; + + var ELEMENT_NODE = 1; + var NG_ANIMATE_STATE = '$$ngAnimateState'; + var NG_ANIMATE_CLASS_NAME = 'ng-animate'; + var rootAnimateState = {running: true}; + + $provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$timeout', '$rootScope', '$document', + function($delegate, $injector, $sniffer, $rootElement, $timeout, $rootScope, $document) { + + $rootElement.data(NG_ANIMATE_STATE, rootAnimateState); + + // disable animations during bootstrap, but once we bootstrapped, wait again + // for another digest until enabling animations. The reason why we digest twice + // is because all structural animations (enter, leave and move) all perform a + // post digest operation before animating. If we only wait for a single digest + // to pass then the structural animation would render its animation on page load. + // (which is what we're trying to avoid when the application first boots up.) + $rootScope.$$postDigest(function() { + $rootScope.$$postDigest(function() { + rootAnimateState.running = false; + }); + }); + + function lookup(name) { + if (name) { + var matches = [], + flagMap = {}, + classes = name.substr(1).split('.'); + + //the empty string value is the default animation + //operation which performs CSS transition and keyframe + //animations sniffing. This is always included for each + //element animation procedure if the browser supports + //transitions and/or keyframe animations + if ($sniffer.transitions || $sniffer.animations) { + classes.push(''); + } + + for(var i=0; i < classes.length; i++) { + var klass = classes[i], + selectorFactoryName = selectors[klass]; + if(selectorFactoryName && !flagMap[klass]) { + matches.push($injector.get(selectorFactoryName)); + flagMap[klass] = true; + } + } + return matches; + } + } + + /** + * @ngdoc object + * @name ngAnimate.$animate + * @function + * + * @description + * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations. + * When any of these operations are run, the $animate service + * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object) + * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run. + * + * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives + * will work out of the box without any extra configuration. + * + * Requires the {@link ngAnimate `ngAnimate`} module to be installed. + * + * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. + * + */ + return { + /** + * @ngdoc function + * @name ngAnimate.$animate#enter + * @methodOf ngAnimate.$animate + * @function + * + * @description + * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once + * the animation is started, the following CSS classes will be present on the element for the duration of the animation: + * + * Below is a breakdown of each step that occurs during enter animation: + * + * | Animation Step | What the element class attribute looks like | + * |----------------------------------------------------------------------------------------------|---------------------------------------------| + * | 1. $animate.enter(...) is called | class="my-animation" | + * | 2. element is inserted into the parentElement element or beside the afterElement element | class="my-animation" | + * | 3. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" | + * | 4. the .ng-enter class is added to the element | class="my-animation ng-animate ng-enter" | + * | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-enter" | + * | 6. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-enter" | + * | 7. the .ng-enter-active and .ng-animate-active classes are added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-enter ng-enter-active" | + * | 8. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-enter ng-enter-active" | + * | 9. The animation ends and all generated CSS classes are removed from the element | class="my-animation" | + * | 10. The doneCallback() callback is fired (if provided) | class="my-animation" | + * + * @param {jQuery/jqLite element} element the element that will be the focus of the enter animation + * @param {jQuery/jqLite element} parentElement the parent element of the element that will be the focus of the enter animation + * @param {jQuery/jqLite element} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation + * @param {function()=} doneCallback the callback function that will be called once the animation is complete + */ + enter : function(element, parentElement, afterElement, doneCallback) { + this.enabled(false, element); + $delegate.enter(element, parentElement, afterElement); + $rootScope.$$postDigest(function() { + performAnimation('enter', 'ng-enter', element, parentElement, afterElement, noop, doneCallback); + }); + }, + + /** + * @ngdoc function + * @name ngAnimate.$animate#leave + * @methodOf ngAnimate.$animate + * @function + * + * @description + * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once + * the animation is started, the following CSS classes will be added for the duration of the animation: + * + * Below is a breakdown of each step that occurs during enter animation: + * + * | Animation Step | What the element class attribute looks like | + * |----------------------------------------------------------------------------------------------|---------------------------------------------| + * | 1. $animate.leave(...) is called | class="my-animation" | + * | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" | + * | 3. the .ng-leave class is added to the element | class="my-animation ng-animate ng-leave" | + * | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-leave" | + * | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-leave" | + * | 6. the .ng-leave-active and .ng-animate-active classes is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-leave ng-leave-active" | + * | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-leave ng-leave-active" | + * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" | + * | 9. The element is removed from the DOM | ... | + * | 10. The doneCallback() callback is fired (if provided) | ... | + * + * @param {jQuery/jqLite element} element the element that will be the focus of the leave animation + * @param {function()=} doneCallback the callback function that will be called once the animation is complete + */ + leave : function(element, doneCallback) { + cancelChildAnimations(element); + this.enabled(false, element); + $rootScope.$$postDigest(function() { + performAnimation('leave', 'ng-leave', element, null, null, function() { + $delegate.leave(element); + }, doneCallback); + }); + }, + + /** + * @ngdoc function + * @name ngAnimate.$animate#move + * @methodOf ngAnimate.$animate + * @function + * + * @description + * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or + * add the element directly after the afterElement element if present. Then the move animation will be run. Once + * the animation is started, the following CSS classes will be added for the duration of the animation: + * + * Below is a breakdown of each step that occurs during move animation: + * + * | Animation Step | What the element class attribute looks like | + * |----------------------------------------------------------------------------------------------|---------------------------------------------| + * | 1. $animate.move(...) is called | class="my-animation" | + * | 2. element is moved into the parentElement element or beside the afterElement element | class="my-animation" | + * | 3. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" | + * | 4. the .ng-move class is added to the element | class="my-animation ng-animate ng-move" | + * | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-move" | + * | 6. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-move" | + * | 7. the .ng-move-active and .ng-animate-active classes is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-move ng-move-active" | + * | 8. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-move ng-move-active" | + * | 9. The animation ends and all generated CSS classes are removed from the element | class="my-animation" | + * | 10. The doneCallback() callback is fired (if provided) | class="my-animation" | + * + * @param {jQuery/jqLite element} element the element that will be the focus of the move animation + * @param {jQuery/jqLite element} parentElement the parentElement element of the element that will be the focus of the move animation + * @param {jQuery/jqLite element} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation + * @param {function()=} doneCallback the callback function that will be called once the animation is complete + */ + move : function(element, parentElement, afterElement, doneCallback) { + cancelChildAnimations(element); + this.enabled(false, element); + $delegate.move(element, parentElement, afterElement); + $rootScope.$$postDigest(function() { + performAnimation('move', 'ng-move', element, parentElement, afterElement, noop, doneCallback); + }); + }, + + /** + * @ngdoc function + * @name ngAnimate.$animate#addClass + * @methodOf ngAnimate.$animate + * + * @description + * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class. + * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide + * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions + * or keyframes are defined on the -add or base CSS class). + * + * Below is a breakdown of each step that occurs during addClass animation: + * + * | Animation Step | What the element class attribute looks like | + * |------------------------------------------------------------------------------------------------|---------------------------------------------| + * | 1. $animate.addClass(element, 'super') is called | class="my-animation" | + * | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" | + * | 3. the .super-add class are added to the element | class="my-animation ng-animate super-add" | + * | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate super-add" | + * | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate super-add" | + * | 6. the .super, .super-add-active and .ng-animate-active classes are added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active super super-add super-add-active" | + * | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation super-add super-add-active" | + * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation super" | + * | 9. The super class is kept on the element | class="my-animation super" | + * | 10. The doneCallback() callback is fired (if provided) | class="my-animation super" | + * + * @param {jQuery/jqLite element} element the element that will be animated + * @param {string} className the CSS class that will be added to the element and then animated + * @param {function()=} doneCallback the callback function that will be called once the animation is complete + */ + addClass : function(element, className, doneCallback) { + performAnimation('addClass', className, element, null, null, function() { + $delegate.addClass(element, className); + }, doneCallback); + }, + + /** + * @ngdoc function + * @name ngAnimate.$animate#removeClass + * @methodOf ngAnimate.$animate + * + * @description + * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value + * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in + * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if + * no CSS transitions or keyframes are defined on the -remove or base CSS classes). + * + * Below is a breakdown of each step that occurs during removeClass animation: + * + * | Animation Step | What the element class attribute looks like | + * |-----------------------------------------------------------------------------------------------|---------------------------------------------| + * | 1. $animate.removeClass(element, 'super') is called | class="my-animation super" | + * | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation super ng-animate" | + * | 3. the .super-remove class are added to the element | class="my-animation super ng-animate super-remove"| + * | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation super ng-animate super-remove" | + * | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation super ng-animate super-remove" | + * | 6. the .super-remove-active and .ng-animate-active classes are added and .super is removed (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active super-remove super-remove-active" | + * | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active super-remove super-remove-active" | + * | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" | + * | 9. The doneCallback() callback is fired (if provided) | class="my-animation" | + * + * + * @param {jQuery/jqLite element} element the element that will be animated + * @param {string} className the CSS class that will be animated and then removed from the element + * @param {function()=} doneCallback the callback function that will be called once the animation is complete + */ + removeClass : function(element, className, doneCallback) { + performAnimation('removeClass', className, element, null, null, function() { + $delegate.removeClass(element, className); + }, doneCallback); + }, + + /** + * @ngdoc function + * @name ngAnimate.$animate#enabled + * @methodOf ngAnimate.$animate + * @function + * + * @param {boolean=} value If provided then set the animation on or off. + * @param {jQuery/jqLite element=} element If provided then the element will be used to represent the enable/disable operation + * @return {boolean} Current animation state. + * + * @description + * Globally enables/disables animations. + * + */ + enabled : function(value, element) { + switch(arguments.length) { + case 2: + if(value) { + cleanup(element); + } else { + var data = element.data(NG_ANIMATE_STATE) || {}; + data.disabled = true; + element.data(NG_ANIMATE_STATE, data); + } + break; + + case 1: + rootAnimateState.disabled = !value; + break; + + default: + value = !rootAnimateState.disabled; + break; + } + return !!value; + } + }; + + /* + all animations call this shared animation triggering function internally. + The animationEvent variable refers to the JavaScript animation event that will be triggered + and the className value is the name of the animation that will be applied within the + CSS code. Element, parentElement and afterElement are provided DOM elements for the animation + and the onComplete callback will be fired once the animation is fully complete. + */ + function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, doneCallback) { + var currentClassName = element.attr('class') || ''; + var classes = currentClassName + ' ' + className; + var animationLookup = (' ' + classes).replace(/\s+/g,'.'); + if (!parentElement) { + parentElement = afterElement ? afterElement.parent() : element.parent(); + } + + var matches = lookup(animationLookup); + var isClassBased = animationEvent == 'addClass' || animationEvent == 'removeClass'; + var ngAnimateState = element.data(NG_ANIMATE_STATE) || {}; + + //skip the animation if animations are disabled, a parent is already being animated, + //the element is not currently attached to the document body or then completely close + //the animation if any matching animations are not found at all. + //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case a NO animation is not found. + if (animationsDisabled(element, parentElement) || matches.length === 0) { + fireDOMOperation(); + closeAnimation(); + return; + } + + var animations = []; + //only add animations if the currently running animation is not structural + //or if there is no animation running at all + if(!ngAnimateState.running || !(isClassBased && ngAnimateState.structural)) { + forEach(matches, function(animation) { + //add the animation to the queue to if it is allowed to be cancelled + if(!animation.allowCancel || animation.allowCancel(element, animationEvent, className)) { + var beforeFn, afterFn = animation[animationEvent]; + + //Special case for a leave animation since there is no point in performing an + //animation on a element node that has already been removed from the DOM + if(animationEvent == 'leave') { + beforeFn = afterFn; + afterFn = null; //this must be falsy so that the animation is skipped for leave + } else { + beforeFn = animation['before' + animationEvent.charAt(0).toUpperCase() + animationEvent.substr(1)]; + } + animations.push({ + before : beforeFn, + after : afterFn + }); + } + }); + } + + //this would mean that an animation was not allowed so let the existing + //animation do it's thing and close this one early + if(animations.length === 0) { + fireDOMOperation(); + fireDoneCallbackAsync(); + return; + } + + //this value will be searched for class-based CSS className lookup. Therefore, + //we prefix and suffix the current className value with spaces to avoid substring + //lookups of className tokens + var futureClassName = ' ' + currentClassName + ' '; + if(ngAnimateState.running) { + //if an animation is currently running on the element then lets take the steps + //to cancel that animation and fire any required callbacks + $timeout.cancel(ngAnimateState.closeAnimationTimeout); + cleanup(element); + cancelAnimations(ngAnimateState.animations); + + //if the class is removed during the reflow then it will revert the styles temporarily + //back to the base class CSS styling causing a jump-like effect to occur. This check + //here ensures that the domOperation is only performed after the reflow has commenced + if(ngAnimateState.beforeComplete) { + (ngAnimateState.done || noop)(true); + } else if(isClassBased && !ngAnimateState.structural) { + //class-based animations will compare element className values after cancelling the + //previous animation to see if the element properties already contain the final CSS + //class and if so then the animation will be skipped. Since the domOperation will + //be performed only after the reflow is complete then our element's className value + //will be invalid. Therefore the same string manipulation that would occur within the + //DOM operation will be performed below so that the class comparison is valid... + futureClassName = ngAnimateState.event == 'removeClass' ? + futureClassName.replace(ngAnimateState.className, '') : + futureClassName + ngAnimateState.className + ' '; + } + } + + //There is no point in perform a class-based animation if the element already contains + //(on addClass) or doesn't contain (on removeClass) the className being animated. + //The reason why this is being called after the previous animations are cancelled + //is so that the CSS classes present on the element can be properly examined. + var classNameToken = ' ' + className + ' '; + if((animationEvent == 'addClass' && futureClassName.indexOf(classNameToken) >= 0) || + (animationEvent == 'removeClass' && futureClassName.indexOf(classNameToken) == -1)) { + fireDOMOperation(); + fireDoneCallbackAsync(); + return; + } + + //the ng-animate class does nothing, but it's here to allow for + //parent animations to find and cancel child animations when needed + element.addClass(NG_ANIMATE_CLASS_NAME); + + element.data(NG_ANIMATE_STATE, { + running:true, + event:animationEvent, + className:className, + structural:!isClassBased, + animations:animations, + done:onBeforeAnimationsComplete + }); + + //first we run the before animations and when all of those are complete + //then we perform the DOM operation and run the next set of animations + invokeRegisteredAnimationFns(animations, 'before', onBeforeAnimationsComplete); + + function onBeforeAnimationsComplete(cancelled) { + fireDOMOperation(); + if(cancelled === true) { + closeAnimation(); + return; + } + + //set the done function to the final done function + //so that the DOM event won't be executed twice by accident + //if the after animation is cancelled as well + var data = element.data(NG_ANIMATE_STATE); + if(data) { + data.done = closeAnimation; + element.data(NG_ANIMATE_STATE, data); + } + invokeRegisteredAnimationFns(animations, 'after', closeAnimation); + } + + function invokeRegisteredAnimationFns(animations, phase, allAnimationFnsComplete) { + var endFnName = phase + 'End'; + forEach(animations, function(animation, index) { + var animationPhaseCompleted = function() { + progress(index, phase); + }; + + //there are no before functions for enter + move since the DOM + //operations happen before the performAnimation method fires + if(phase == 'before' && (animationEvent == 'enter' || animationEvent == 'move')) { + animationPhaseCompleted(); + return; + } + + if(animation[phase]) { + animation[endFnName] = isClassBased ? + animation[phase](element, className, animationPhaseCompleted) : + animation[phase](element, animationPhaseCompleted); + } else { + animationPhaseCompleted(); + } + }); + + function progress(index, phase) { + var phaseCompletionFlag = phase + 'Complete'; + var currentAnimation = animations[index]; + currentAnimation[phaseCompletionFlag] = true; + (currentAnimation[endFnName] || noop)(); + + for(var i=0;i 0) { + aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1; + } + + animationDuration = Math.max(aDuration, animationDuration); + } + }); + data = { + total : 0, + transitionPropertyStyle: transitionPropertyStyle, + transitionDurationStyle: transitionDurationStyle, + transitionDelayStyle: transitionDelayStyle, + transitionDelay: transitionDelay, + transitionDuration: transitionDuration, + animationDelayStyle: animationDelayStyle, + animationDelay: animationDelay, + animationDuration: animationDuration + }; + if(cacheKey) { + lookupCache[cacheKey] = data; + } + } + return data; + } + + function parseMaxTime(str) { + var maxValue = 0; + var values = angular.isString(str) ? + str.split(/\s*,\s*/) : + []; + forEach(values, function(value) { + maxValue = Math.max(parseFloat(value) || 0, maxValue); + }); + return maxValue; + } + + function getCacheKey(element) { + var parentElement = element.parent(); + var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY); + if(!parentID) { + parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter); + parentID = parentCounter; + } + return parentID + '-' + element[0].className; + } + + function animateSetup(element, className) { + var cacheKey = getCacheKey(element); + var eventCacheKey = cacheKey + ' ' + className; + var stagger = {}; + var ii = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; + + if(ii > 0) { + var staggerClassName = className + '-stagger'; + var staggerCacheKey = cacheKey + ' ' + staggerClassName; + var applyClasses = !lookupCache[staggerCacheKey]; + + applyClasses && element.addClass(staggerClassName); + + stagger = getElementAnimationDetails(element, staggerCacheKey); + + applyClasses && element.removeClass(staggerClassName); + } + + element.addClass(className); + + var timings = getElementAnimationDetails(element, eventCacheKey); + + /* there is no point in performing a reflow if the animation + timeout is empty (this would cause a flicker bug normally + in the page. There is also no point in performing an animation + that only has a delay and no duration */ + var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration); + if(maxDuration === 0) { + element.removeClass(className); + return false; + } + + var node = element[0]; + //temporarily disable the transition so that the enter styles + //don't animate twice (this is here to avoid a bug in Chrome/FF). + var activeClassName = ''; + if(timings.transitionDuration > 0) { + element.addClass(NG_ANIMATE_FALLBACK_CLASS_NAME); + activeClassName += NG_ANIMATE_FALLBACK_ACTIVE_CLASS_NAME + ' '; + blockTransitions(element); + } else { + blockKeyframeAnimations(element); + } + + forEach(className.split(' '), function(klass, i) { + activeClassName += (i > 0 ? ' ' : '') + klass + '-active'; + }); + + element.data(NG_ANIMATE_CSS_DATA_KEY, { + className : className, + activeClassName : activeClassName, + maxDuration : maxDuration, + classes : className + ' ' + activeClassName, + timings : timings, + stagger : stagger, + ii : ii + }); + + return true; + } + + function blockTransitions(element) { + element[0].style[TRANSITION_PROP + PROPERTY_KEY] = 'none'; + } + + function blockKeyframeAnimations(element) { + element[0].style[ANIMATION_PROP] = 'none 0s'; + } + + function unblockTransitions(element) { + var node = element[0], prop = TRANSITION_PROP + PROPERTY_KEY; + if(node.style[prop] && node.style[prop].length > 0) { + node.style[prop] = ''; + } + } + + function unblockKeyframeAnimations(element) { + var node = element[0], prop = ANIMATION_PROP; + if(node.style[prop] && node.style[prop].length > 0) { + element[0].style[prop] = ''; + } + } + + function animateRun(element, className, activeAnimationComplete) { + var data = element.data(NG_ANIMATE_CSS_DATA_KEY); + if(!element.hasClass(className) || !data) { + activeAnimationComplete(); + return; + } + + var node = element[0]; + var timings = data.timings; + var stagger = data.stagger; + var maxDuration = data.maxDuration; + var activeClassName = data.activeClassName; + var maxDelayTime = Math.max(timings.transitionDelay, timings.animationDelay) * 1000; + var startTime = Date.now(); + var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT; + var ii = data.ii; + + var applyFallbackStyle, style = '', appliedStyles = []; + if(timings.transitionDuration > 0) { + var propertyStyle = timings.transitionPropertyStyle; + if(propertyStyle.indexOf('all') == -1) { + applyFallbackStyle = true; + var fallbackProperty = $sniffer.msie ? '-ms-zoom' : 'border-spacing'; + style += CSS_PREFIX + 'transition-property: ' + propertyStyle + ', ' + fallbackProperty + '; '; + style += CSS_PREFIX + 'transition-duration: ' + timings.transitionDurationStyle + ', ' + timings.transitionDuration + 's; '; + appliedStyles.push(CSS_PREFIX + 'transition-property'); + appliedStyles.push(CSS_PREFIX + 'transition-duration'); + } + } + + if(ii > 0) { + if(stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { + var delayStyle = timings.transitionDelayStyle; + if(applyFallbackStyle) { + delayStyle += ', ' + timings.transitionDelay + 's'; + } + + style += CSS_PREFIX + 'transition-delay: ' + + prepareStaggerDelay(delayStyle, stagger.transitionDelay, ii) + '; '; + appliedStyles.push(CSS_PREFIX + 'transition-delay'); + } + + if(stagger.animationDelay > 0 && stagger.animationDuration === 0) { + style += CSS_PREFIX + 'animation-delay: ' + + prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, ii) + '; '; + appliedStyles.push(CSS_PREFIX + 'animation-delay'); + } + } + + if(appliedStyles.length > 0) { + var oldStyle = node.getAttribute('style') || ''; + node.setAttribute('style', oldStyle + ' ' + style); + } + + element.on(css3AnimationEvents, onAnimationProgress); + element.addClass(activeClassName); + + // This will automatically be called by $animate so + // there is no need to attach this internally to the + // timeout done method. + return function onEnd(cancelled) { + element.off(css3AnimationEvents, onAnimationProgress); + element.removeClass(activeClassName); + animateClose(element, className); + for (var i in appliedStyles) { + node.style.removeProperty(appliedStyles[i]); + } + }; + + function onAnimationProgress(event) { + event.stopPropagation(); + var ev = event.originalEvent || event; + var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); + /* $manualTimeStamp is a mocked timeStamp value which is set + * within browserTrigger(). This is only here so that tests can + * mock animations properly. Real events fallback to event.timeStamp, + * or, if they don't, then a timeStamp is automatically created for them. + * We're checking to see if the timeStamp surpasses the expected delay, + * but we're using elapsedTime instead of the timeStamp on the 2nd + * pre-condition since animations sometimes close off early */ + if(Math.max(timeStamp - startTime, 0) >= maxDelayTime && ev.elapsedTime >= maxDuration) { + activeAnimationComplete(); + } + } + } + + function prepareStaggerDelay(delayStyle, staggerDelay, index) { + var style = ''; + forEach(delayStyle.split(','), function(val, i) { + style += (i > 0 ? ',' : '') + + (index * staggerDelay + parseInt(val, 10)) + 's'; + }); + return style; + } + + function animateBefore(element, className) { + if(animateSetup(element, className)) { + return function(cancelled) { + cancelled && animateClose(element, className); + }; + } + } + + function animateAfter(element, className, afterAnimationComplete) { + if(element.data(NG_ANIMATE_CSS_DATA_KEY)) { + return animateRun(element, className, afterAnimationComplete); + } else { + animateClose(element, className); + afterAnimationComplete(); + } + } + + function animate(element, className, animationComplete) { + //If the animateSetup function doesn't bother returning a + //cancellation function then it means that there is no animation + //to perform at all + var preReflowCancellation = animateBefore(element, className); + if(!preReflowCancellation) { + animationComplete(); + return; + } + + //There are two cancellation functions: one is before the first + //reflow animation and the second is during the active state + //animation. The first function will take care of removing the + //data from the element which will not make the 2nd animation + //happen in the first place + var cancel = preReflowCancellation; + afterReflow(function() { + unblockTransitions(element); + unblockKeyframeAnimations(element); + //once the reflow is complete then we point cancel to + //the new cancellation function which will remove all of the + //animation properties from the active animation + cancel = animateAfter(element, className, animationComplete); + }); + + return function(cancelled) { + (cancel || noop)(cancelled); + }; + } + + function animateClose(element, className) { + element.removeClass(className); + element.removeClass(NG_ANIMATE_FALLBACK_CLASS_NAME); + element.removeData(NG_ANIMATE_CSS_DATA_KEY); + } + + return { + allowCancel : function(element, animationEvent, className) { + //always cancel the current animation if it is a + //structural animation + var oldClasses = (element.data(NG_ANIMATE_CSS_DATA_KEY) || {}).classes; + if(!oldClasses || ['enter','leave','move'].indexOf(animationEvent) >= 0) { + return true; + } + + var parentElement = element.parent(); + var clone = angular.element(element[0].cloneNode()); + + //make the element super hidden and override any CSS style values + clone.attr('style','position:absolute; top:-9999px; left:-9999px'); + clone.removeAttr('id'); + clone.html(''); + + forEach(oldClasses.split(' '), function(klass) { + clone.removeClass(klass); + }); + + var suffix = animationEvent == 'addClass' ? '-add' : '-remove'; + clone.addClass(suffixClasses(className, suffix)); + parentElement.append(clone); + + var timings = getElementAnimationDetails(clone); + clone.remove(); + + return Math.max(timings.transitionDuration, timings.animationDuration) > 0; + }, + + enter : function(element, animationCompleted) { + return animate(element, 'ng-enter', animationCompleted); + }, + + leave : function(element, animationCompleted) { + return animate(element, 'ng-leave', animationCompleted); + }, + + move : function(element, animationCompleted) { + return animate(element, 'ng-move', animationCompleted); + }, + + beforeAddClass : function(element, className, animationCompleted) { + var cancellationMethod = animateBefore(element, suffixClasses(className, '-add')); + if(cancellationMethod) { + afterReflow(function() { + unblockTransitions(element); + unblockKeyframeAnimations(element); + animationCompleted(); + }); + return cancellationMethod; + } + animationCompleted(); + }, + + addClass : function(element, className, animationCompleted) { + return animateAfter(element, suffixClasses(className, '-add'), animationCompleted); + }, + + beforeRemoveClass : function(element, className, animationCompleted) { + var cancellationMethod = animateBefore(element, suffixClasses(className, '-remove')); + if(cancellationMethod) { + afterReflow(function() { + unblockTransitions(element); + unblockKeyframeAnimations(element); + animationCompleted(); + }); + return cancellationMethod; + } + animationCompleted(); + }, + + removeClass : function(element, className, animationCompleted) { + return animateAfter(element, suffixClasses(className, '-remove'), animationCompleted); + } + }; + + function suffixClasses(classes, suffix) { + var className = ''; + classes = angular.isArray(classes) ? classes : classes.split(/\s+/); + forEach(classes, function(klass, i) { + if(klass && klass.length > 0) { + className += (i > 0 ? ' ' : '') + klass + suffix; + } + }); + return className; + } + }]); + }]); + + +})(window, window.angular); diff --git a/app/vendor/angular/angular-animate.min.js b/app/vendor/angular/angular-animate.min.js new file mode 100644 index 00000000..796fbbb2 --- /dev/null +++ b/app/vendor/angular/angular-animate.min.js @@ -0,0 +1,22 @@ +/* + AngularJS v1.2.3 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(C,k,F){'use strict';k.module("ngAnimate",["ng"]).config(["$provide","$animateProvider",function(M,G){var p=k.noop,r=k.forEach,N=G.$$selectors,T=1,h="$$ngAnimateState",H="ng-animate",l={running:!0};M.decorator("$animate",["$delegate","$injector","$sniffer","$rootElement","$timeout","$rootScope","$document",function(v,C,I,g,s,q,F){function O(a){if(a){var d=[],c={};a=a.substr(1).split(".");(I.transitions||I.animations)&&a.push("");for(var e=0;e=v&&a.elapsedTime>=q&&e()}var n=a.data(y);if(a.hasClass(d)&&n){var l=a[0],g=n.timings,m=n.stagger, +q=n.maxDuration,r=n.activeClassName,v=1E3*Math.max(g.transitionDelay,g.animationDelay),w=Date.now(),t=Q+" "+P,u=n.ii,x,n="",p=[];if(0 + * + * See {@link ngCookies.$cookies `$cookies`} and + * {@link ngCookies.$cookieStore `$cookieStore`} for usage. + */ + + +angular.module('ngCookies', ['ng']). + /** + * @ngdoc object + * @name ngCookies.$cookies + * @requires $browser + * + * @description + * Provides read/write access to browser's cookies. + * + * Only a simple Object is exposed and by adding or removing properties to/from + * this object, new cookies are created/deleted at the end of current $eval. + * + * Requires the {@link ngCookies `ngCookies`} module to be installed. + * + * @example + + + + + + */ + factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) { + var cookies = {}, + lastCookies = {}, + lastBrowserCookies, + runEval = false, + copy = angular.copy, + isUndefined = angular.isUndefined; + + //creates a poller fn that copies all cookies from the $browser to service & inits the service + $browser.addPollFn(function() { + var currentCookies = $browser.cookies(); + if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl + lastBrowserCookies = currentCookies; + copy(currentCookies, lastCookies); + copy(currentCookies, cookies); + if (runEval) $rootScope.$apply(); + } + })(); + + runEval = true; + + //at the end of each eval, push cookies + //TODO: this should happen before the "delayed" watches fire, because if some cookies are not + // strings or browser refuses to store some cookies, we update the model in the push fn. + $rootScope.$watch(push); + + return cookies; + + + /** + * Pushes all the cookies from the service to the browser and verifies if all cookies were + * stored. + */ + function push() { + var name, + value, + browserCookies, + updated; + + //delete any cookies deleted in $cookies + for (name in lastCookies) { + if (isUndefined(cookies[name])) { + $browser.cookies(name, undefined); + } + } + + //update all cookies updated in $cookies + for(name in cookies) { + value = cookies[name]; + if (!angular.isString(value)) { + if (angular.isDefined(lastCookies[name])) { + cookies[name] = lastCookies[name]; + } else { + delete cookies[name]; + } + } else if (value !== lastCookies[name]) { + $browser.cookies(name, value); + updated = true; + } + } + + //verify what was actually stored + if (updated){ + updated = false; + browserCookies = $browser.cookies(); + + for (name in cookies) { + if (cookies[name] !== browserCookies[name]) { + //delete or reset all cookies that the browser dropped from $cookies + if (isUndefined(browserCookies[name])) { + delete cookies[name]; + } else { + cookies[name] = browserCookies[name]; + } + updated = true; + } + } + } + } + }]). + + + /** + * @ngdoc object + * @name ngCookies.$cookieStore + * @requires $cookies + * + * @description + * Provides a key-value (string-object) storage, that is backed by session cookies. + * Objects put or retrieved from this storage are automatically serialized or + * deserialized by angular's toJson/fromJson. + * + * Requires the {@link ngCookies `ngCookies`} module to be installed. + * + * @example + */ + factory('$cookieStore', ['$cookies', function($cookies) { + + return { + /** + * @ngdoc method + * @name ngCookies.$cookieStore#get + * @methodOf ngCookies.$cookieStore + * + * @description + * Returns the value of given cookie key + * + * @param {string} key Id to use for lookup. + * @returns {Object} Deserialized cookie value. + */ + get: function(key) { + var value = $cookies[key]; + return value ? angular.fromJson(value) : value; + }, + + /** + * @ngdoc method + * @name ngCookies.$cookieStore#put + * @methodOf ngCookies.$cookieStore + * + * @description + * Sets a value for given cookie key + * + * @param {string} key Id for the `value`. + * @param {Object} value Value to be stored. + */ + put: function(key, value) { + $cookies[key] = angular.toJson(value); + }, + + /** + * @ngdoc method + * @name ngCookies.$cookieStore#remove + * @methodOf ngCookies.$cookieStore + * + * @description + * Remove given cookie + * + * @param {string} key Id of the key-value pair to delete. + */ + remove: function(key) { + delete $cookies[key]; + } + }; + + }]); + + +})(window, window.angular); diff --git a/app/vendor/angular/angular-cookies.min.js b/app/vendor/angular/angular-cookies.min.js new file mode 100644 index 00000000..c6956ac8 --- /dev/null +++ b/app/vendor/angular/angular-cookies.min.js @@ -0,0 +1,8 @@ +/* + AngularJS v1.2.3 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&d.$apply())})();k=!0;d.$watch(function(){var a,e,d;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)(e=c[a],f.isString(e))?e!==g[a]&&(b.cookies(a,e),d=!0):f.isDefined(g[a])?c[a]=g[a]:delete c[a];if(d)for(a in e=b.cookies(),c)c[a]!==e[a]&&(m(e[a])?delete c[a]:c[a]=e[a])}); +return c}]).factory("$cookieStore",["$cookies",function(d){return{get:function(b){return(b=d[b])?f.fromJson(b):b},put:function(b,c){d[b]=f.toJson(c)},remove:function(b){delete d[b]}}}])})(window,window.angular); +//# sourceMappingURL=angular-cookies.min.js.map diff --git a/app/vendor/angular/angular-cookies.min.js.map b/app/vendor/angular/angular-cookies.min.js.map new file mode 100644 index 00000000..a7fd1e9c --- /dev/null +++ b/app/vendor/angular/angular-cookies.min.js.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"angular-cookies.min.js", +"lineCount":7, +"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAoBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA4BW,UA5BX,CA4BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAS,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACxEC,EAAU,EAD8D,CAExEC,EAAc,EAF0D,CAGxEC,CAHwE,CAIxEC,EAAU,CAAA,CAJ8D,CAKxEC,EAAOV,CAAAU,KALiE,CAMxEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAIgB,CAAJ,GAAYX,EAAZ,CAEE,CADAY,CACK,CADGZ,CAAA,CAAQW,CAAR,CACH,CAAAjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAAL,EAMWA,CANX,GAMqBX,CAAA,CAAYU,CAAZ,CANrB,GAOEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CARZ,EACMnB,CAAAqB,UAAA,CAAkBd,CAAA,CAAYU,CAAZ,CAAlB,CAAJ,CACEX,CAAA,CAAQW,CAAR,CADF,CACkBV,CAAA,CAAYU,CAAZ,CADlB,CAGE,OAAOX,CAAA,CAAQW,CAAR,CASb,IAAIE,CAAJ,CAIE,IAAKF,CAAL,GAFAK,EAEahB,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBK,CAAA,CAAeL,CAAf,CAAtB,GAEMN,CAAA,CAAYW,CAAA,CAAeL,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBK,CAAA,CAAeL,CAAf,CALpB,CAlCU,CAThB,CAEA;MAAOX,EA1BqE,CAA3D,CA5BvB,CAAAH,QAAA,CA4HW,cA5HX,CA4H2B,CAAC,UAAD,CAAa,QAAQ,CAACoB,CAAD,CAAW,CAErD,MAAO,KAYAC,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHP,CACG,CADKK,CAAA,CAASE,CAAT,CACL,EAAQzB,CAAA0B,SAAA,CAAiBR,CAAjB,CAAR,CAAkCA,CAFxB,CAZd,KA4BAS,QAAQ,CAACF,CAAD,CAAMP,CAAN,CAAa,CACxBK,CAAA,CAASE,CAAT,CAAA,CAAgBzB,CAAA4B,OAAA,CAAeV,CAAf,CADQ,CA5BrB,QA0CGW,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CA1CjB,CAF8C,CAAhC,CA5H3B,CApBsC,CAArC,CAAA,CAoME1B,MApMF,CAoMUA,MAAAC,QApMV;", +"sources":["angular-cookies.js"], +"names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","isDefined","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"] +} diff --git a/app/vendor/angular/angular-csp.css b/app/vendor/angular/angular-csp.css new file mode 100644 index 00000000..585878ef --- /dev/null +++ b/app/vendor/angular/angular-csp.css @@ -0,0 +1,24 @@ +/* Include this file in your html if you are using the CSP mode. */ + +@charset "UTF-8"; + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], +.ng-cloak, .x-ng-cloak, +.ng-hide { + display: none !important; +} + +ng\:form { + display: block; +} + +/* The styles below ensure that the CSS transition will ALWAYS + * animate and close. A nasty bug occurs with CSS transitions where + * when the active class isn't set, or if the active class doesn't + * contain any styles to transition to, then, if ngAnimate is used, + * it will appear as if the webpage is broken due to the forever hanging + * animations. The border-spacing (!ie) and zoom (ie) CSS properties are + * used below since they trigger a transition without making the browser + * animate anything and they're both highly underused CSS properties */ +.ng-animate-start { border-spacing:1px 1px; -ms-zoom:1.0001; } +.ng-animate-active { border-spacing:0px 0px; -ms-zoom:1; } diff --git a/app/vendor/angular/angular-loader.js b/app/vendor/angular/angular-loader.js new file mode 100644 index 00000000..431ff1f0 --- /dev/null +++ b/app/vendor/angular/angular-loader.js @@ -0,0 +1,410 @@ +/** + * @license AngularJS v1.2.3 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ + +(function() {'use strict'; + +/** + * @description + * + * This object provides a utility for producing rich Error messages within + * Angular. It can be called as follows: + * + * var exampleMinErr = minErr('example'); + * throw exampleMinErr('one', 'This {0} is {1}', foo, bar); + * + * The above creates an instance of minErr in the example namespace. The + * resulting error will have a namespaced error code of example.one. The + * resulting error will replace {0} with the value of foo, and {1} with the + * value of bar. The object is not restricted in the number of arguments it can + * take. + * + * If fewer arguments are specified than necessary for interpolation, the extra + * interpolation markers will be preserved in the final string. + * + * Since data will be parsed statically during a build step, some restrictions + * are applied with respect to how minErr instances are created and called. + * Instances should have names of the form namespaceMinErr for a minErr created + * using minErr('namespace') . Error codes, namespaces and template strings + * should all be static strings, not variables or general expressions. + * + * @param {string} module The namespace to use for the new minErr instance. + * @returns {function(string, string, ...): Error} instance + */ + +function minErr(module) { + return function () { + var code = arguments[0], + prefix = '[' + (module ? module + ':' : '') + code + '] ', + template = arguments[1], + templateArgs = arguments, + stringify = function (obj) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (typeof obj === 'undefined') { + return 'undefined'; + } else if (typeof obj !== 'string') { + return JSON.stringify(obj); + } + return obj; + }, + message, i; + + message = prefix + template.replace(/\{\d+\}/g, function (match) { + var index = +match.slice(1, -1), arg; + + if (index + 2 < templateArgs.length) { + arg = templateArgs[index + 2]; + if (typeof arg === 'function') { + return arg.toString().replace(/ ?\{[\s\S]*$/, ''); + } else if (typeof arg === 'undefined') { + return 'undefined'; + } else if (typeof arg !== 'string') { + return toJson(arg); + } + return arg; + } + return match; + }); + + message = message + '\nhttp://errors.angularjs.org/1.2.3/' + + (module ? module + '/' : '') + code; + for (i = 2; i < arguments.length; i++) { + message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' + + encodeURIComponent(stringify(arguments[i])); + } + + return new Error(message); + }; +} + +/** + * @ngdoc interface + * @name angular.Module + * @description + * + * Interface for configuring angular {@link angular.module modules}. + */ + +function setupModuleLoader(window) { + + var $injectorMinErr = minErr('$injector'); + var ngMinErr = minErr('ng'); + + function ensure(obj, name, factory) { + return obj[name] || (obj[name] = factory()); + } + + var angular = ensure(window, 'angular', Object); + + // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap + angular.$$minErr = angular.$$minErr || minErr; + + return ensure(angular, 'module', function() { + /** @type {Object.} */ + var modules = {}; + + /** + * @ngdoc function + * @name angular.module + * @description + * + * The `angular.module` is a global place for creating, registering and retrieving Angular + * modules. + * All modules (angular core or 3rd party) that should be available to an application must be + * registered using this mechanism. + * + * When passed two or more arguments, a new module is created. If passed only one argument, an + * existing module (the name passed as the first argument to `module`) is retrieved. + * + * + * # Module + * + * A module is a collection of services, directives, filters, and configuration information. + * `angular.module` is used to configure the {@link AUTO.$injector $injector}. + * + *
+     * // Create a new module
+     * var myModule = angular.module('myModule', []);
+     *
+     * // register a new service
+     * myModule.value('appName', 'MyCoolApp');
+     *
+     * // configure existing services inside initialization blocks.
+     * myModule.config(function($locationProvider) {
+     *   // Configure existing providers
+     *   $locationProvider.hashPrefix('!');
+     * });
+     * 
+ * + * Then you can create an injector and load your modules like this: + * + *
+     * var injector = angular.injector(['ng', 'MyModule'])
+     * 
+ * + * However it's more likely that you'll just use + * {@link ng.directive:ngApp ngApp} or + * {@link angular.bootstrap} to simplify this process for you. + * + * @param {!string} name The name of the module to create or retrieve. + * @param {Array.=} requires If specified then new module is being created. If + * unspecified then the the module is being retrieved for further configuration. + * @param {Function} configFn Optional configuration function for the module. Same as + * {@link angular.Module#methods_config Module#config()}. + * @returns {module} new module with the {@link angular.Module} api. + */ + return function module(name, requires, configFn) { + var assertNotHasOwnProperty = function(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); + } + }; + + assertNotHasOwnProperty(name, 'module'); + if (requires && modules.hasOwnProperty(name)) { + modules[name] = null; + } + return ensure(modules, name, function() { + if (!requires) { + throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + + "the module name or forgot to load it. If registering a module ensure that you " + + "specify the dependencies as the second argument.", name); + } + + /** @type {!Array.>} */ + var invokeQueue = []; + + /** @type {!Array.} */ + var runBlocks = []; + + var config = invokeLater('$injector', 'invoke'); + + /** @type {angular.Module} */ + var moduleInstance = { + // Private state + _invokeQueue: invokeQueue, + _runBlocks: runBlocks, + + /** + * @ngdoc property + * @name angular.Module#requires + * @propertyOf angular.Module + * @returns {Array.} List of module names which must be loaded before this module. + * @description + * Holds the list of modules which the injector will load before the current module is + * loaded. + */ + requires: requires, + + /** + * @ngdoc property + * @name angular.Module#name + * @propertyOf angular.Module + * @returns {string} Name of the module. + * @description + */ + name: name, + + + /** + * @ngdoc method + * @name angular.Module#provider + * @methodOf angular.Module + * @param {string} name service name + * @param {Function} providerType Construction function for creating new instance of the + * service. + * @description + * See {@link AUTO.$provide#provider $provide.provider()}. + */ + provider: invokeLater('$provide', 'provider'), + + /** + * @ngdoc method + * @name angular.Module#factory + * @methodOf angular.Module + * @param {string} name service name + * @param {Function} providerFunction Function for creating new instance of the service. + * @description + * See {@link AUTO.$provide#factory $provide.factory()}. + */ + factory: invokeLater('$provide', 'factory'), + + /** + * @ngdoc method + * @name angular.Module#service + * @methodOf angular.Module + * @param {string} name service name + * @param {Function} constructor A constructor function that will be instantiated. + * @description + * See {@link AUTO.$provide#service $provide.service()}. + */ + service: invokeLater('$provide', 'service'), + + /** + * @ngdoc method + * @name angular.Module#value + * @methodOf angular.Module + * @param {string} name service name + * @param {*} object Service instance object. + * @description + * See {@link AUTO.$provide#value $provide.value()}. + */ + value: invokeLater('$provide', 'value'), + + /** + * @ngdoc method + * @name angular.Module#constant + * @methodOf angular.Module + * @param {string} name constant name + * @param {*} object Constant value. + * @description + * Because the constant are fixed, they get applied before other provide methods. + * See {@link AUTO.$provide#constant $provide.constant()}. + */ + constant: invokeLater('$provide', 'constant', 'unshift'), + + /** + * @ngdoc method + * @name angular.Module#animation + * @methodOf angular.Module + * @param {string} name animation name + * @param {Function} animationFactory Factory function for creating new instance of an + * animation. + * @description + * + * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. + * + * + * Defines an animation hook that can be later used with + * {@link ngAnimate.$animate $animate} service and directives that use this service. + * + *
+           * module.animation('.animation-name', function($inject1, $inject2) {
+           *   return {
+           *     eventName : function(element, done) {
+           *       //code to run the animation
+           *       //once complete, then run done()
+           *       return function cancellationFunction(element) {
+           *         //code to cancel the animation
+           *       }
+           *     }
+           *   }
+           * })
+           * 
+ * + * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and + * {@link ngAnimate ngAnimate module} for more information. + */ + animation: invokeLater('$animateProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#filter + * @methodOf angular.Module + * @param {string} name Filter name. + * @param {Function} filterFactory Factory function for creating new instance of filter. + * @description + * See {@link ng.$filterProvider#register $filterProvider.register()}. + */ + filter: invokeLater('$filterProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#controller + * @methodOf angular.Module + * @param {string|Object} name Controller name, or an object map of controllers where the + * keys are the names and the values are the constructors. + * @param {Function} constructor Controller constructor function. + * @description + * See {@link ng.$controllerProvider#register $controllerProvider.register()}. + */ + controller: invokeLater('$controllerProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#directive + * @methodOf angular.Module + * @param {string|Object} name Directive name, or an object map of directives where the + * keys are the names and the values are the factories. + * @param {Function} directiveFactory Factory function for creating new instance of + * directives. + * @description + * See {@link ng.$compileProvider#methods_directive $compileProvider.directive()}. + */ + directive: invokeLater('$compileProvider', 'directive'), + + /** + * @ngdoc method + * @name angular.Module#config + * @methodOf angular.Module + * @param {Function} configFn Execute this function on module load. Useful for service + * configuration. + * @description + * Use this method to register work which needs to be performed on module loading. + */ + config: config, + + /** + * @ngdoc method + * @name angular.Module#run + * @methodOf angular.Module + * @param {Function} initializationFn Execute this function after injector creation. + * Useful for application initialization. + * @description + * Use this method to register work which should be performed when the injector is done + * loading all modules. + */ + run: function(block) { + runBlocks.push(block); + return this; + } + }; + + if (configFn) { + config(configFn); + } + + return moduleInstance; + + /** + * @param {string} provider + * @param {string} method + * @param {String=} insertMethod + * @returns {angular.Module} + */ + function invokeLater(provider, method, insertMethod) { + return function() { + invokeQueue[insertMethod || 'push']([provider, method, arguments]); + return moduleInstance; + }; + } + }); + }; + }); + +} + +setupModuleLoader(window); +})(window); + +/** + * Closure compiler type information + * + * @typedef { { + * requires: !Array., + * invokeQueue: !Array.>, + * + * service: function(string, Function):angular.Module, + * factory: function(string, Function):angular.Module, + * value: function(string, *):angular.Module, + * + * filter: function(string, Function):angular.Module, + * + * init: function(Function):angular.Module + * } } + */ +angular.Module; + diff --git a/app/vendor/angular/angular-loader.min.js b/app/vendor/angular/angular-loader.min.js new file mode 100644 index 00000000..33c58308 --- /dev/null +++ b/app/vendor/angular/angular-loader.min.js @@ -0,0 +1,9 @@ +/* + AngularJS v1.2.3 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(){'use strict';function d(a){return function(){var c=arguments[0],b,c="["+(a?a+":":"")+c+"] http://errors.angularjs.org/1.2.3/"+(a?a+"/":"")+c;for(b=1;b + * + * See {@link ngResource.$resource `$resource`} for usage. + */ + +/** + * @ngdoc object + * @name ngResource.$resource + * @requires $http + * + * @description + * A factory which creates a resource object that lets you interact with + * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. + * + * The returned resource object has action methods which provide high-level behaviors without + * the need to interact with the low level {@link ng.$http $http} service. + * + * Requires the {@link ngResource `ngResource`} module to be installed. + * + * @param {string} url A parametrized URL template with parameters prefixed by `:` as in + * `/user/:username`. If you are using a URL with a port number (e.g. + * `http://example.com:8080/api`), it will be respected. + * + * If you are using a url with a suffix, just add the suffix, like this: + * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')` + * or even `$resource('http://example.com/resource/:resource_id.:format')` + * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be + * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you + * can escape it with `/\.`. + * + * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in + * `actions` methods. If any of the parameter value is a function, it will be executed every time + * when a param value needs to be obtained for a request (unless the param was overridden). + * + * Each key value in the parameter object is first bound to url template if present and then any + * excess keys are appended to the url search query after the `?`. + * + * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in + * URL `/path/greet?salutation=Hello`. + * + * If the parameter value is prefixed with `@` then the value of that parameter is extracted from + * the data object (useful for non-GET operations). + * + * @param {Object.=} actions Hash with declaration of custom action that should extend the + * default set of resource actions. The declaration should be created in the format of {@link + * ng.$http#usage_parameters $http.config}: + * + * {action1: {method:?, params:?, isArray:?, headers:?, ...}, + * action2: {method:?, params:?, isArray:?, headers:?, ...}, + * ...} + * + * Where: + * + * - **`action`** – {string} – The name of action. This name becomes the name of the method on + * your resource object. + * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, + * `DELETE`, and `JSONP`. + * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of + * the parameter value is a function, it will be executed every time when a param value needs to + * be obtained for a request (unless the param was overridden). + * - **`url`** – {string} – action specific `url` override. The url templating is supported just + * like for the resource-level urls. + * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, + * see `returns` section. + * - **`transformRequest`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * - **`transformResponse`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body and headers and returns its transformed (typically deserialized) version. + * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that + * should abort the request when resolved. + * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 + * requests with credentials} for more information. + * - **`responseType`** - `{string}` - see {@link + * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. + * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods - + * `response` and `responseError`. Both `response` and `responseError` interceptors get called + * with `http response` object. See {@link ng.$http $http interceptors}. + * + * @returns {Object} A resource "class" object with methods for the default set of resource actions + * optionally extended with custom `actions`. The default set contains these actions: + * + * { 'get': {method:'GET'}, + * 'save': {method:'POST'}, + * 'query': {method:'GET', isArray:true}, + * 'remove': {method:'DELETE'}, + * 'delete': {method:'DELETE'} }; + * + * Calling these methods invoke an {@link ng.$http} with the specified http method, + * destination and parameters. When the data is returned from the server then the object is an + * instance of the resource class. The actions `save`, `remove` and `delete` are available on it + * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, + * read, update, delete) on server-side data like this: + *
+        var User = $resource('/user/:userId', {userId:'@id'});
+        var user = User.get({userId:123}, function() {
+          user.abc = true;
+          user.$save();
+        });
+     
+ * + * It is important to realize that invoking a $resource object method immediately returns an + * empty reference (object or array depending on `isArray`). Once the data is returned from the + * server the existing reference is populated with the actual data. This is a useful trick since + * usually the resource is assigned to a model which is then rendered by the view. Having an empty + * object results in no rendering, once the data arrives from the server then the object is + * populated with the data and the view automatically re-renders itself showing the new data. This + * means that in most cases one never has to write a callback function for the action methods. + * + * The action methods on the class object or instance object can be invoked with the following + * parameters: + * + * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` + * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` + * - non-GET instance actions: `instance.$action([parameters], [success], [error])` + * + * Success callback is called with (value, responseHeaders) arguments. Error callback is called + * with (httpResponse) argument. + * + * Class actions return empty instance (with additional properties below). + * Instance actions return promise of the action. + * + * The Resource instances and collection have these additional properties: + * + * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this + * instance or collection. + * + * On success, the promise is resolved with the same resource instance or collection object, + * updated with data from server. This makes it easy to use in + * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view + * rendering until the resource(s) are loaded. + * + * On failure, the promise is resolved with the {@link ng.$http http response} object, without + * the `resource` property. + * + * - `$resolved`: `true` after first server interaction is completed (either with success or + * rejection), `false` before that. Knowing if the Resource has been resolved is useful in + * data-binding. + * + * @example + * + * # Credit card resource + * + *
+     // Define CreditCard class
+     var CreditCard = $resource('/user/:userId/card/:cardId',
+      {userId:123, cardId:'@id'}, {
+       charge: {method:'POST', params:{charge:true}}
+      });
+
+     // We can retrieve a collection from the server
+     var cards = CreditCard.query(function() {
+       // GET: /user/123/card
+       // server returns: [ {id:456, number:'1234', name:'Smith'} ];
+
+       var card = cards[0];
+       // each item is an instance of CreditCard
+       expect(card instanceof CreditCard).toEqual(true);
+       card.name = "J. Smith";
+       // non GET methods are mapped onto the instances
+       card.$save();
+       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
+       // server returns: {id:456, number:'1234', name: 'J. Smith'};
+
+       // our custom method is mapped as well.
+       card.$charge({amount:9.99});
+       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
+     });
+
+     // we can create an instance as well
+     var newCard = new CreditCard({number:'0123'});
+     newCard.name = "Mike Smith";
+     newCard.$save();
+     // POST: /user/123/card {number:'0123', name:'Mike Smith'}
+     // server returns: {id:789, number:'01234', name: 'Mike Smith'};
+     expect(newCard.id).toEqual(789);
+ * 
+ * + * The object returned from this function execution is a resource "class" which has "static" method + * for each action in the definition. + * + * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and + * `headers`. + * When the data is returned from the server then the object is an instance of the resource type and + * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD + * operations (create, read, update, delete) on server-side data. + +
+     var User = $resource('/user/:userId', {userId:'@id'});
+     var user = User.get({userId:123}, function() {
+       user.abc = true;
+       user.$save();
+     });
+   
+ * + * It's worth noting that the success callback for `get`, `query` and other methods gets passed + * in the response that came from the server as well as $http header getter function, so one + * could rewrite the above example and get access to http headers as: + * +
+     var User = $resource('/user/:userId', {userId:'@id'});
+     User.get({userId:123}, function(u, getResponseHeaders){
+       u.abc = true;
+       u.$save(function(u, putResponseHeaders) {
+         //u => saved user object
+         //putResponseHeaders => $http header getter
+       });
+     });
+   
+ */ +angular.module('ngResource', ['ng']). + factory('$resource', ['$http', '$q', function($http, $q) { + + var DEFAULT_ACTIONS = { + 'get': {method:'GET'}, + 'save': {method:'POST'}, + 'query': {method:'GET', isArray:true}, + 'remove': {method:'DELETE'}, + 'delete': {method:'DELETE'} + }; + var noop = angular.noop, + forEach = angular.forEach, + extend = angular.extend, + copy = angular.copy, + isFunction = angular.isFunction; + + /** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path + * segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); + } + + + /** + * This method is intended for encoding *key* or *value* parts of query component. We need a + * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't + * have to be encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); + } + + function Route(template, defaults) { + this.template = template; + this.defaults = defaults || {}; + this.urlParams = {}; + } + + Route.prototype = { + setUrlParams: function(config, params, actionUrl) { + var self = this, + url = actionUrl || self.template, + val, + encodedVal; + + var urlParams = self.urlParams = {}; + forEach(url.split(/\W/), function(param){ + if (param === 'hasOwnProperty') { + throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); + } + if (!(new RegExp("^\\d+$").test(param)) && param && + (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { + urlParams[param] = true; + } + }); + url = url.replace(/\\:/g, ':'); + + params = params || {}; + forEach(self.urlParams, function(_, urlParam){ + val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; + if (angular.isDefined(val) && val !== null) { + encodedVal = encodeUriSegment(val); + url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1"); + } else { + url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, + leadingSlashes, tail) { + if (tail.charAt(0) == '/') { + return tail; + } else { + return leadingSlashes + tail; + } + }); + } + }); + + // strip trailing slashes and set the url + url = url.replace(/\/+$/, ''); + // then replace collapse `/.` if found in the last URL path segment before the query + // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` + url = url.replace(/\/\.(?=\w+($|\?))/, '.'); + // replace escaped `/\.` with `/.` + config.url = url.replace(/\/\\\./, '/.'); + + + // set params - delegate param encoding to $http + forEach(params, function(value, key){ + if (!self.urlParams[key]) { + config.params = config.params || {}; + config.params[key] = value; + } + }); + } + }; + + + function resourceFactory(url, paramDefaults, actions) { + var route = new Route(url); + + actions = extend({}, DEFAULT_ACTIONS, actions); + + function extractParams(data, actionParams){ + var ids = {}; + actionParams = extend({}, paramDefaults, actionParams); + forEach(actionParams, function(value, key){ + if (isFunction(value)) { value = value(); } + ids[key] = value && value.charAt && value.charAt(0) == '@' ? + lookupDottedPath(data, value.substr(1)) : value; + }); + return ids; + } + + function defaultResponseInterceptor(response) { + return response.resource; + } + + function Resource(value){ + copy(value || {}, this); + } + + forEach(actions, function(action, name) { + var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); + + Resource[name] = function(a1, a2, a3, a4) { + var params = {}, data, success, error; + + /* jshint -W086 */ /* (purposefully fall through case statements) */ + switch(arguments.length) { + case 4: + error = a4; + success = a3; + //fallthrough + case 3: + case 2: + if (isFunction(a2)) { + if (isFunction(a1)) { + success = a1; + error = a2; + break; + } + + success = a2; + error = a3; + //fallthrough + } else { + params = a1; + data = a2; + success = a3; + break; + } + case 1: + if (isFunction(a1)) success = a1; + else if (hasBody) data = a1; + else params = a1; + break; + case 0: break; + default: + throw $resourceMinErr('badargs', + "Expected up to 4 arguments [params, data, success, error], got {0} arguments", + arguments.length); + } + /* jshint +W086 */ /* (purposefully fall through case statements) */ + + var isInstanceCall = this instanceof Resource; + var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); + var httpConfig = {}; + var responseInterceptor = action.interceptor && action.interceptor.response || + defaultResponseInterceptor; + var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || + undefined; + + forEach(action, function(value, key) { + if (key != 'params' && key != 'isArray' && key != 'interceptor') { + httpConfig[key] = copy(value); + } + }); + + if (hasBody) httpConfig.data = data; + route.setUrlParams(httpConfig, + extend({}, extractParams(data, action.params || {}), params), + action.url); + + var promise = $http(httpConfig).then(function(response) { + var data = response.data, + promise = value.$promise; + + if (data) { + // Need to convert action.isArray to boolean in case it is undefined + // jshint -W018 + if ( angular.isArray(data) !== (!!action.isArray) ) { + throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' + + 'response to contain an {0} but got an {1}', + action.isArray?'array':'object', angular.isArray(data)?'array':'object'); + } + // jshint +W018 + if (action.isArray) { + value.length = 0; + forEach(data, function(item) { + value.push(new Resource(item)); + }); + } else { + copy(data, value); + value.$promise = promise; + } + } + + value.$resolved = true; + + response.resource = value; + + return response; + }, function(response) { + value.$resolved = true; + + (error||noop)(response); + + return $q.reject(response); + }); + + promise = promise.then( + function(response) { + var value = responseInterceptor(response); + (success||noop)(value, response.headers); + return value; + }, + responseErrorInterceptor); + + if (!isInstanceCall) { + // we are creating instance / collection + // - set the initial promise + // - return the instance / collection + value.$promise = promise; + value.$resolved = false; + + return value; + } + + // instance call + return promise; + }; + + + Resource.prototype['$' + name] = function(params, success, error) { + if (isFunction(params)) { + error = success; success = params; params = {}; + } + var result = Resource[name].call(this, params, this, success, error); + return result.$promise || result; + }; + }); + + Resource.bind = function(additionalParamDefaults){ + return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); + }; + + return Resource; + } + + return resourceFactory; + }]); + + +})(window, window.angular); diff --git a/app/vendor/angular/angular-resource.min.js b/app/vendor/angular/angular-resource.min.js new file mode 100644 index 00000000..728aee8f --- /dev/null +++ b/app/vendor/angular/angular-resource.min.js @@ -0,0 +1,12 @@ +/* + AngularJS v1.2.3 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(H,f,z){'use strict';var u=f.$$minErr("$resource"),A=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;f.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(D,E){function n(f,h){this.template=f;this.defaults=h||{};this.urlParams={}}function v(m,h,k){function r(d,c){var e={};c=w({},h,c);s(c,function(a,c){t(a)&&(a=a());var g;if(a&&a.charAt&&"@"==a.charAt(0)){g=d;var b=a.substr(1);if(null==b||""===b||"hasOwnProperty"===b||!A.test("."+b))throw u("badmember",b);for(var b=b.split("."),f=0,h= +b.length;f + */ + /* global -ngRouteModule */ +var ngRouteModule = angular.module('ngRoute', ['ng']). + provider('$route', $RouteProvider); + +/** + * @ngdoc object + * @name ngRoute.$routeProvider + * @function + * + * @description + * + * Used for configuring routes. + * + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. + * + * ## Dependencies + * Requires the {@link ngRoute `ngRoute`} module to be installed. + */ +function $RouteProvider(){ + function inherit(parent, extra) { + return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra); + } + + var routes = {}; + + /** + * @ngdoc method + * @name ngRoute.$routeProvider#when + * @methodOf ngRoute.$routeProvider + * + * @param {string} path Route path (matched against `$location.path`). If `$location.path` + * contains redundant trailing slash or is missing one, the route will still match and the + * `$location.path` will be updated to add or drop the trailing slash to exactly match the + * route definition. + * + * * `path` can contain named groups starting with a colon (`:name`). All characters up + * to the next slash are matched and stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain named groups starting with a colon and ending with a star (`:name*`). + * All characters are eagerly stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain optional named groups with a question mark (`:name?`). + * + * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match + * `/color/brown/largecode/code/with/slashs/edit` and extract: + * + * * `color: brown` + * * `largecode: code/with/slashs`. + * + * + * @param {Object} route Mapping information to be assigned to `$route.current` on route + * match. + * + * Object properties: + * + * - `controller` – `{(string|function()=}` – Controller fn that should be associated with + * newly created scope or the name of a {@link angular.Module#controller registered + * controller} if passed as a string. + * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be + * published to scope under the `controllerAs` name. + * - `template` – `{string=|function()=}` – html template as a string or a function that + * returns an html template as a string which should be used by {@link + * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives. + * This property takes precedence over `templateUrl`. + * + * If `template` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html + * template that should be used by {@link ngRoute.directive:ngView ngView}. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `resolve` - `{Object.=}` - An optional map of dependencies which should + * be injected into the controller. If any of these dependencies are promises, the router + * will wait for them all to be resolved or one to be rejected before the controller is + * instantiated. + * If all the promises are resolved successfully, the values of the resolved promises are + * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is + * fired. If any of the promises are rejected the + * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object + * is: + * + * - `key` – `{string}`: a name of a dependency to be injected into the controller. + * - `factory` - `{string|function}`: If `string` then it is an alias for a service. + * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected} + * and the return value is treated as the dependency. If the result is a promise, it is + * resolved before its value is injected into the controller. Be aware that + * `ngRoute.$routeParams` will still refer to the previous route within these resolve + * functions. Use `$route.current.params` to access the new route parameters, instead. + * + * - `redirectTo` – {(string|function())=} – value to update + * {@link ng.$location $location} path with and trigger route redirection. + * + * If `redirectTo` is a function, it will be called with the following parameters: + * + * - `{Object.}` - route parameters extracted from the current + * `$location.path()` by applying the current route templateUrl. + * - `{string}` - current `$location.path()` + * - `{Object}` - current `$location.search()` + * + * The custom `redirectTo` function is expected to return a string which will be used + * to update `$location.path()` and `$location.search()`. + * + * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()` + * or `$location.hash()` changes. + * + * If the option is set to `false` and url in the browser changes, then + * `$routeUpdate` event is broadcasted on the root scope. + * + * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive + * + * If the option is set to `true`, then the particular route can be matched without being + * case sensitive + * + * @returns {Object} self + * + * @description + * Adds a new route definition to the `$route` service. + */ + this.when = function(path, route) { + routes[path] = angular.extend( + {reloadOnSearch: true}, + route, + path && pathRegExp(path, route) + ); + + // create redirection for trailing slashes + if (path) { + var redirectPath = (path[path.length-1] == '/') + ? path.substr(0, path.length-1) + : path +'/'; + + routes[redirectPath] = angular.extend( + {redirectTo: path}, + pathRegExp(redirectPath, route) + ); + } + + return this; + }; + + /** + * @param path {string} path + * @param opts {Object} options + * @return {?Object} + * + * @description + * Normalizes the given path, returning a regular expression + * and the original path. + * + * Inspired by pathRexp in visionmedia/express/lib/utils.js. + */ + function pathRegExp(path, opts) { + var insensitive = opts.caseInsensitiveMatch, + ret = { + originalPath: path, + regexp: path + }, + keys = ret.keys = []; + + path = path + .replace(/([().])/g, '\\$1') + .replace(/(\/)?:(\w+)([\?|\*])?/g, function(_, slash, key, option){ + var optional = option === '?' ? option : null; + var star = option === '*' ? option : null; + keys.push({ name: key, optional: !!optional }); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (star && '(.+?)' || '([^/]+)') + + (optional || '') + + ')' + + (optional || ''); + }) + .replace(/([\/$\*])/g, '\\$1'); + + ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : ''); + return ret; + } + + /** + * @ngdoc method + * @name ngRoute.$routeProvider#otherwise + * @methodOf ngRoute.$routeProvider + * + * @description + * Sets route definition that will be used on route change when no other route definition + * is matched. + * + * @param {Object} params Mapping information to be assigned to `$route.current`. + * @returns {Object} self + */ + this.otherwise = function(params) { + this.when(null, params); + return this; + }; + + + this.$get = ['$rootScope', + '$location', + '$routeParams', + '$q', + '$injector', + '$http', + '$templateCache', + '$sce', + function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) { + + /** + * @ngdoc object + * @name ngRoute.$route + * @requires $location + * @requires $routeParams + * + * @property {Object} current Reference to the current route definition. + * The route definition contains: + * + * - `controller`: The controller constructor as define in route definition. + * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for + * controller instantiation. The `locals` contain + * the resolved values of the `resolve` map. Additionally the `locals` also contain: + * + * - `$scope` - The current route scope. + * - `$template` - The current route template HTML. + * + * @property {Array.} routes Array of all configured routes. + * + * @description + * `$route` is used for deep-linking URLs to controllers and views (HTML partials). + * It watches `$location.url()` and tries to map the path to an existing route definition. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API. + * + * The `$route` service is typically used in conjunction with the + * {@link ngRoute.directive:ngView `ngView`} directive and the + * {@link ngRoute.$routeParams `$routeParams`} service. + * + * @example + This example shows how changing the URL hash causes the `$route` to match a route against the + URL, and the `ngView` pulls in the partial. + + Note that this example is using {@link ng.directive:script inlined templates} + to get it working on jsfiddle as well. + + + +
+ Choose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4 | + Scarlet Letter
+ +
+
+ +
$location.path() = {{$location.path()}}
+
$route.current.templateUrl = {{$route.current.templateUrl}}
+
$route.current.params = {{$route.current.params}}
+
$route.current.scope.name = {{$route.current.scope.name}}
+
$routeParams = {{$routeParams}}
+
+
+ + + controller: {{name}}
+ Book Id: {{params.bookId}}
+
+ + + controller: {{name}}
+ Book Id: {{params.bookId}}
+ Chapter Id: {{params.chapterId}} +
+ + + angular.module('ngViewExample', ['ngRoute']) + + .config(function($routeProvider, $locationProvider) { + $routeProvider.when('/Book/:bookId', { + templateUrl: 'book.html', + controller: BookCntl, + resolve: { + // I will cause a 1 second delay + delay: function($q, $timeout) { + var delay = $q.defer(); + $timeout(delay.resolve, 1000); + return delay.promise; + } + } + }); + $routeProvider.when('/Book/:bookId/ch/:chapterId', { + templateUrl: 'chapter.html', + controller: ChapterCntl + }); + + // configure html5 to get links working on jsfiddle + $locationProvider.html5Mode(true); + }); + + function MainCntl($scope, $route, $routeParams, $location) { + $scope.$route = $route; + $scope.$location = $location; + $scope.$routeParams = $routeParams; + } + + function BookCntl($scope, $routeParams) { + $scope.name = "BookCntl"; + $scope.params = $routeParams; + } + + function ChapterCntl($scope, $routeParams) { + $scope.name = "ChapterCntl"; + $scope.params = $routeParams; + } + + + + it('should load and compile correct template', function() { + element('a:contains("Moby: Ch1")').click(); + var content = element('.doc-example-live [ng-view]').text(); + expect(content).toMatch(/controller\: ChapterCntl/); + expect(content).toMatch(/Book Id\: Moby/); + expect(content).toMatch(/Chapter Id\: 1/); + + element('a:contains("Scarlet")').click(); + sleep(2); // promises are not part of scenario waiting + content = element('.doc-example-live [ng-view]').text(); + expect(content).toMatch(/controller\: BookCntl/); + expect(content).toMatch(/Book Id\: Scarlet/); + }); + +
+ */ + + /** + * @ngdoc event + * @name ngRoute.$route#$routeChangeStart + * @eventOf ngRoute.$route + * @eventType broadcast on root scope + * @description + * Broadcasted before a route change. At this point the route services starts + * resolving all of the dependencies needed for the route change to occurs. + * Typically this involves fetching the view template as well as any dependencies + * defined in `resolve` route property. Once all of the dependencies are resolved + * `$routeChangeSuccess` is fired. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} next Future route information. + * @param {Route} current Current route information. + */ + + /** + * @ngdoc event + * @name ngRoute.$route#$routeChangeSuccess + * @eventOf ngRoute.$route + * @eventType broadcast on root scope + * @description + * Broadcasted after a route dependencies are resolved. + * {@link ngRoute.directive:ngView ngView} listens for the directive + * to instantiate the controller and render the view. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} current Current route information. + * @param {Route|Undefined} previous Previous route information, or undefined if current is + * first route entered. + */ + + /** + * @ngdoc event + * @name ngRoute.$route#$routeChangeError + * @eventOf ngRoute.$route + * @eventType broadcast on root scope + * @description + * Broadcasted if any of the resolve promises are rejected. + * + * @param {Object} angularEvent Synthetic event object + * @param {Route} current Current route information. + * @param {Route} previous Previous route information. + * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. + */ + + /** + * @ngdoc event + * @name ngRoute.$route#$routeUpdate + * @eventOf ngRoute.$route + * @eventType broadcast on root scope + * @description + * + * The `reloadOnSearch` property has been set to false, and we are reusing the same + * instance of the Controller. + */ + + var forceReload = false, + $route = { + routes: routes, + + /** + * @ngdoc method + * @name ngRoute.$route#reload + * @methodOf ngRoute.$route + * + * @description + * Causes `$route` service to reload the current route even if + * {@link ng.$location $location} hasn't changed. + * + * As a result of that, {@link ngRoute.directive:ngView ngView} + * creates new scope, reinstantiates the controller. + */ + reload: function() { + forceReload = true; + $rootScope.$evalAsync(updateRoute); + } + }; + + $rootScope.$on('$locationChangeSuccess', updateRoute); + + return $route; + + ///////////////////////////////////////////////////// + + /** + * @param on {string} current url + * @param route {Object} route regexp to match the url against + * @return {?Object} + * + * @description + * Check if the route matches the current url. + * + * Inspired by match in + * visionmedia/express/lib/router/router.js. + */ + function switchRouteMatcher(on, route) { + var keys = route.keys, + params = {}; + + if (!route.regexp) return null; + + var m = route.regexp.exec(on); + if (!m) return null; + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + + var val = 'string' == typeof m[i] + ? decodeURIComponent(m[i]) + : m[i]; + + if (key && val) { + params[key.name] = val; + } + } + return params; + } + + function updateRoute() { + var next = parseRoute(), + last = $route.current; + + if (next && last && next.$$route === last.$$route + && angular.equals(next.pathParams, last.pathParams) + && !next.reloadOnSearch && !forceReload) { + last.params = next.params; + angular.copy(last.params, $routeParams); + $rootScope.$broadcast('$routeUpdate', last); + } else if (next || last) { + forceReload = false; + $rootScope.$broadcast('$routeChangeStart', next, last); + $route.current = next; + if (next) { + if (next.redirectTo) { + if (angular.isString(next.redirectTo)) { + $location.path(interpolate(next.redirectTo, next.params)).search(next.params) + .replace(); + } else { + $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search())) + .replace(); + } + } + } + + $q.when(next). + then(function() { + if (next) { + var locals = angular.extend({}, next.resolve), + template, templateUrl; + + angular.forEach(locals, function(value, key) { + locals[key] = angular.isString(value) ? + $injector.get(value) : $injector.invoke(value); + }); + + if (angular.isDefined(template = next.template)) { + if (angular.isFunction(template)) { + template = template(next.params); + } + } else if (angular.isDefined(templateUrl = next.templateUrl)) { + if (angular.isFunction(templateUrl)) { + templateUrl = templateUrl(next.params); + } + templateUrl = $sce.getTrustedResourceUrl(templateUrl); + if (angular.isDefined(templateUrl)) { + next.loadedTemplateUrl = templateUrl; + template = $http.get(templateUrl, {cache: $templateCache}). + then(function(response) { return response.data; }); + } + } + if (angular.isDefined(template)) { + locals['$template'] = template; + } + return $q.all(locals); + } + }). + // after route change + then(function(locals) { + if (next == $route.current) { + if (next) { + next.locals = locals; + angular.copy(next.params, $routeParams); + } + $rootScope.$broadcast('$routeChangeSuccess', next, last); + } + }, function(error) { + if (next == $route.current) { + $rootScope.$broadcast('$routeChangeError', next, last, error); + } + }); + } + } + + + /** + * @returns the current active route, by matching it against the URL + */ + function parseRoute() { + // Match a route + var params, match; + angular.forEach(routes, function(route, path) { + if (!match && (params = switchRouteMatcher($location.path(), route))) { + match = inherit(route, { + params: angular.extend({}, $location.search(), params), + pathParams: params}); + match.$$route = route; + } + }); + // No route matched; fallback to "otherwise" route + return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); + } + + /** + * @returns interpolation of the redirect path with the parameters + */ + function interpolate(string, params) { + var result = []; + angular.forEach((string||'').split(':'), function(segment, i) { + if (i === 0) { + result.push(segment); + } else { + var segmentMatch = segment.match(/(\w+)(.*)/); + var key = segmentMatch[1]; + result.push(params[key]); + result.push(segmentMatch[2] || ''); + delete params[key]; + } + }); + return result.join(''); + } + }]; +} + +ngRouteModule.provider('$routeParams', $RouteParamsProvider); + + +/** + * @ngdoc object + * @name ngRoute.$routeParams + * @requires $route + * + * @description + * The `$routeParams` service allows you to retrieve the current set of route parameters. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * The route parameters are a combination of {@link ng.$location `$location`}'s + * {@link ng.$location#methods_search `search()`} and {@link ng.$location#methods_path `path()`}. + * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched. + * + * In case of parameter name collision, `path` params take precedence over `search` params. + * + * The service guarantees that the identity of the `$routeParams` object will remain unchanged + * (but its properties will likely change) even when a route change occurs. + * + * Note that the `$routeParams` are only updated *after* a route change completes successfully. + * This means that you cannot rely on `$routeParams` being correct in route resolve functions. + * Instead you can use `$route.current.params` to access the new route's parameters. + * + * @example + *
+ *  // Given:
+ *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
+ *  // Route: /Chapter/:chapterId/Section/:sectionId
+ *  //
+ *  // Then
+ *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
+ * 
+ */ +function $RouteParamsProvider() { + this.$get = function() { return {}; }; +} + +ngRouteModule.directive('ngView', ngViewFactory); + +/** + * @ngdoc directive + * @name ngRoute.directive:ngView + * @restrict ECA + * + * @description + * # Overview + * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by + * including the rendered template of the current route into the main layout (`index.html`) file. + * Every time the current route changes, the included view changes with it according to the + * configuration of the `$route` service. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * @animations + * enter - animation is used to bring new content into the browser. + * leave - animation is used to animate existing content away. + * + * The enter and leave animation occur concurrently. + * + * @scope + * @priority 400 + * @example + + +
+ Choose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4 | + Scarlet Letter
+ +
+
+
+
+ +
$location.path() = {{main.$location.path()}}
+
$route.current.templateUrl = {{main.$route.current.templateUrl}}
+
$route.current.params = {{main.$route.current.params}}
+
$route.current.scope.name = {{main.$route.current.scope.name}}
+
$routeParams = {{main.$routeParams}}
+
+
+ + +
+ controller: {{book.name}}
+ Book Id: {{book.params.bookId}}
+
+
+ + +
+ controller: {{chapter.name}}
+ Book Id: {{chapter.params.bookId}}
+ Chapter Id: {{chapter.params.chapterId}} +
+
+ + + .view-animate-container { + position:relative; + height:100px!important; + position:relative; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .view-animate { + padding:10px; + } + + .view-animate.ng-enter, .view-animate.ng-leave { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; + + display:block; + width:100%; + border-left:1px solid black; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + padding:10px; + } + + .view-animate.ng-enter { + left:100%; + } + .view-animate.ng-enter.ng-enter-active { + left:0; + } + .view-animate.ng-leave.ng-leave-active { + left:-100%; + } + + + + angular.module('ngViewExample', ['ngRoute', 'ngAnimate'], + function($routeProvider, $locationProvider) { + $routeProvider.when('/Book/:bookId', { + templateUrl: 'book.html', + controller: BookCntl, + controllerAs: 'book' + }); + $routeProvider.when('/Book/:bookId/ch/:chapterId', { + templateUrl: 'chapter.html', + controller: ChapterCntl, + controllerAs: 'chapter' + }); + + // configure html5 to get links working on jsfiddle + $locationProvider.html5Mode(true); + }); + + function MainCntl($route, $routeParams, $location) { + this.$route = $route; + this.$location = $location; + this.$routeParams = $routeParams; + } + + function BookCntl($routeParams) { + this.name = "BookCntl"; + this.params = $routeParams; + } + + function ChapterCntl($routeParams) { + this.name = "ChapterCntl"; + this.params = $routeParams; + } + + + + it('should load and compile correct template', function() { + element('a:contains("Moby: Ch1")').click(); + var content = element('.doc-example-live [ng-view]').text(); + expect(content).toMatch(/controller\: ChapterCntl/); + expect(content).toMatch(/Book Id\: Moby/); + expect(content).toMatch(/Chapter Id\: 1/); + + element('a:contains("Scarlet")').click(); + content = element('.doc-example-live [ng-view]').text(); + expect(content).toMatch(/controller\: BookCntl/); + expect(content).toMatch(/Book Id\: Scarlet/); + }); + +
+ */ + + +/** + * @ngdoc event + * @name ngRoute.directive:ngView#$viewContentLoaded + * @eventOf ngRoute.directive:ngView + * @eventType emit on the current ngView scope + * @description + * Emitted every time the ngView content is reloaded. + */ +ngViewFactory.$inject = ['$route', '$anchorScroll', '$compile', '$controller', '$animate']; +function ngViewFactory( $route, $anchorScroll, $compile, $controller, $animate) { + return { + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + link: function(scope, $element, attr, ctrl, $transclude) { + var currentScope, + currentElement, + autoScrollExp = attr.autoscroll, + onloadExp = attr.onload || ''; + + scope.$on('$routeChangeSuccess', update); + update(); + + function cleanupLastView() { + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if(currentElement) { + $animate.leave(currentElement); + currentElement = null; + } + } + + function update() { + var locals = $route.current && $route.current.locals, + template = locals && locals.$template; + + if (template) { + var newScope = scope.$new(); + + // Note: This will also link all children of ng-view that were contained in the original + // html. If that content contains controllers, ... they could pollute/change the scope. + // However, using ng-view on an element with additional content does not make sense... + // Note: We can't remove them in the cloneAttchFn of $transclude as that + // function is called before linking the content, which would apply child + // directives to non existing elements. + var clone = $transclude(newScope, angular.noop); + clone.html(template); + $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () { + if (angular.isDefined(autoScrollExp) + && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }); + + cleanupLastView(); + + var link = $compile(clone.contents()), + current = $route.current; + + currentScope = current.scope = newScope; + currentElement = clone; + + if (current.controller) { + locals.$scope = currentScope; + var controller = $controller(current.controller, locals); + if (current.controllerAs) { + currentScope[current.controllerAs] = controller; + } + clone.data('$ngControllerController', controller); + clone.children().data('$ngControllerController', controller); + } + + link(currentScope); + currentScope.$emit('$viewContentLoaded'); + currentScope.$eval(onloadExp); + } else { + cleanupLastView(); + } + } + } + }; +} + + +})(window, window.angular); diff --git a/app/vendor/angular/angular-route.min.js b/app/vendor/angular/angular-route.min.js new file mode 100644 index 00000000..5870a6a8 --- /dev/null +++ b/app/vendor/angular/angular-route.min.js @@ -0,0 +1,14 @@ +/* + AngularJS v1.2.3 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(t,c,A){'use strict';function x(r,m,d,b,h){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(l,z,k,B,w){function v(){g&&(g.$destroy(),g=null);q&&(h.leave(q),q=null)}function u(){var a=r.current&&r.current.locals,e=a&&a.$template;if(e){var y=l.$new(),s=w(y,c.noop);s.html(e);h.enter(s,null,q||z,function(){!c.isDefined(n)||n&&!l.$eval(n)||m()});v();var e=d(s.contents()),f=r.current;g=f.scope=y;q=s;f.controller&&(a.$scope=g,a=b(f.controller,a),f.controllerAs&& +(g[f.controllerAs]=a),s.data("$ngControllerController",a),s.children().data("$ngControllerController",a));e(g);g.$emit("$viewContentLoaded");g.$eval(p)}else v()}var g,q,n=k.autoscroll,p=k.onload||"";l.$on("$routeChangeSuccess",u);u()}}}t=c.module("ngRoute",["ng"]).provider("$route",function(){function r(b,h){return c.extend(new (c.extend(function(){},{prototype:b})),h)}function m(b,c){var l=c.caseInsensitiveMatch,d={originalPath:b,regexp:b},k=d.keys=[];b=b.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g, +function(b,c,h,d){b="?"===d?d:null;d="*"===d?d:null;k.push({name:h,optional:!!b});c=c||"";return""+(b?"":c)+"(?:"+(b?c:"")+(d&&"(.+?)"||"([^/]+)")+(b||"")+")"+(b||"")}).replace(/([\/$\*])/g,"\\$1");d.regexp=RegExp("^"+b+"$",l?"i":"");return d}var d={};this.when=function(b,h){d[b]=c.extend({reloadOnSearch:!0},h,b&&m(b,h));if(b){var l="/"==b[b.length-1]?b.substr(0,b.length-1):b+"/";d[l]=c.extend({redirectTo:b},m(l,h))}return this};this.otherwise=function(b){this.when(null,b);return this};this.$get= +["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(b,h,l,m,k,t,w,v){function u(){var a=g(),e=p.current;if(a&&e&&a.$$route===e.$$route&&c.equals(a.pathParams,e.pathParams)&&!a.reloadOnSearch&&!n)e.params=a.params,c.copy(e.params,l),b.$broadcast("$routeUpdate",e);else if(a||e)n=!1,b.$broadcast("$routeChangeStart",a,e),(p.current=a)&&a.redirectTo&&(c.isString(a.redirectTo)?h.path(q(a.redirectTo,a.params)).search(a.params).replace():h.url(a.redirectTo(a.pathParams, +h.path(),h.search())).replace()),m.when(a).then(function(){if(a){var b=c.extend({},a.resolve),e,f;c.forEach(b,function(a,e){b[e]=c.isString(a)?k.get(a):k.invoke(a)});c.isDefined(e=a.template)?c.isFunction(e)&&(e=e(a.params)):c.isDefined(f=a.templateUrl)&&(c.isFunction(f)&&(f=f(a.params)),f=v.getTrustedResourceUrl(f),c.isDefined(f)&&(a.loadedTemplateUrl=f,e=t.get(f,{cache:w}).then(function(a){return a.data})));c.isDefined(e)&&(b.$template=e);return m.all(b)}}).then(function(d){a==p.current&&(a&&(a.locals= +d,c.copy(a.params,l)),b.$broadcast("$routeChangeSuccess",a,e))},function(c){a==p.current&&b.$broadcast("$routeChangeError",a,e,c)})}function g(){var a,b;c.forEach(d,function(d,l){var f;if(f=!b){var g=h.path();f=d.keys;var m={};if(d.regexp)if(g=d.regexp.exec(g)){for(var k=1,q=g.length;k + * + * See {@link ngSanitize.$sanitize `$sanitize`} for usage. + */ + +/* + * HTML Parser By Misko Hevery (misko@hevery.com) + * based on: HTML Parser By John Resig (ejohn.org) + * Original code by Erik Arvidsson, Mozilla Public License + * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js + * + * // Use like so: + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + */ + + +/** + * @ngdoc service + * @name ngSanitize.$sanitize + * @function + * + * @description + * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are + * then serialized back to properly escaped html string. This means that no unsafe input can make + * it into the returned string, however, since our parser is more strict than a typical browser + * parser, it's possible that some obscure input, which would be recognized as valid HTML by a + * browser, won't make it through the sanitizer. + * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and + * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. + * + * @param {string} html Html input. + * @returns {string} Sanitized html. + * + * @example + + + +
+ Snippet: + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html="snippet">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value +
<div ng-bind-html="deliberatelyTrustDangerousSnippet()">
+</div>
+
ng-bindAutomatically escapes
<div ng-bind="snippet">
</div>
+
+
+ + it('should sanitize the html snippet by default', function() { + expect(using('#bind-html-with-sanitize').element('div').html()). + toBe('

an html\nclick here\nsnippet

'); + }); + + it('should inline raw snippet if bound to a trusted value', function() { + expect(using('#bind-html-with-trust').element("div").html()). + toBe("

an html\n" + + "click here\n" + + "snippet

"); + }); + + it('should escape snippet without any filter', function() { + expect(using('#bind-default').element('div').html()). + toBe("<p style=\"color:blue\">an html\n" + + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + + "snippet</p>"); + }); + + it('should update', function() { + input('snippet').enter('new text'); + expect(using('#bind-html-with-sanitize').element('div').html()).toBe('new text'); + expect(using('#bind-html-with-trust').element('div').html()).toBe( + 'new text'); + expect(using('#bind-default').element('div').html()).toBe( + "new <b onclick=\"alert(1)\">text</b>"); + }); +
+
+ */ +function $SanitizeProvider() { + this.$get = ['$$sanitizeUri', function($$sanitizeUri) { + return function(html) { + var buf = []; + htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { + return !/^unsafe/.test($$sanitizeUri(uri, isImage)); + })); + return buf.join(''); + }; + }]; +} + +function sanitizeText(chars) { + var buf = []; + var writer = htmlSanitizeWriter(buf, angular.noop); + writer.chars(chars); + return buf.join(''); +} + + +// Regular Expressions for parsing tags and attributes +var START_TAG_REGEXP = + /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, + END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, + ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, + BEGIN_TAG_REGEXP = /^/g, + DOCTYPE_REGEXP = /]*?)>/i, + CDATA_REGEXP = //g, + // Match everything outside of normal chars and " (quote character) + NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; + + +// Good source of info about elements and attributes +// http://dev.w3.org/html5/spec/Overview.html#semantics +// http://simon.html5.org/html-elements + +// Safe Void Elements - HTML5 +// http://dev.w3.org/html5/spec/Overview.html#void-elements +var voidElements = makeMap("area,br,col,hr,img,wbr"); + +// Elements that you can, intentionally, leave open (and which close themselves) +// http://dev.w3.org/html5/spec/Overview.html#optional-tags +var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), + optionalEndTagInlineElements = makeMap("rp,rt"), + optionalEndTagElements = angular.extend({}, + optionalEndTagInlineElements, + optionalEndTagBlockElements); + +// Safe Block Elements - HTML5 +var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + + "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + + "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); + +// Inline Elements - HTML5 +var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + + "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + + "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); + + +// Special Elements (can contain anything) +var specialElements = makeMap("script,style"); + +var validElements = angular.extend({}, + voidElements, + blockElements, + inlineElements, + optionalEndTagElements); + +//Attributes that have href and hence need to be sanitized +var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); +var validAttrs = angular.extend({}, uriAttrs, makeMap( + 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ + 'scope,scrolling,shape,span,start,summary,target,title,type,'+ + 'valign,value,vspace,width')); + +function makeMap(str) { + var obj = {}, items = str.split(','), i; + for (i = 0; i < items.length; i++) obj[items[i]] = true; + return obj; +} + + +/** + * @example + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + * @param {string} html string + * @param {object} handler + */ +function htmlParser( html, handler ) { + var index, chars, match, stack = [], last = html; + stack.last = function() { return stack[ stack.length - 1 ]; }; + + while ( html ) { + chars = true; + + // Make sure we're not in a script or style element + if ( !stack.last() || !specialElements[ stack.last() ] ) { + + // Comment + if ( html.indexOf("", index) === index) { + if (handler.comment) handler.comment( html.substring( 4, index ) ); + html = html.substring( index + 3 ); + chars = false; + } + // DOCTYPE + } else if ( DOCTYPE_REGEXP.test(html) ) { + match = html.match( DOCTYPE_REGEXP ); + + if ( match ) { + html = html.replace( match[0] , ''); + chars = false; + } + // end tag + } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { + match = html.match( END_TAG_REGEXP ); + + if ( match ) { + html = html.substring( match[0].length ); + match[0].replace( END_TAG_REGEXP, parseEndTag ); + chars = false; + } + + // start tag + } else if ( BEGIN_TAG_REGEXP.test(html) ) { + match = html.match( START_TAG_REGEXP ); + + if ( match ) { + html = html.substring( match[0].length ); + match[0].replace( START_TAG_REGEXP, parseStartTag ); + chars = false; + } + } + + if ( chars ) { + index = html.indexOf("<"); + + var text = index < 0 ? html : html.substring( 0, index ); + html = index < 0 ? "" : html.substring( index ); + + if (handler.chars) handler.chars( decodeEntities(text) ); + } + + } else { + html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), + function(all, text){ + text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); + + if (handler.chars) handler.chars( decodeEntities(text) ); + + return ""; + }); + + parseEndTag( "", stack.last() ); + } + + if ( html == last ) { + throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + + "of html: {0}", html); + } + last = html; + } + + // Clean up any remaining tags + parseEndTag(); + + function parseStartTag( tag, tagName, rest, unary ) { + tagName = angular.lowercase(tagName); + if ( blockElements[ tagName ] ) { + while ( stack.last() && inlineElements[ stack.last() ] ) { + parseEndTag( "", stack.last() ); + } + } + + if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { + parseEndTag( "", tagName ); + } + + unary = voidElements[ tagName ] || !!unary; + + if ( !unary ) + stack.push( tagName ); + + var attrs = {}; + + rest.replace(ATTR_REGEXP, + function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { + var value = doubleQuotedValue + || singleQuotedValue + || unquotedValue + || ''; + + attrs[name] = decodeEntities(value); + }); + if (handler.start) handler.start( tagName, attrs, unary ); + } + + function parseEndTag( tag, tagName ) { + var pos = 0, i; + tagName = angular.lowercase(tagName); + if ( tagName ) + // Find the closest opened tag of the same type + for ( pos = stack.length - 1; pos >= 0; pos-- ) + if ( stack[ pos ] == tagName ) + break; + + if ( pos >= 0 ) { + // Close all the open elements, up the stack + for ( i = stack.length - 1; i >= pos; i-- ) + if (handler.end) handler.end( stack[ i ] ); + + // Remove the open elements from the stack + stack.length = pos; + } + } +} + +/** + * decodes all entities into regular string + * @param value + * @returns {string} A string with decoded entities. + */ +var hiddenPre=document.createElement("pre"); +function decodeEntities(value) { + if (!value) { + return ''; + } + // Note: IE8 does not preserve spaces at the start/end of innerHTML + var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; + var parts = spaceRe.exec(value); + parts[0] = ''; + if (parts[2]) { + hiddenPre.innerHTML=parts[2].replace(//g, '>'); +} + +/** + * create an HTML/XML writer which writes to buffer + * @param {Array} buf use buf.jain('') to get out sanitized html string + * @returns {object} in the form of { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * } + */ +function htmlSanitizeWriter(buf, uriValidator){ + var ignore = false; + var out = angular.bind(buf, buf.push); + return { + start: function(tag, attrs, unary){ + tag = angular.lowercase(tag); + if (!ignore && specialElements[tag]) { + ignore = tag; + } + if (!ignore && validElements[tag] === true) { + out('<'); + out(tag); + angular.forEach(attrs, function(value, key){ + var lkey=angular.lowercase(key); + var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); + if (validAttrs[lkey] === true && + (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { + out(' '); + out(key); + out('="'); + out(encodeEntities(value)); + out('"'); + } + }); + out(unary ? '/>' : '>'); + } + }, + end: function(tag){ + tag = angular.lowercase(tag); + if (!ignore && validElements[tag] === true) { + out(''); + } + if (tag == ignore) { + ignore = false; + } + }, + chars: function(chars){ + if (!ignore) { + out(encodeEntities(chars)); + } + } + }; +} + + +// define ngSanitize module and register $sanitize service +angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); + +/* global sanitizeText: false */ + +/** + * @ngdoc filter + * @name ngSanitize.filter:linky + * @function + * + * @description + * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and + * plain email address links. + * + * Requires the {@link ngSanitize `ngSanitize`} module to be installed. + * + * @param {string} text Input text. + * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. + * @returns {string} Html-linkified text. + * + * @usage + + * + * @example + + + +
+ Snippet: + + + + + + + + + + + + + + + + + + + + + +
FilterSourceRendered
linky filter +
<div ng-bind-html="snippet | linky">
</div>
+
+
+
linky target +
<div ng-bind-html="snippetWithTarget | linky:'_blank'">
</div>
+
+
+
no filter
<div ng-bind="snippet">
</div>
+ + + it('should linkify the snippet with urls', function() { + expect(using('#linky-filter').binding('snippet | linky')). + toBe('Pretty text with some links: ' + + 'http://angularjs.org/, ' + + 'us@somewhere.org, ' + + 'another@somewhere.org, ' + + 'and one more: ftp://127.0.0.1/.'); + }); + + it ('should not linkify snippet without the linky filter', function() { + expect(using('#escaped-html').binding('snippet')). + toBe("Pretty text with some links:\n" + + "http://angularjs.org/,\n" + + "mailto:us@somewhere.org,\n" + + "another@somewhere.org,\n" + + "and one more: ftp://127.0.0.1/."); + }); + + it('should update', function() { + input('snippet').enter('new http://link.'); + expect(using('#linky-filter').binding('snippet | linky')). + toBe('new http://link.'); + expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); + }); + + it('should work with the target property', function() { + expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")). + toBe('http://angularjs.org/'); + }); + + + */ +angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { + var LINKY_URL_REGEXP = + /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, + MAILTO_REGEXP = /^mailto:/; + + return function(text, target) { + if (!text) return text; + var match; + var raw = text; + var html = []; + var url; + var i; + while ((match = raw.match(LINKY_URL_REGEXP))) { + // We can not end in these as they are sometimes found at the end of the sentence + url = match[0]; + // if we did not match ftp/http/mailto then assume mailto + if (match[2] == match[3]) url = 'mailto:' + url; + i = match.index; + addText(raw.substr(0, i)); + addLink(url, match[0].replace(MAILTO_REGEXP, '')); + raw = raw.substring(i + match[0].length); + } + addText(raw); + return $sanitize(html.join('')); + + function addText(text) { + if (!text) { + return; + } + html.push(sanitizeText(text)); + } + + function addLink(url, text) { + html.push(''); + addText(text); + html.push(''); + } + }; +}]); + + +})(window, window.angular); diff --git a/app/vendor/angular/angular-sanitize.min.js b/app/vendor/angular/angular-sanitize.min.js new file mode 100644 index 00000000..ed3ec446 --- /dev/null +++ b/app/vendor/angular/angular-sanitize.min.js @@ -0,0 +1,14 @@ +/* + AngularJS v1.2.3 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(n,h,q){'use strict';function F(a){var e=[];t(e,h.noop).chars(a);return e.join("")}function k(a){var e={};a=a.split(",");var d;for(d=0;d=c;d--)e.end&&e.end(f[d]);f.length=c}}var b,g,f=[],l=a;for(f.last=function(){return f[f.length-1]};a;){g=!0;if(f.last()&&y[f.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(a,b){b=b.replace(I,"$1").replace(J,"$1");e.chars&&e.chars(r(b));return""}),c("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(e.comment&&e.comment(a.substring(4,b)),a=a.substring(b+3),g=!1);else if(z.test(a)){if(b=a.match(z))a= +a.replace(b[0],""),g=!1}else if(K.test(a)){if(b=a.match(A))a=a.substring(b[0].length),b[0].replace(A,c),g=!1}else L.test(a)&&(b=a.match(B))&&(a=a.substring(b[0].length),b[0].replace(B,d),g=!1);g&&(b=a.indexOf("<"),g=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),e.chars&&e.chars(r(g)))}if(a==l)throw M("badparse",a);l=a}c()}function r(a){if(!a)return"";a=/^(\s*)([\s\S]*?)(\s*)$/.exec(a);a[0]="";a[2]&&(s.innerHTML=a[2].replace(//g,">")}function t(a,e){var d=!1,c=h.bind(a,a.push);return{start:function(a,g,f){a=h.lowercase(a);!d&&y[a]&&(d=a);d||!0!==D[a]||(c("<"),c(a),h.forEach(g,function(d,f){var g=h.lowercase(f),k="img"===a&&"src"===g||"background"===g;!0!==O[g]||!0===E[g]&&!e(d,k)||(c(" "),c(f),c('="'),c(C(d)),c('"'))}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==D[a]||(c(""));a==d&&(d=!1)},chars:function(a){d|| +c(C(a))}}}var M=h.$$minErr("$sanitize"),B=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,A=/^<\s*\/\s*([\w:-]+)[^>]*>/,H=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,L=/^]*?)>/i,J=/]/,d=/^mailto:/;return function(c,b){function g(a){a&&m.push(F(a))}function f(a,c){m.push("');g(c);m.push("")}if(!c)return c;for(var l,k=c,m=[],p,n;l=k.match(e);)p=l[0],l[2]==l[3]&&(p="mailto:"+p),n=l.index,g(k.substr(0,n)),f(p,l[0].replace(d,"")),k=k.substring(n+l[0].length);g(k);return a(m.join(""))}}])})(window,window.angular); +//# sourceMappingURL=angular-sanitize.min.js.map diff --git a/app/vendor/angular/angular-sanitize.min.js.map b/app/vendor/angular/angular-sanitize.min.js.map new file mode 100644 index 00000000..f211e9a6 --- /dev/null +++ b/app/vendor/angular/angular-sanitize.min.js.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"angular-sanitize.min.js", +"lineCount":13, +"mappings":"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", +"sources":["angular-sanitize.js"], +"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","stack.last","specialElements","RegExp","all","text","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","parts","spaceRe","exec","hiddenPre","innerHTML","innerText","textContent","encodeEntities","NON_ALPHANUMERIC_REGEXP","charCodeAt","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"] +} diff --git a/app/vendor/angular/angular-touch.js b/app/vendor/angular/angular-touch.js new file mode 100644 index 00000000..cd45d0cf --- /dev/null +++ b/app/vendor/angular/angular-touch.js @@ -0,0 +1,563 @@ +/** + * @license AngularJS v1.2.3 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/** + * @ngdoc overview + * @name ngTouch + * @description + * + * # ngTouch + * + * The `ngTouch` module provides touch events and other helpers for touch-enabled devices. + * The implementation is based on jQuery Mobile touch event handling + * ([jquerymobile.com](http://jquerymobile.com/)). + * + * {@installModule touch} + * + * See {@link ngTouch.$swipe `$swipe`} for usage. + * + *
+ * + */ + +// define ngTouch module +/* global -ngTouch */ +var ngTouch = angular.module('ngTouch', []); + +/* global ngTouch: false */ + + /** + * @ngdoc object + * @name ngTouch.$swipe + * + * @description + * The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe + * behavior, to make implementing swipe-related directives more convenient. + * + * Requires the {@link ngTouch `ngTouch`} module to be installed. + * + * `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`, and by + * `ngCarousel` in a separate component. + * + * # Usage + * The `$swipe` service is an object with a single method: `bind`. `bind` takes an element + * which is to be watched for swipes, and an object with four handler functions. See the + * documentation for `bind` below. + */ + +ngTouch.factory('$swipe', [function() { + // The total distance in any direction before we make the call on swipe vs. scroll. + var MOVE_BUFFER_RADIUS = 10; + + function getCoordinates(event) { + var touches = event.touches && event.touches.length ? event.touches : [event]; + var e = (event.changedTouches && event.changedTouches[0]) || + (event.originalEvent && event.originalEvent.changedTouches && + event.originalEvent.changedTouches[0]) || + touches[0].originalEvent || touches[0]; + + return { + x: e.clientX, + y: e.clientY + }; + } + + return { + /** + * @ngdoc method + * @name ngTouch.$swipe#bind + * @methodOf ngTouch.$swipe + * + * @description + * The main method of `$swipe`. It takes an element to be watched for swipe motions, and an + * object containing event handlers. + * + * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end` + * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }`. + * + * `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is + * watching for `touchmove` or `mousemove` events. These events are ignored until the total + * distance moved in either dimension exceeds a small threshold. + * + * Once this threshold is exceeded, either the horizontal or vertical delta is greater. + * - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow. + * - If the vertical distance is greater, this is a scroll, and we let the browser take over. + * A `cancel` event is sent. + * + * `move` is called on `mousemove` and `touchmove` after the above logic has determined that + * a swipe is in progress. + * + * `end` is called when a swipe is successfully completed with a `touchend` or `mouseup`. + * + * `cancel` is called either on a `touchcancel` from the browser, or when we begin scrolling + * as described above. + * + */ + bind: function(element, eventHandlers) { + // Absolute total movement, used to control swipe vs. scroll. + var totalX, totalY; + // Coordinates of the start position. + var startCoords; + // Last event's position. + var lastPos; + // Whether a swipe is active. + var active = false; + + element.on('touchstart mousedown', function(event) { + startCoords = getCoordinates(event); + active = true; + totalX = 0; + totalY = 0; + lastPos = startCoords; + eventHandlers['start'] && eventHandlers['start'](startCoords, event); + }); + + element.on('touchcancel', function(event) { + active = false; + eventHandlers['cancel'] && eventHandlers['cancel'](event); + }); + + element.on('touchmove mousemove', function(event) { + if (!active) return; + + // Android will send a touchcancel if it thinks we're starting to scroll. + // So when the total distance (+ or - or both) exceeds 10px in either direction, + // we either: + // - On totalX > totalY, we send preventDefault() and treat this as a swipe. + // - On totalY > totalX, we let the browser handle it as a scroll. + + if (!startCoords) return; + var coords = getCoordinates(event); + + totalX += Math.abs(coords.x - lastPos.x); + totalY += Math.abs(coords.y - lastPos.y); + + lastPos = coords; + + if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) { + return; + } + + // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll. + if (totalY > totalX) { + // Allow native scrolling to take over. + active = false; + eventHandlers['cancel'] && eventHandlers['cancel'](event); + return; + } else { + // Prevent the browser from scrolling. + event.preventDefault(); + eventHandlers['move'] && eventHandlers['move'](coords, event); + } + }); + + element.on('touchend mouseup', function(event) { + if (!active) return; + active = false; + eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event); + }); + } + }; +}]); + +/* global ngTouch: false */ + +/** + * @ngdoc directive + * @name ngTouch.directive:ngClick + * + * @description + * A more powerful replacement for the default ngClick designed to be used on touchscreen + * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending + * the click event. This version handles them immediately, and then prevents the + * following click event from propagating. + * + * Requires the {@link ngTouch `ngTouch`} module to be installed. + * + * This directive can fall back to using an ordinary click event, and so works on desktop + * browsers as well as mobile. + * + * This directive also sets the CSS class `ng-click-active` while the element is being held + * down (by a mouse click or touch) so you can restyle the depressed element if you wish. + * + * @element ANY + * @param {expression} ngClick {@link guide/expression Expression} to evaluate + * upon tap. (Event object is available as `$event`) + * + * @example + + + + count: {{ count }} + + + */ + +ngTouch.config(['$provide', function($provide) { + $provide.decorator('ngClickDirective', ['$delegate', function($delegate) { + // drop the default ngClick directive + $delegate.shift(); + return $delegate; + }]); +}]); + +ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement', + function($parse, $timeout, $rootElement) { + var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag. + var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers. + var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click + var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks. + + var ACTIVE_CLASS_NAME = 'ng-click-active'; + var lastPreventedTime; + var touchCoordinates; + + + // TAP EVENTS AND GHOST CLICKS + // + // Why tap events? + // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're + // double-tapping, and then fire a click event. + // + // This delay sucks and makes mobile apps feel unresponsive. + // So we detect touchstart, touchmove, touchcancel and touchend ourselves and determine when + // the user has tapped on something. + // + // What happens when the browser then generates a click event? + // The browser, of course, also detects the tap and fires a click after a delay. This results in + // tapping/clicking twice. So we do "clickbusting" to prevent it. + // + // How does it work? + // We attach global touchstart and click handlers, that run during the capture (early) phase. + // So the sequence for a tap is: + // - global touchstart: Sets an "allowable region" at the point touched. + // - element's touchstart: Starts a touch + // (- touchmove or touchcancel ends the touch, no click follows) + // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold + // too long) and fires the user's tap handler. The touchend also calls preventGhostClick(). + // - preventGhostClick() removes the allowable region the global touchstart created. + // - The browser generates a click event. + // - The global click handler catches the click, and checks whether it was in an allowable region. + // - If preventGhostClick was called, the region will have been removed, the click is busted. + // - If the region is still there, the click proceeds normally. Therefore clicks on links and + // other elements without ngTap on them work normally. + // + // This is an ugly, terrible hack! + // Yeah, tell me about it. The alternatives are using the slow click events, or making our users + // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular + // encapsulates this ugly logic away from the user. + // + // Why not just put click handlers on the element? + // We do that too, just to be sure. The problem is that the tap event might have caused the DOM + // to change, so that the click fires in the same position but something else is there now. So + // the handlers are global and care only about coordinates and not elements. + + // Checks if the coordinates are close enough to be within the region. + function hit(x1, y1, x2, y2) { + return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD; + } + + // Checks a list of allowable regions against a click location. + // Returns true if the click should be allowed. + // Splices out the allowable region from the list after it has been used. + function checkAllowableRegions(touchCoordinates, x, y) { + for (var i = 0; i < touchCoordinates.length; i += 2) { + if (hit(touchCoordinates[i], touchCoordinates[i+1], x, y)) { + touchCoordinates.splice(i, i + 2); + return true; // allowable region + } + } + return false; // No allowable region; bust it. + } + + // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick + // was called recently. + function onClick(event) { + if (Date.now() - lastPreventedTime > PREVENT_DURATION) { + return; // Too old. + } + + var touches = event.touches && event.touches.length ? event.touches : [event]; + var x = touches[0].clientX; + var y = touches[0].clientY; + // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label + // and on the input element). Depending on the exact browser, this second click we don't want + // to bust has either (0,0) or negative coordinates. + if (x < 1 && y < 1) { + return; // offscreen + } + + // Look for an allowable region containing this click. + // If we find one, that means it was created by touchstart and not removed by + // preventGhostClick, so we don't bust it. + if (checkAllowableRegions(touchCoordinates, x, y)) { + return; + } + + // If we didn't find an allowable region, bust the click. + event.stopPropagation(); + event.preventDefault(); + + // Blur focused form elements + event.target && event.target.blur(); + } + + + // Global touchstart handler that creates an allowable region for a click event. + // This allowable region can be removed by preventGhostClick if we want to bust it. + function onTouchStart(event) { + var touches = event.touches && event.touches.length ? event.touches : [event]; + var x = touches[0].clientX; + var y = touches[0].clientY; + touchCoordinates.push(x, y); + + $timeout(function() { + // Remove the allowable region. + for (var i = 0; i < touchCoordinates.length; i += 2) { + if (touchCoordinates[i] == x && touchCoordinates[i+1] == y) { + touchCoordinates.splice(i, i + 2); + return; + } + } + }, PREVENT_DURATION, false); + } + + // On the first call, attaches some event handlers. Then whenever it gets called, it creates a + // zone around the touchstart where clicks will get busted. + function preventGhostClick(x, y) { + if (!touchCoordinates) { + $rootElement[0].addEventListener('click', onClick, true); + $rootElement[0].addEventListener('touchstart', onTouchStart, true); + touchCoordinates = []; + } + + lastPreventedTime = Date.now(); + + checkAllowableRegions(touchCoordinates, x, y); + } + + // Actual linking function. + return function(scope, element, attr) { + var clickHandler = $parse(attr.ngClick), + tapping = false, + tapElement, // Used to blur the element after a tap. + startTime, // Used to check if the tap was held too long. + touchStartX, + touchStartY; + + function resetState() { + tapping = false; + element.removeClass(ACTIVE_CLASS_NAME); + } + + element.on('touchstart', function(event) { + tapping = true; + tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement. + // Hack for Safari, which can target text nodes instead of containers. + if(tapElement.nodeType == 3) { + tapElement = tapElement.parentNode; + } + + element.addClass(ACTIVE_CLASS_NAME); + + startTime = Date.now(); + + var touches = event.touches && event.touches.length ? event.touches : [event]; + var e = touches[0].originalEvent || touches[0]; + touchStartX = e.clientX; + touchStartY = e.clientY; + }); + + element.on('touchmove', function(event) { + resetState(); + }); + + element.on('touchcancel', function(event) { + resetState(); + }); + + element.on('touchend', function(event) { + var diff = Date.now() - startTime; + + var touches = (event.changedTouches && event.changedTouches.length) ? event.changedTouches : + ((event.touches && event.touches.length) ? event.touches : [event]); + var e = touches[0].originalEvent || touches[0]; + var x = e.clientX; + var y = e.clientY; + var dist = Math.sqrt( Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2) ); + + if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) { + // Call preventGhostClick so the clickbuster will catch the corresponding click. + preventGhostClick(x, y); + + // Blur the focused element (the button, probably) before firing the callback. + // This doesn't work perfectly on Android Chrome, but seems to work elsewhere. + // I couldn't get anything to work reliably on Android Chrome. + if (tapElement) { + tapElement.blur(); + } + + if (!angular.isDefined(attr.disabled) || attr.disabled === false) { + element.triggerHandler('click', [event]); + } + } + + resetState(); + }); + + // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click + // something else nearby. + element.onclick = function(event) { }; + + // Actual click handler. + // There are three different kinds of clicks, only two of which reach this point. + // - On desktop browsers without touch events, their clicks will always come here. + // - On mobile browsers, the simulated "fast" click will call this. + // - But the browser's follow-up slow click will be "busted" before it reaches this handler. + // Therefore it's safe to use this directive on both mobile and desktop. + element.on('click', function(event, touchend) { + scope.$apply(function() { + clickHandler(scope, {$event: (touchend || event)}); + }); + }); + + element.on('mousedown', function(event) { + element.addClass(ACTIVE_CLASS_NAME); + }); + + element.on('mousemove mouseup', function(event) { + element.removeClass(ACTIVE_CLASS_NAME); + }); + + }; +}]); + +/* global ngTouch: false */ + +/** + * @ngdoc directive + * @name ngTouch.directive:ngSwipeLeft + * + * @description + * Specify custom behavior when an element is swiped to the left on a touchscreen device. + * A leftward swipe is a quick, right-to-left slide of the finger. + * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag + * too. + * + * Requires the {@link ngTouch `ngTouch`} module to be installed. + * + * @element ANY + * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate + * upon left swipe. (Event object is available as `$event`) + * + * @example + + +
+ Some list content, like an email in the inbox +
+
+ + +
+
+
+ */ + +/** + * @ngdoc directive + * @name ngTouch.directive:ngSwipeRight + * + * @description + * Specify custom behavior when an element is swiped to the right on a touchscreen device. + * A rightward swipe is a quick, left-to-right slide of the finger. + * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag + * too. + * + * Requires the {@link ngTouch `ngTouch`} module to be installed. + * + * @element ANY + * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate + * upon right swipe. (Event object is available as `$event`) + * + * @example + + +
+ Some list content, like an email in the inbox +
+
+ + +
+
+
+ */ + +function makeSwipeDirective(directiveName, direction, eventName) { + ngTouch.directive(directiveName, ['$parse', '$swipe', function($parse, $swipe) { + // The maximum vertical delta for a swipe should be less than 75px. + var MAX_VERTICAL_DISTANCE = 75; + // Vertical distance should not be more than a fraction of the horizontal distance. + var MAX_VERTICAL_RATIO = 0.3; + // At least a 30px lateral motion is necessary for a swipe. + var MIN_HORIZONTAL_DISTANCE = 30; + + return function(scope, element, attr) { + var swipeHandler = $parse(attr[directiveName]); + + var startCoords, valid; + + function validSwipe(coords) { + // Check that it's within the coordinates. + // Absolute vertical distance must be within tolerances. + // Horizontal distance, we take the current X - the starting X. + // This is negative for leftward swipes and positive for rightward swipes. + // After multiplying by the direction (-1 for left, +1 for right), legal swipes + // (ie. same direction as the directive wants) will have a positive delta and + // illegal ones a negative delta. + // Therefore this delta must be positive, and larger than the minimum. + if (!startCoords) return false; + var deltaY = Math.abs(coords.y - startCoords.y); + var deltaX = (coords.x - startCoords.x) * direction; + return valid && // Short circuit for already-invalidated swipes. + deltaY < MAX_VERTICAL_DISTANCE && + deltaX > 0 && + deltaX > MIN_HORIZONTAL_DISTANCE && + deltaY / deltaX < MAX_VERTICAL_RATIO; + } + + $swipe.bind(element, { + 'start': function(coords, event) { + startCoords = coords; + valid = true; + }, + 'cancel': function(event) { + valid = false; + }, + 'end': function(coords, event) { + if (validSwipe(coords)) { + scope.$apply(function() { + element.triggerHandler(eventName); + swipeHandler(scope, {$event: event}); + }); + } + } + }); + }; + }]); +} + +// Left is negative X-coordinate, right is positive. +makeSwipeDirective('ngSwipeLeft', -1, 'swipeleft'); +makeSwipeDirective('ngSwipeRight', 1, 'swiperight'); + + + +})(window, window.angular); diff --git a/app/vendor/angular/angular-touch.min.js b/app/vendor/angular/angular-touch.min.js new file mode 100644 index 00000000..9e554042 --- /dev/null +++ b/app/vendor/angular/angular-touch.min.js @@ -0,0 +1,13 @@ +/* + AngularJS v1.2.3 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(y,v,z){'use strict';function t(g,a,b){q.directive(g,["$parse","$swipe",function(l,n){var r=75,h=0.3,d=30;return function(p,m,k){function e(e){if(!u)return!1;var c=Math.abs(e.y-u.y);e=(e.x-u.x)*a;return f&&cd&&c/el&&10>n|| +(n>l?(d=!1,b.cancel&&b.cancel(a)):(a.preventDefault(),b.move&&b.move(m,a)))}});a.on("touchend mouseup",function(a){d&&(d=!1,b.end&&b.end(g(a),a))})}}}]);q.config(["$provide",function(g){g.decorator("ngClickDirective",["$delegate",function(a){a.shift();return a}])}]);q.directive("ngClick",["$parse","$timeout","$rootElement",function(g,a,b){function l(a,c,b){for(var f=0;fh)){var c= +a.touches&&a.touches.length?a.touches:[a],b=c[0].clientX,c=c[0].clientY;1>b&&1>c||l(k,b,c)||(a.stopPropagation(),a.preventDefault(),a.target&&a.target.blur())}}function r(b){b=b.touches&&b.touches.length?b.touches:[b];var c=b[0].clientX,d=b[0].clientY;k.push(c,d);a(function(){for(var a=0;ah&&12>p)&&(k||(b[0].addEventListener("click",n,!0),b[0].addEventListener("touchstart",r,!0),k=[]),m=Date.now(),l(k,e,g),s&&s.blur(),v.isDefined(d.disabled)&&!1!==d.disabled||c.triggerHandler("click",[a]));f()});c.onclick=function(a){};c.on("click",function(b,c){a.$apply(function(){h(a,{$event:c||b})})});c.on("mousedown",function(a){c.addClass(p)});c.on("mousemove mouseup",function(a){c.removeClass(p)})}}]);t("ngSwipeLeft",-1,"swipeleft");t("ngSwipeRight",1,"swiperight")})(window, +window.angular); +//# sourceMappingURL=angular-touch.min.js.map diff --git a/app/vendor/angular/angular-touch.min.js.map b/app/vendor/angular/angular-touch.min.js.map new file mode 100644 index 00000000..6681ba1b --- /dev/null +++ b/app/vendor/angular/angular-touch.min.js.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"angular-touch.min.js", +"lineCount":12, +"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAiftCC,QAASA,EAAkB,CAACC,CAAD,CAAgBC,CAAhB,CAA2BC,CAA3B,CAAsC,CAC/DC,CAAAC,UAAA,CAAkBJ,CAAlB,CAAiC,CAAC,QAAD,CAAW,QAAX,CAAqB,QAAQ,CAACK,CAAD,CAASC,CAAT,CAAiB,CAE7E,IAAIC,EAAwB,EAA5B,CAEIC,EAAqB,GAFzB,CAIIC,EAA0B,EAE9B,OAAO,SAAQ,CAACC,CAAD,CAAQC,CAAR,CAAiBC,CAAjB,CAAuB,CAKpCC,QAASA,EAAU,CAACC,CAAD,CAAS,CAS1B,GAAI,CAACC,CAAL,CAAkB,MAAO,CAAA,CACzB,KAAIC,EAASC,IAAAC,IAAA,CAASJ,CAAAK,EAAT,CAAoBJ,CAAAI,EAApB,CACTC,EAAAA,EAAUN,CAAAO,EAAVD,CAAqBL,CAAAM,EAArBD,EAAsCnB,CAC1C,OAAOqB,EAAP,EACIN,CADJ,CACaT,CADb,EAEa,CAFb,CAEIa,CAFJ,EAGIA,CAHJ,CAGaX,CAHb,EAIIO,CAJJ,CAIaI,CAJb,CAIsBZ,CAhBI,CAJ5B,IAAIe,EAAelB,CAAA,CAAOO,CAAA,CAAKZ,CAAL,CAAP,CAAnB,CAEIe,CAFJ,CAEiBO,CAqBjBhB,EAAAkB,KAAA,CAAYb,CAAZ,CAAqB,OACVc,QAAQ,CAACX,CAAD,CAASY,CAAT,CAAgB,CAC/BX,CAAA,CAAcD,CACdQ,EAAA,CAAQ,CAAA,CAFuB,CADd,QAKTK,QAAQ,CAACD,CAAD,CAAQ,CACxBJ,CAAA,CAAQ,CAAA,CADgB,CALP,KAQZM,QAAQ,CAACd,CAAD,CAASY,CAAT,CAAgB,CACzBb,CAAA,CAAWC,CAAX,CAAJ,EACEJ,CAAAmB,OAAA,CAAa,QAAQ,EAAG,CACtBlB,CAAAmB,eAAA,CAAuB5B,CAAvB,CACAqB,EAAA,CAAab,CAAb,CAAoB,QAASgB,CAAT,CAApB,CAFsB,CAAxB,CAF2B,CARZ,CAArB,CAxBoC,CARuC,CAA9C,CAAjC,CAD+D,CA1djE,IAAIvB,EAAUN,CAAAkC,OAAA,CAAe,SAAf,CAA0B,EAA1B,CAuBd5B,EAAA6B,QAAA,CAAgB,QAAhB,CAA0B,CAAC,QAAQ,EAAG,CAIpCC,QAASA,EAAc,CAACP,CAAD,CAAQ,CAC7B,IAAIQ,EAAUR,CAAAQ,QAAA,EAAiBR,CAAAQ,QAAAC,OAAjB;AAAwCT,CAAAQ,QAAxC,CAAwD,CAACR,CAAD,CAClEU,EAAAA,CAAKV,CAAAW,eAALD,EAA6BV,CAAAW,eAAA,CAAqB,CAArB,CAA7BD,EACCV,CAAAY,cADDF,EACwBV,CAAAY,cAAAD,eADxBD,EAEIV,CAAAY,cAAAD,eAAA,CAAmC,CAAnC,CAFJD,EAGAF,CAAA,CAAQ,CAAR,CAAAI,cAHAF,EAG4BF,CAAA,CAAQ,CAAR,CAEhC,OAAO,GACFE,CAAAG,QADE,GAEFH,CAAAI,QAFE,CAPsB,CAa/B,MAAO,MA+BChB,QAAQ,CAACb,CAAD,CAAU8B,CAAV,CAAyB,CAAA,IAEjCC,CAFiC,CAEzBC,CAFyB,CAIjC5B,CAJiC,CAMjC6B,CANiC,CAQjCC,EAAS,CAAA,CAEblC,EAAAmC,GAAA,CAAW,sBAAX,CAAmC,QAAQ,CAACpB,CAAD,CAAQ,CACjDX,CAAA,CAAckB,CAAA,CAAeP,CAAf,CACdmB,EAAA,CAAS,CAAA,CAETF,EAAA,CADAD,CACA,CADS,CAETE,EAAA,CAAU7B,CACV0B,EAAA,MAAA,EAA0BA,CAAA,MAAA,CAAuB1B,CAAvB,CAAoCW,CAApC,CANuB,CAAnD,CASAf,EAAAmC,GAAA,CAAW,aAAX,CAA0B,QAAQ,CAACpB,CAAD,CAAQ,CACxCmB,CAAA,CAAS,CAAA,CACTJ,EAAA,OAAA,EAA2BA,CAAA,OAAA,CAAwBf,CAAxB,CAFa,CAA1C,CAKAf,EAAAmC,GAAA,CAAW,qBAAX,CAAkC,QAAQ,CAACpB,CAAD,CAAQ,CAChD,GAAKmB,CAAL,EAQK9B,CARL,CAQA,CACA,IAAID,EAASmB,CAAA,CAAeP,CAAf,CAEbgB,EAAA,EAAUzB,IAAAC,IAAA,CAASJ,CAAAO,EAAT,CAAoBuB,CAAAvB,EAApB,CACVsB,EAAA,EAAU1B,IAAAC,IAAA,CAASJ,CAAAK,EAAT,CAAoByB,CAAAzB,EAApB,CAEVyB,EAAA,CAAU9B,CArFSiC,GAuFnB,CAAIL,CAAJ,EAvFmBK,EAuFnB,CAAmCJ,CAAnC;CAKIA,CAAJ,CAAaD,CAAb,EAEEG,CACA,CADS,CAAA,CACT,CAAAJ,CAAA,OAAA,EAA2BA,CAAA,OAAA,CAAwBf,CAAxB,CAH7B,GAOEA,CAAAsB,eAAA,EACA,CAAAP,CAAA,KAAA,EAAyBA,CAAA,KAAA,CAAsB3B,CAAtB,CAA8BY,CAA9B,CAR3B,CALA,CARA,CATgD,CAAlD,CAkCAf,EAAAmC,GAAA,CAAW,kBAAX,CAA+B,QAAQ,CAACpB,CAAD,CAAQ,CACxCmB,CAAL,GACAA,CACA,CADS,CAAA,CACT,CAAAJ,CAAA,IAAA,EAAwBA,CAAA,IAAA,CAAqBR,CAAA,CAAeP,CAAf,CAArB,CAA4CA,CAA5C,CAFxB,CAD6C,CAA/C,CA1DqC,CA/BlC,CAjB6B,CAAZ,CAA1B,CAsJAvB,EAAA8C,OAAA,CAAe,CAAC,UAAD,CAAa,QAAQ,CAACC,CAAD,CAAW,CAC7CA,CAAAC,UAAA,CAAmB,kBAAnB,CAAuC,CAAC,WAAD,CAAc,QAAQ,CAACC,CAAD,CAAY,CAEvEA,CAAAC,MAAA,EACA,OAAOD,EAHgE,CAAlC,CAAvC,CAD6C,CAAhC,CAAf,CAQAjD,EAAAC,UAAA,CAAkB,SAAlB,CAA6B,CAAC,QAAD,CAAW,UAAX,CAAuB,cAAvB,CACzB,QAAQ,CAACC,CAAD,CAASiD,CAAT,CAAmBC,CAAnB,CAAiC,CA0D3CC,QAASA,EAAqB,CAACC,CAAD,CAAmBpC,CAAnB,CAAsBF,CAAtB,CAAyB,CACrD,IAAK,IAAIuC,EAAI,CAAb,CAAgBA,CAAhB,CAAoBD,CAAAtB,OAApB,CAA6CuB,CAA7C,EAAkD,CAAlD,CACE,GARKzC,IAAAC,IAAA,CAQGuC,CAAAE,CAAiBD,CAAjBC,CARH,CAQ+CtC,CAR/C,CAQL,CARyBuC,CAQzB,EARkD3C,IAAAC,IAAA,CAQrBuC,CAAAI,CAAiBH,CAAjBG,CAAmB,CAAnBA,CARqB,CAQK1C,CARL,CAQlD,CARsEyC,CAQtE,CAEE,MADAH,EAAAK,OAAA,CAAwBJ,CAAxB,CAA2BA,CAA3B,CAA+B,CAA/B,CACO,CAAA,CAAA,CAGX,OAAO,CAAA,CAP8C,CAYvDK,QAASA,EAAO,CAACrC,CAAD,CAAQ,CACtB,GAAI,EAAAsC,IAAAC,IAAA,EAAA,CAAaC,CAAb,CAAiCC,CAAjC,CAAJ,CAAA,CAIA,IAAIjC;AAAUR,CAAAQ,QAAA,EAAiBR,CAAAQ,QAAAC,OAAjB,CAAwCT,CAAAQ,QAAxC,CAAwD,CAACR,CAAD,CAAtE,CACIL,EAAIa,CAAA,CAAQ,CAAR,CAAAK,QADR,CAEIpB,EAAIe,CAAA,CAAQ,CAAR,CAAAM,QAIA,EAAR,CAAInB,CAAJ,EAAiB,CAAjB,CAAaF,CAAb,EAOIqC,CAAA,CAAsBC,CAAtB,CAAwCpC,CAAxC,CAA2CF,CAA3C,CAPJ,GAYAO,CAAA0C,gBAAA,EAIA,CAHA1C,CAAAsB,eAAA,EAGA,CAAAtB,CAAA2C,OAAA,EAAgB3C,CAAA2C,OAAAC,KAAA,EAhBhB,CAVA,CADsB,CAiCxBC,QAASA,EAAY,CAAC7C,CAAD,CAAQ,CACvBQ,CAAAA,CAAUR,CAAAQ,QAAA,EAAiBR,CAAAQ,QAAAC,OAAjB,CAAwCT,CAAAQ,QAAxC,CAAwD,CAACR,CAAD,CACtE,KAAIL,EAAIa,CAAA,CAAQ,CAAR,CAAAK,QAAR,CACIpB,EAAIe,CAAA,CAAQ,CAAR,CAAAM,QACRiB,EAAAe,KAAA,CAAsBnD,CAAtB,CAAyBF,CAAzB,CAEAmC,EAAA,CAAS,QAAQ,EAAG,CAElB,IAAK,IAAII,EAAI,CAAb,CAAgBA,CAAhB,CAAoBD,CAAAtB,OAApB,CAA6CuB,CAA7C,EAAkD,CAAlD,CACE,GAAID,CAAA,CAAiBC,CAAjB,CAAJ,EAA2BrC,CAA3B,EAAgCoC,CAAA,CAAiBC,CAAjB,CAAmB,CAAnB,CAAhC,EAAyDvC,CAAzD,CAA4D,CAC1DsC,CAAAK,OAAA,CAAwBJ,CAAxB,CAA2BA,CAA3B,CAA+B,CAA/B,CACA,MAF0D,CAH5C,CAApB,CAQGS,CARH,CAQqB,CAAA,CARrB,CAN2B,CApG7B,IAAIA,EAAmB,IAAvB,CACIP,EAAwB,EAD5B,CAGIa,EAAoB,iBAHxB,CAIIP,CAJJ,CAKIT,CA+HJ,OAAO,SAAQ,CAAC/C,CAAD,CAAQC,CAAR,CAAiBC,CAAjB,CAAuB,CAQpC8D,QAASA,EAAU,EAAG,CACpBC,CAAA,CAAU,CAAA,CACVhE,EAAAiE,YAAA,CAAoBH,CAApB,CAFoB,CARc,IAChCI,EAAexE,CAAA,CAAOO,CAAAkE,QAAP,CADiB,CAEhCH,EAAU,CAAA,CAFsB,CAGhCI,CAHgC,CAIhCC,CAJgC,CAKhCC,CALgC,CAMhCC,CAOJvE,EAAAmC,GAAA,CAAW,YAAX;AAAyB,QAAQ,CAACpB,CAAD,CAAQ,CACvCiD,CAAA,CAAU,CAAA,CACVI,EAAA,CAAarD,CAAA2C,OAAA,CAAe3C,CAAA2C,OAAf,CAA8B3C,CAAAyD,WAEjB,EAA1B,EAAGJ,CAAAK,SAAH,GACEL,CADF,CACeA,CAAAM,WADf,CAIA1E,EAAA2E,SAAA,CAAiBb,CAAjB,CAEAO,EAAA,CAAYhB,IAAAC,IAAA,EAER/B,EAAAA,CAAUR,CAAAQ,QAAA,EAAiBR,CAAAQ,QAAAC,OAAjB,CAAwCT,CAAAQ,QAAxC,CAAwD,CAACR,CAAD,CAClEU,EAAAA,CAAIF,CAAA,CAAQ,CAAR,CAAAI,cAAJF,EAAgCF,CAAA,CAAQ,CAAR,CACpC+C,EAAA,CAAc7C,CAAAG,QACd2C,EAAA,CAAc9C,CAAAI,QAfyB,CAAzC,CAkBA7B,EAAAmC,GAAA,CAAW,WAAX,CAAwB,QAAQ,CAACpB,CAAD,CAAQ,CACtCgD,CAAA,EADsC,CAAxC,CAIA/D,EAAAmC,GAAA,CAAW,aAAX,CAA0B,QAAQ,CAACpB,CAAD,CAAQ,CACxCgD,CAAA,EADwC,CAA1C,CAIA/D,EAAAmC,GAAA,CAAW,UAAX,CAAuB,QAAQ,CAACpB,CAAD,CAAQ,CACrC,IAAI6D,EAAOvB,IAAAC,IAAA,EAAPsB,CAAoBP,CAAxB,CAEI9C,EAAWR,CAAAW,eAAD,EAAyBX,CAAAW,eAAAF,OAAzB,CAAwDT,CAAAW,eAAxD,CACRX,CAAAQ,QAAD,EAAkBR,CAAAQ,QAAAC,OAAlB,CAA0CT,CAAAQ,QAA1C,CAA0D,CAACR,CAAD,CAH/D,CAIIU,EAAIF,CAAA,CAAQ,CAAR,CAAAI,cAAJF,EAAgCF,CAAA,CAAQ,CAAR,CAJpC,CAKIb,EAAIe,CAAAG,QALR,CAMIpB,EAAIiB,CAAAI,QANR,CAOIgD,EAAOvE,IAAAwE,KAAA,CAAWxE,IAAAyE,IAAA,CAASrE,CAAT;AAAa4D,CAAb,CAA0B,CAA1B,CAAX,CAA0ChE,IAAAyE,IAAA,CAASvE,CAAT,CAAa+D,CAAb,CAA0B,CAA1B,CAA1C,CAEPP,EAAJ,GAvLegB,GAuLf,CAAeJ,CAAf,EAtLiBK,EAsLjB,CAAsCJ,CAAtC,IA7DG/B,CAwED,GAvEFF,CAAA,CAAa,CAAb,CAAAsC,iBAAA,CAAiC,OAAjC,CAA0C9B,CAA1C,CAAmD,CAAA,CAAnD,CAEA,CADAR,CAAA,CAAa,CAAb,CAAAsC,iBAAA,CAAiC,YAAjC,CAA+CtB,CAA/C,CAA6D,CAAA,CAA7D,CACA,CAAAd,CAAA,CAAmB,EAqEjB,EAlEJS,CAkEI,CAlEgBF,IAAAC,IAAA,EAkEhB,CAhEJT,CAAA,CAAsBC,CAAtB,CAuDsBpC,CAvDtB,CAuDyBF,CAvDzB,CAgEI,CAJI4D,CAIJ,EAHEA,CAAAT,KAAA,EAGF,CAAKzE,CAAAiG,UAAA,CAAkBlF,CAAAmF,SAAlB,CAAL,EAA2D,CAAA,CAA3D,GAAyCnF,CAAAmF,SAAzC,EACEpF,CAAAmB,eAAA,CAAuB,OAAvB,CAAgC,CAACJ,CAAD,CAAhC,CAZJ,CAgBAgD,EAAA,EA1BqC,CAAvC,CA+BA/D,EAAAqF,QAAA,CAAkBC,QAAQ,CAACvE,CAAD,CAAQ,EAQlCf,EAAAmC,GAAA,CAAW,OAAX,CAAoB,QAAQ,CAACpB,CAAD,CAAQwE,CAAR,CAAkB,CAC5CxF,CAAAmB,OAAA,CAAa,QAAQ,EAAG,CACtBgD,CAAA,CAAanE,CAAb,CAAoB,QAAUwF,CAAV,EAAsBxE,CAAtB,CAApB,CADsB,CAAxB,CAD4C,CAA9C,CAMAf,EAAAmC,GAAA,CAAW,WAAX,CAAwB,QAAQ,CAACpB,CAAD,CAAQ,CACtCf,CAAA2E,SAAA,CAAiBb,CAAjB,CADsC,CAAxC,CAIA9D,EAAAmC,GAAA,CAAW,mBAAX,CAAgC,QAAQ,CAACpB,CAAD,CAAQ,CAC9Cf,CAAAiE,YAAA,CAAoBH,CAApB,CAD8C,CAAhD,CAxFoC,CAvIK,CADhB,CAA7B,CA4VA1E,EAAA,CAAmB,aAAnB,CAAmC,EAAnC,CAAsC,WAAtC,CACAA,EAAA,CAAmB,cAAnB,CAAmC,CAAnC,CAAsC,YAAtC,CAziBsC,CAArC,CAAA,CA6iBEH,MA7iBF;AA6iBUA,MAAAC,QA7iBV;", +"sources":["angular-touch.js"], +"names":["window","angular","undefined","makeSwipeDirective","directiveName","direction","eventName","ngTouch","directive","$parse","$swipe","MAX_VERTICAL_DISTANCE","MAX_VERTICAL_RATIO","MIN_HORIZONTAL_DISTANCE","scope","element","attr","validSwipe","coords","startCoords","deltaY","Math","abs","y","deltaX","x","valid","swipeHandler","bind","start","event","cancel","end","$apply","triggerHandler","module","factory","getCoordinates","touches","length","e","changedTouches","originalEvent","clientX","clientY","eventHandlers","totalX","totalY","lastPos","active","on","MOVE_BUFFER_RADIUS","preventDefault","config","$provide","decorator","$delegate","shift","$timeout","$rootElement","checkAllowableRegions","touchCoordinates","i","x1","CLICKBUSTER_THRESHOLD","y1","splice","onClick","Date","now","lastPreventedTime","PREVENT_DURATION","stopPropagation","target","blur","onTouchStart","push","ACTIVE_CLASS_NAME","resetState","tapping","removeClass","clickHandler","ngClick","tapElement","startTime","touchStartX","touchStartY","srcElement","nodeType","parentNode","addClass","diff","dist","sqrt","pow","TAP_DURATION","MOVE_TOLERANCE","addEventListener","isDefined","disabled","onclick","element.onclick","touchend"] +} diff --git a/app/vendor/angular/angular.js b/app/vendor/angular/angular.js new file mode 100644 index 00000000..8b538ce2 --- /dev/null +++ b/app/vendor/angular/angular.js @@ -0,0 +1,20282 @@ +/** + * @license AngularJS v1.2.3 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, document, undefined) {'use strict'; + +/** + * @description + * + * This object provides a utility for producing rich Error messages within + * Angular. It can be called as follows: + * + * var exampleMinErr = minErr('example'); + * throw exampleMinErr('one', 'This {0} is {1}', foo, bar); + * + * The above creates an instance of minErr in the example namespace. The + * resulting error will have a namespaced error code of example.one. The + * resulting error will replace {0} with the value of foo, and {1} with the + * value of bar. The object is not restricted in the number of arguments it can + * take. + * + * If fewer arguments are specified than necessary for interpolation, the extra + * interpolation markers will be preserved in the final string. + * + * Since data will be parsed statically during a build step, some restrictions + * are applied with respect to how minErr instances are created and called. + * Instances should have names of the form namespaceMinErr for a minErr created + * using minErr('namespace') . Error codes, namespaces and template strings + * should all be static strings, not variables or general expressions. + * + * @param {string} module The namespace to use for the new minErr instance. + * @returns {function(string, string, ...): Error} instance + */ + +function minErr(module) { + return function () { + var code = arguments[0], + prefix = '[' + (module ? module + ':' : '') + code + '] ', + template = arguments[1], + templateArgs = arguments, + stringify = function (obj) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (typeof obj === 'undefined') { + return 'undefined'; + } else if (typeof obj !== 'string') { + return JSON.stringify(obj); + } + return obj; + }, + message, i; + + message = prefix + template.replace(/\{\d+\}/g, function (match) { + var index = +match.slice(1, -1), arg; + + if (index + 2 < templateArgs.length) { + arg = templateArgs[index + 2]; + if (typeof arg === 'function') { + return arg.toString().replace(/ ?\{[\s\S]*$/, ''); + } else if (typeof arg === 'undefined') { + return 'undefined'; + } else if (typeof arg !== 'string') { + return toJson(arg); + } + return arg; + } + return match; + }); + + message = message + '\nhttp://errors.angularjs.org/1.2.3/' + + (module ? module + '/' : '') + code; + for (i = 2; i < arguments.length; i++) { + message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' + + encodeURIComponent(stringify(arguments[i])); + } + + return new Error(message); + }; +} + +/* We need to tell jshint what variables are being exported */ +/* global + -angular, + -msie, + -jqLite, + -jQuery, + -slice, + -push, + -toString, + -ngMinErr, + -_angular, + -angularModule, + -nodeName_, + -uid, + + -lowercase, + -uppercase, + -manualLowercase, + -manualUppercase, + -nodeName_, + -isArrayLike, + -forEach, + -sortedKeys, + -forEachSorted, + -reverseParams, + -nextUid, + -setHashKey, + -extend, + -int, + -inherit, + -noop, + -identity, + -valueFn, + -isUndefined, + -isDefined, + -isObject, + -isString, + -isNumber, + -isDate, + -isArray, + -isFunction, + -isRegExp, + -isWindow, + -isScope, + -isFile, + -isBoolean, + -trim, + -isElement, + -makeMap, + -map, + -size, + -includes, + -indexOf, + -arrayRemove, + -isLeafNode, + -copy, + -shallowCopy, + -equals, + -csp, + -concat, + -sliceArgs, + -bind, + -toJsonReplacer, + -toJson, + -fromJson, + -toBoolean, + -startingTag, + -tryDecodeURIComponent, + -parseKeyValue, + -toKeyValue, + -encodeUriSegment, + -encodeUriQuery, + -angularInit, + -bootstrap, + -snake_case, + -bindJQuery, + -assertArg, + -assertArgFn, + -assertNotHasOwnProperty, + -getter, + -getBlockElements, + +*/ + +//////////////////////////////////// + +/** + * @ngdoc function + * @name angular.lowercase + * @function + * + * @description Converts the specified string to lowercase. + * @param {string} string String to be converted to lowercase. + * @returns {string} Lowercased string. + */ +var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;}; + + +/** + * @ngdoc function + * @name angular.uppercase + * @function + * + * @description Converts the specified string to uppercase. + * @param {string} string String to be converted to uppercase. + * @returns {string} Uppercased string. + */ +var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;}; + + +var manualLowercase = function(s) { + /* jshint bitwise: false */ + return isString(s) + ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) + : s; +}; +var manualUppercase = function(s) { + /* jshint bitwise: false */ + return isString(s) + ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) + : s; +}; + + +// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish +// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods +// with correct but slower alternatives. +if ('i' !== 'I'.toLowerCase()) { + lowercase = manualLowercase; + uppercase = manualUppercase; +} + + +var /** holds major version number for IE or NaN for real browsers */ + msie, + jqLite, // delay binding since jQuery could be loaded after us. + jQuery, // delay binding + slice = [].slice, + push = [].push, + toString = Object.prototype.toString, + ngMinErr = minErr('ng'), + + + _angular = window.angular, + /** @name angular */ + angular = window.angular || (window.angular = {}), + angularModule, + nodeName_, + uid = ['0', '0', '0']; + +/** + * IE 11 changed the format of the UserAgent string. + * See http://msdn.microsoft.com/en-us/library/ms537503.aspx + */ +msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]); +if (isNaN(msie)) { + msie = int((/trident\/.*; rv:(\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]); +} + + +/** + * @private + * @param {*} obj + * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, + * String ...) + */ +function isArrayLike(obj) { + if (obj == null || isWindow(obj)) { + return false; + } + + var length = obj.length; + + if (obj.nodeType === 1 && length) { + return true; + } + + return isString(obj) || isArray(obj) || length === 0 || + typeof length === 'number' && length > 0 && (length - 1) in obj; +} + +/** + * @ngdoc function + * @name angular.forEach + * @function + * + * @description + * Invokes the `iterator` function once for each item in `obj` collection, which can be either an + * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value` + * is the value of an object property or an array element and `key` is the object property key or + * array element index. Specifying a `context` for the function is optional. + * + * Note: this function was previously known as `angular.foreach`. + * +
+     var values = {name: 'misko', gender: 'male'};
+     var log = [];
+     angular.forEach(values, function(value, key){
+       this.push(key + ': ' + value);
+     }, log);
+     expect(log).toEqual(['name: misko', 'gender:male']);
+   
+ * + * @param {Object|Array} obj Object to iterate over. + * @param {Function} iterator Iterator function. + * @param {Object=} context Object to become context (`this`) for the iterator function. + * @returns {Object|Array} Reference to `obj`. + */ +function forEach(obj, iterator, context) { + var key; + if (obj) { + if (isFunction(obj)){ + for (key in obj) { + if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key); + } + } + } else if (obj.forEach && obj.forEach !== forEach) { + obj.forEach(iterator, context); + } else if (isArrayLike(obj)) { + for (key = 0; key < obj.length; key++) + iterator.call(context, obj[key], key); + } else { + for (key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key); + } + } + } + } + return obj; +} + +function sortedKeys(obj) { + var keys = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + keys.push(key); + } + } + return keys.sort(); +} + +function forEachSorted(obj, iterator, context) { + var keys = sortedKeys(obj); + for ( var i = 0; i < keys.length; i++) { + iterator.call(context, obj[keys[i]], keys[i]); + } + return keys; +} + + +/** + * when using forEach the params are value, key, but it is often useful to have key, value. + * @param {function(string, *)} iteratorFn + * @returns {function(*, string)} + */ +function reverseParams(iteratorFn) { + return function(value, key) { iteratorFn(key, value); }; +} + +/** + * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric + * characters such as '012ABC'. The reason why we are not using simply a number counter is that + * the number string gets longer over time, and it can also overflow, where as the nextId + * will grow much slower, it is a string, and it will never overflow. + * + * @returns an unique alpha-numeric string + */ +function nextUid() { + var index = uid.length; + var digit; + + while(index) { + index--; + digit = uid[index].charCodeAt(0); + if (digit == 57 /*'9'*/) { + uid[index] = 'A'; + return uid.join(''); + } + if (digit == 90 /*'Z'*/) { + uid[index] = '0'; + } else { + uid[index] = String.fromCharCode(digit + 1); + return uid.join(''); + } + } + uid.unshift('0'); + return uid.join(''); +} + + +/** + * Set or clear the hashkey for an object. + * @param obj object + * @param h the hashkey (!truthy to delete the hashkey) + */ +function setHashKey(obj, h) { + if (h) { + obj.$$hashKey = h; + } + else { + delete obj.$$hashKey; + } +} + +/** + * @ngdoc function + * @name angular.extend + * @function + * + * @description + * Extends the destination object `dst` by copying all of the properties from the `src` object(s) + * to `dst`. You can specify multiple `src` objects. + * + * @param {Object} dst Destination object. + * @param {...Object} src Source object(s). + * @returns {Object} Reference to `dst`. + */ +function extend(dst) { + var h = dst.$$hashKey; + forEach(arguments, function(obj){ + if (obj !== dst) { + forEach(obj, function(value, key){ + dst[key] = value; + }); + } + }); + + setHashKey(dst,h); + return dst; +} + +function int(str) { + return parseInt(str, 10); +} + + +function inherit(parent, extra) { + return extend(new (extend(function() {}, {prototype:parent}))(), extra); +} + +/** + * @ngdoc function + * @name angular.noop + * @function + * + * @description + * A function that performs no operations. This function can be useful when writing code in the + * functional style. +
+     function foo(callback) {
+       var result = calculateResult();
+       (callback || angular.noop)(result);
+     }
+   
+ */ +function noop() {} +noop.$inject = []; + + +/** + * @ngdoc function + * @name angular.identity + * @function + * + * @description + * A function that returns its first argument. This function is useful when writing code in the + * functional style. + * +
+     function transformer(transformationFn, value) {
+       return (transformationFn || angular.identity)(value);
+     };
+   
+ */ +function identity($) {return $;} +identity.$inject = []; + + +function valueFn(value) {return function() {return value;};} + +/** + * @ngdoc function + * @name angular.isUndefined + * @function + * + * @description + * Determines if a reference is undefined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is undefined. + */ +function isUndefined(value){return typeof value == 'undefined';} + + +/** + * @ngdoc function + * @name angular.isDefined + * @function + * + * @description + * Determines if a reference is defined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is defined. + */ +function isDefined(value){return typeof value != 'undefined';} + + +/** + * @ngdoc function + * @name angular.isObject + * @function + * + * @description + * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not + * considered to be objects. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Object` but not `null`. + */ +function isObject(value){return value != null && typeof value == 'object';} + + +/** + * @ngdoc function + * @name angular.isString + * @function + * + * @description + * Determines if a reference is a `String`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `String`. + */ +function isString(value){return typeof value == 'string';} + + +/** + * @ngdoc function + * @name angular.isNumber + * @function + * + * @description + * Determines if a reference is a `Number`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Number`. + */ +function isNumber(value){return typeof value == 'number';} + + +/** + * @ngdoc function + * @name angular.isDate + * @function + * + * @description + * Determines if a value is a date. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Date`. + */ +function isDate(value){ + return toString.apply(value) == '[object Date]'; +} + + +/** + * @ngdoc function + * @name angular.isArray + * @function + * + * @description + * Determines if a reference is an `Array`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Array`. + */ +function isArray(value) { + return toString.apply(value) == '[object Array]'; +} + + +/** + * @ngdoc function + * @name angular.isFunction + * @function + * + * @description + * Determines if a reference is a `Function`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Function`. + */ +function isFunction(value){return typeof value == 'function';} + + +/** + * Determines if a value is a regular expression object. + * + * @private + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `RegExp`. + */ +function isRegExp(value) { + return toString.apply(value) == '[object RegExp]'; +} + + +/** + * Checks if `obj` is a window object. + * + * @private + * @param {*} obj Object to check + * @returns {boolean} True if `obj` is a window obj. + */ +function isWindow(obj) { + return obj && obj.document && obj.location && obj.alert && obj.setInterval; +} + + +function isScope(obj) { + return obj && obj.$evalAsync && obj.$watch; +} + + +function isFile(obj) { + return toString.apply(obj) === '[object File]'; +} + + +function isBoolean(value) { + return typeof value == 'boolean'; +} + + +var trim = (function() { + // native trim is way faster: http://jsperf.com/angular-trim-test + // but IE doesn't have it... :-( + // TODO: we should move this into IE/ES5 polyfill + if (!String.prototype.trim) { + return function(value) { + return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value; + }; + } + return function(value) { + return isString(value) ? value.trim() : value; + }; +})(); + + +/** + * @ngdoc function + * @name angular.isElement + * @function + * + * @description + * Determines if a reference is a DOM element (or wrapped jQuery element). + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element). + */ +function isElement(node) { + return node && + (node.nodeName // we are a direct element + || (node.on && node.find)); // we have an on and find method part of jQuery API +} + +/** + * @param str 'key1,key2,...' + * @returns {object} in the form of {key1:true, key2:true, ...} + */ +function makeMap(str){ + var obj = {}, items = str.split(","), i; + for ( i = 0; i < items.length; i++ ) + obj[ items[i] ] = true; + return obj; +} + + +if (msie < 9) { + nodeName_ = function(element) { + element = element.nodeName ? element : element[0]; + return (element.scopeName && element.scopeName != 'HTML') + ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName; + }; +} else { + nodeName_ = function(element) { + return element.nodeName ? element.nodeName : element[0].nodeName; + }; +} + + +function map(obj, iterator, context) { + var results = []; + forEach(obj, function(value, index, list) { + results.push(iterator.call(context, value, index, list)); + }); + return results; +} + + +/** + * @description + * Determines the number of elements in an array, the number of properties an object has, or + * the length of a string. + * + * Note: This function is used to augment the Object type in Angular expressions. See + * {@link angular.Object} for more information about Angular arrays. + * + * @param {Object|Array|string} obj Object, array, or string to inspect. + * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object + * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array. + */ +function size(obj, ownPropsOnly) { + var count = 0, key; + + if (isArray(obj) || isString(obj)) { + return obj.length; + } else if (isObject(obj)){ + for (key in obj) + if (!ownPropsOnly || obj.hasOwnProperty(key)) + count++; + } + + return count; +} + + +function includes(array, obj) { + return indexOf(array, obj) != -1; +} + +function indexOf(array, obj) { + if (array.indexOf) return array.indexOf(obj); + + for ( var i = 0; i < array.length; i++) { + if (obj === array[i]) return i; + } + return -1; +} + +function arrayRemove(array, value) { + var index = indexOf(array, value); + if (index >=0) + array.splice(index, 1); + return value; +} + +function isLeafNode (node) { + if (node) { + switch (node.nodeName) { + case "OPTION": + case "PRE": + case "TITLE": + return true; + } + } + return false; +} + +/** + * @ngdoc function + * @name angular.copy + * @function + * + * @description + * Creates a deep copy of `source`, which should be an object or an array. + * + * * If no destination is supplied, a copy of the object or array is created. + * * If a destination is provided, all of its elements (for array) or properties (for objects) + * are deleted and then all elements/properties from the source are copied to it. + * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. + * * If `source` is identical to 'destination' an exception will be thrown. + * + * @param {*} source The source that will be used to make a copy. + * Can be any type, including primitives, `null`, and `undefined`. + * @param {(Object|Array)=} destination Destination into which the source is copied. If + * provided, must be of the same type as `source`. + * @returns {*} The copy or updated `destination`, if `destination` was specified. + * + * @example + + +
+
+ Name:
+ E-mail:
+ Gender: male + female
+ + +
+
form = {{user | json}}
+
master = {{master | json}}
+
+ + +
+
+ */ +function copy(source, destination){ + if (isWindow(source) || isScope(source)) { + throw ngMinErr('cpws', + "Can't copy! Making copies of Window or Scope instances is not supported."); + } + + if (!destination) { + destination = source; + if (source) { + if (isArray(source)) { + destination = copy(source, []); + } else if (isDate(source)) { + destination = new Date(source.getTime()); + } else if (isRegExp(source)) { + destination = new RegExp(source.source); + } else if (isObject(source)) { + destination = copy(source, {}); + } + } + } else { + if (source === destination) throw ngMinErr('cpi', + "Can't copy! Source and destination are identical."); + if (isArray(source)) { + destination.length = 0; + for ( var i = 0; i < source.length; i++) { + destination.push(copy(source[i])); + } + } else { + var h = destination.$$hashKey; + forEach(destination, function(value, key){ + delete destination[key]; + }); + for ( var key in source) { + destination[key] = copy(source[key]); + } + setHashKey(destination,h); + } + } + return destination; +} + +/** + * Create a shallow copy of an object + */ +function shallowCopy(src, dst) { + dst = dst || {}; + + for(var key in src) { + // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src + // so we don't need to worry hasOwnProperty here + if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') { + dst[key] = src[key]; + } + } + + return dst; +} + + +/** + * @ngdoc function + * @name angular.equals + * @function + * + * @description + * Determines if two objects or two values are equivalent. Supports value types, regular + * expressions, arrays and objects. + * + * Two objects or values are considered equivalent if at least one of the following is true: + * + * * Both objects or values pass `===` comparison. + * * Both objects or values are of the same type and all of their properties are equal by + * comparing them with `angular.equals`. + * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal) + * * Both values represent the same regular expression (In JavasScript, + * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual + * representation matches). + * + * During a property comparison, properties of `function` type and properties with names + * that begin with `$` are ignored. + * + * Scope and DOMWindow objects are being compared only by identify (`===`). + * + * @param {*} o1 Object or value to compare. + * @param {*} o2 Object or value to compare. + * @returns {boolean} True if arguments are equal. + */ +function equals(o1, o2) { + if (o1 === o2) return true; + if (o1 === null || o2 === null) return false; + if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN + var t1 = typeof o1, t2 = typeof o2, length, key, keySet; + if (t1 == t2) { + if (t1 == 'object') { + if (isArray(o1)) { + if (!isArray(o2)) return false; + if ((length = o1.length) == o2.length) { + for(key=0; key 2 ? sliceArgs(arguments, 2) : []; + if (isFunction(fn) && !(fn instanceof RegExp)) { + return curryArgs.length + ? function() { + return arguments.length + ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0))) + : fn.apply(self, curryArgs); + } + : function() { + return arguments.length + ? fn.apply(self, arguments) + : fn.call(self); + }; + } else { + // in IE, native methods are not functions so they cannot be bound (note: they don't need to be) + return fn; + } +} + + +function toJsonReplacer(key, value) { + var val = value; + + if (typeof key === 'string' && key.charAt(0) === '$') { + val = undefined; + } else if (isWindow(value)) { + val = '$WINDOW'; + } else if (value && document === value) { + val = '$DOCUMENT'; + } else if (isScope(value)) { + val = '$SCOPE'; + } + + return val; +} + + +/** + * @ngdoc function + * @name angular.toJson + * @function + * + * @description + * Serializes input into a JSON-formatted string. Properties with leading $ characters will be + * stripped since angular uses this notation internally. + * + * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. + * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace. + * @returns {string|undefined} JSON-ified string representing `obj`. + */ +function toJson(obj, pretty) { + if (typeof obj === 'undefined') return undefined; + return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null); +} + + +/** + * @ngdoc function + * @name angular.fromJson + * @function + * + * @description + * Deserializes a JSON string. + * + * @param {string} json JSON string to deserialize. + * @returns {Object|Array|Date|string|number} Deserialized thingy. + */ +function fromJson(json) { + return isString(json) + ? JSON.parse(json) + : json; +} + + +function toBoolean(value) { + if (value && value.length !== 0) { + var v = lowercase("" + value); + value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]'); + } else { + value = false; + } + return value; +} + +/** + * @returns {string} Returns the string representation of the element. + */ +function startingTag(element) { + element = jqLite(element).clone(); + try { + // turns out IE does not let you set .html() on elements which + // are not allowed to have children. So we just ignore it. + element.html(''); + } catch(e) {} + // As Per DOM Standards + var TEXT_NODE = 3; + var elemHtml = jqLite('
').append(element).html(); + try { + return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) : + elemHtml. + match(/^(<[^>]+>)/)[1]. + replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); + } catch(e) { + return lowercase(elemHtml); + } + +} + + +///////////////////////////////////////////////// + +/** + * Tries to decode the URI component without throwing an exception. + * + * @private + * @param str value potential URI component to check. + * @returns {boolean} True if `value` can be decoded + * with the decodeURIComponent function. + */ +function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch(e) { + // Ignore any invalid uri component + } +} + + +/** + * Parses an escaped url query string into key-value pairs. + * @returns Object.<(string|boolean)> + */ +function parseKeyValue(/**string*/keyValue) { + var obj = {}, key_value, key; + forEach((keyValue || "").split('&'), function(keyValue){ + if ( keyValue ) { + key_value = keyValue.split('='); + key = tryDecodeURIComponent(key_value[0]); + if ( isDefined(key) ) { + var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true; + if (!obj[key]) { + obj[key] = val; + } else if(isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [obj[key],val]; + } + } + } + }); + return obj; +} + +function toKeyValue(obj) { + var parts = []; + forEach(obj, function(value, key) { + if (isArray(value)) { + forEach(value, function(arrayValue) { + parts.push(encodeUriQuery(key, true) + + (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true))); + }); + } else { + parts.push(encodeUriQuery(key, true) + + (value === true ? '' : '=' + encodeUriQuery(value, true))); + } + }); + return parts.length ? parts.join('&') : ''; +} + + +/** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path + * segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); +} + + +/** + * This method is intended for encoding *key* or *value* parts of query component. We need a custom + * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be + * encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); +} + + +/** + * @ngdoc directive + * @name ng.directive:ngApp + * + * @element ANY + * @param {angular.Module} ngApp an optional application + * {@link angular.module module} name to load. + * + * @description + * + * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive + * designates the **root element** of the application and is typically placed near the root element + * of the page - e.g. on the `` or `` tags. + * + * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` + * found in the document will be used to define the root element to auto-bootstrap as an + * application. To run multiple applications in an HTML document you must manually bootstrap them using + * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other. + * + * You can specify an **AngularJS module** to be used as the root module for the application. This + * module will be loaded into the {@link AUTO.$injector} when the application is bootstrapped and + * should contain the application code needed or have dependencies on other modules that will + * contain the code. See {@link angular.module} for more information. + * + * In the example below if the `ngApp` directive were not placed on the `html` element then the + * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}` + * would not be resolved to `3`. + * + * `ngApp` is the easiest, and most common, way to bootstrap an application. + * + + +
+ I can add: {{a}} + {{b}} = {{ a+b }} + + + angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }); + + + * + */ +function angularInit(element, bootstrap) { + var elements = [element], + appElement, + module, + names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'], + NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/; + + function append(element) { + element && elements.push(element); + } + + forEach(names, function(name) { + names[name] = true; + append(document.getElementById(name)); + name = name.replace(':', '\\:'); + if (element.querySelectorAll) { + forEach(element.querySelectorAll('.' + name), append); + forEach(element.querySelectorAll('.' + name + '\\:'), append); + forEach(element.querySelectorAll('[' + name + ']'), append); + } + }); + + forEach(elements, function(element) { + if (!appElement) { + var className = ' ' + element.className + ' '; + var match = NG_APP_CLASS_REGEXP.exec(className); + if (match) { + appElement = element; + module = (match[2] || '').replace(/\s+/g, ','); + } else { + forEach(element.attributes, function(attr) { + if (!appElement && names[attr.name]) { + appElement = element; + module = attr.value; + } + }); + } + } + }); + if (appElement) { + bootstrap(appElement, module ? [module] : []); + } +} + +/** + * @ngdoc function + * @name angular.bootstrap + * @description + * Use this function to manually start up angular application. + * + * See: {@link guide/bootstrap Bootstrap} + * + * Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually. + * They must use {@link api/ng.directive:ngApp ngApp}. + * + * @param {Element} element DOM element which is the root of angular application. + * @param {Array=} modules an array of modules to load into the application. + * Each item in the array should be the name of a predefined module or a (DI annotated) + * function that will be invoked by the injector as a run block. + * See: {@link angular.module modules} + * @returns {AUTO.$injector} Returns the newly created injector for this app. + */ +function bootstrap(element, modules) { + var doBootstrap = function() { + element = jqLite(element); + + if (element.injector()) { + var tag = (element[0] === document) ? 'document' : startingTag(element); + throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag); + } + + modules = modules || []; + modules.unshift(['$provide', function($provide) { + $provide.value('$rootElement', element); + }]); + modules.unshift('ng'); + var injector = createInjector(modules); + injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate', + function(scope, element, compile, injector, animate) { + scope.$apply(function() { + element.data('$injector', injector); + compile(element)(scope); + }); + }] + ); + return injector; + }; + + var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; + + if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { + return doBootstrap(); + } + + window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); + angular.resumeBootstrap = function(extraModules) { + forEach(extraModules, function(module) { + modules.push(module); + }); + doBootstrap(); + }; +} + +var SNAKE_CASE_REGEXP = /[A-Z]/g; +function snake_case(name, separator){ + separator = separator || '_'; + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); +} + +function bindJQuery() { + // bind to jQuery if present; + jQuery = window.jQuery; + // reset to jQuery or default to us. + if (jQuery) { + jqLite = jQuery; + extend(jQuery.fn, { + scope: JQLitePrototype.scope, + isolateScope: JQLitePrototype.isolateScope, + controller: JQLitePrototype.controller, + injector: JQLitePrototype.injector, + inheritedData: JQLitePrototype.inheritedData + }); + // Method signature: + // jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) + jqLitePatchJQueryRemove('remove', true, true, false); + jqLitePatchJQueryRemove('empty', false, false, false); + jqLitePatchJQueryRemove('html', false, false, true); + } else { + jqLite = JQLite; + } + angular.element = jqLite; +} + +/** + * throw error if the argument is falsy. + */ +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + +function assertArgFn(arg, name, acceptArrayAnnotation) { + if (acceptArrayAnnotation && isArray(arg)) { + arg = arg[arg.length - 1]; + } + + assertArg(isFunction(arg), name, 'not a function, got ' + + (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg)); + return arg; +} + +/** + * throw error if the name given is hasOwnProperty + * @param {String} name the name to test + * @param {String} context the context in which the name is used, such as module or directive + */ +function assertNotHasOwnProperty(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context); + } +} + +/** + * Return the value accessible from the object by path. Any undefined traversals are ignored + * @param {Object} obj starting object + * @param {string} path path to traverse + * @param {boolean=true} bindFnToScope + * @returns value as accessible by path + */ +//TODO(misko): this function needs to be removed +function getter(obj, path, bindFnToScope) { + if (!path) return obj; + var keys = path.split('.'); + var key; + var lastInstance = obj; + var len = keys.length; + + for (var i = 0; i < len; i++) { + key = keys[i]; + if (obj) { + obj = (lastInstance = obj)[key]; + } + } + if (!bindFnToScope && isFunction(obj)) { + return bind(lastInstance, obj); + } + return obj; +} + +/** + * Return the siblings between `startNode` and `endNode`, inclusive + * @param {Object} object with `startNode` and `endNode` properties + * @returns jQlite object containing the elements + */ +function getBlockElements(block) { + if (block.startNode === block.endNode) { + return jqLite(block.startNode); + } + + var element = block.startNode; + var elements = [element]; + + do { + element = element.nextSibling; + if (!element) break; + elements.push(element); + } while (element !== block.endNode); + + return jqLite(elements); +} + +/** + * @ngdoc interface + * @name angular.Module + * @description + * + * Interface for configuring angular {@link angular.module modules}. + */ + +function setupModuleLoader(window) { + + var $injectorMinErr = minErr('$injector'); + var ngMinErr = minErr('ng'); + + function ensure(obj, name, factory) { + return obj[name] || (obj[name] = factory()); + } + + var angular = ensure(window, 'angular', Object); + + // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap + angular.$$minErr = angular.$$minErr || minErr; + + return ensure(angular, 'module', function() { + /** @type {Object.} */ + var modules = {}; + + /** + * @ngdoc function + * @name angular.module + * @description + * + * The `angular.module` is a global place for creating, registering and retrieving Angular + * modules. + * All modules (angular core or 3rd party) that should be available to an application must be + * registered using this mechanism. + * + * When passed two or more arguments, a new module is created. If passed only one argument, an + * existing module (the name passed as the first argument to `module`) is retrieved. + * + * + * # Module + * + * A module is a collection of services, directives, filters, and configuration information. + * `angular.module` is used to configure the {@link AUTO.$injector $injector}. + * + *
+     * // Create a new module
+     * var myModule = angular.module('myModule', []);
+     *
+     * // register a new service
+     * myModule.value('appName', 'MyCoolApp');
+     *
+     * // configure existing services inside initialization blocks.
+     * myModule.config(function($locationProvider) {
+     *   // Configure existing providers
+     *   $locationProvider.hashPrefix('!');
+     * });
+     * 
+ * + * Then you can create an injector and load your modules like this: + * + *
+     * var injector = angular.injector(['ng', 'MyModule'])
+     * 
+ * + * However it's more likely that you'll just use + * {@link ng.directive:ngApp ngApp} or + * {@link angular.bootstrap} to simplify this process for you. + * + * @param {!string} name The name of the module to create or retrieve. + * @param {Array.=} requires If specified then new module is being created. If + * unspecified then the the module is being retrieved for further configuration. + * @param {Function} configFn Optional configuration function for the module. Same as + * {@link angular.Module#methods_config Module#config()}. + * @returns {module} new module with the {@link angular.Module} api. + */ + return function module(name, requires, configFn) { + var assertNotHasOwnProperty = function(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); + } + }; + + assertNotHasOwnProperty(name, 'module'); + if (requires && modules.hasOwnProperty(name)) { + modules[name] = null; + } + return ensure(modules, name, function() { + if (!requires) { + throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + + "the module name or forgot to load it. If registering a module ensure that you " + + "specify the dependencies as the second argument.", name); + } + + /** @type {!Array.>} */ + var invokeQueue = []; + + /** @type {!Array.} */ + var runBlocks = []; + + var config = invokeLater('$injector', 'invoke'); + + /** @type {angular.Module} */ + var moduleInstance = { + // Private state + _invokeQueue: invokeQueue, + _runBlocks: runBlocks, + + /** + * @ngdoc property + * @name angular.Module#requires + * @propertyOf angular.Module + * @returns {Array.} List of module names which must be loaded before this module. + * @description + * Holds the list of modules which the injector will load before the current module is + * loaded. + */ + requires: requires, + + /** + * @ngdoc property + * @name angular.Module#name + * @propertyOf angular.Module + * @returns {string} Name of the module. + * @description + */ + name: name, + + + /** + * @ngdoc method + * @name angular.Module#provider + * @methodOf angular.Module + * @param {string} name service name + * @param {Function} providerType Construction function for creating new instance of the + * service. + * @description + * See {@link AUTO.$provide#provider $provide.provider()}. + */ + provider: invokeLater('$provide', 'provider'), + + /** + * @ngdoc method + * @name angular.Module#factory + * @methodOf angular.Module + * @param {string} name service name + * @param {Function} providerFunction Function for creating new instance of the service. + * @description + * See {@link AUTO.$provide#factory $provide.factory()}. + */ + factory: invokeLater('$provide', 'factory'), + + /** + * @ngdoc method + * @name angular.Module#service + * @methodOf angular.Module + * @param {string} name service name + * @param {Function} constructor A constructor function that will be instantiated. + * @description + * See {@link AUTO.$provide#service $provide.service()}. + */ + service: invokeLater('$provide', 'service'), + + /** + * @ngdoc method + * @name angular.Module#value + * @methodOf angular.Module + * @param {string} name service name + * @param {*} object Service instance object. + * @description + * See {@link AUTO.$provide#value $provide.value()}. + */ + value: invokeLater('$provide', 'value'), + + /** + * @ngdoc method + * @name angular.Module#constant + * @methodOf angular.Module + * @param {string} name constant name + * @param {*} object Constant value. + * @description + * Because the constant are fixed, they get applied before other provide methods. + * See {@link AUTO.$provide#constant $provide.constant()}. + */ + constant: invokeLater('$provide', 'constant', 'unshift'), + + /** + * @ngdoc method + * @name angular.Module#animation + * @methodOf angular.Module + * @param {string} name animation name + * @param {Function} animationFactory Factory function for creating new instance of an + * animation. + * @description + * + * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. + * + * + * Defines an animation hook that can be later used with + * {@link ngAnimate.$animate $animate} service and directives that use this service. + * + *
+           * module.animation('.animation-name', function($inject1, $inject2) {
+           *   return {
+           *     eventName : function(element, done) {
+           *       //code to run the animation
+           *       //once complete, then run done()
+           *       return function cancellationFunction(element) {
+           *         //code to cancel the animation
+           *       }
+           *     }
+           *   }
+           * })
+           * 
+ * + * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and + * {@link ngAnimate ngAnimate module} for more information. + */ + animation: invokeLater('$animateProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#filter + * @methodOf angular.Module + * @param {string} name Filter name. + * @param {Function} filterFactory Factory function for creating new instance of filter. + * @description + * See {@link ng.$filterProvider#register $filterProvider.register()}. + */ + filter: invokeLater('$filterProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#controller + * @methodOf angular.Module + * @param {string|Object} name Controller name, or an object map of controllers where the + * keys are the names and the values are the constructors. + * @param {Function} constructor Controller constructor function. + * @description + * See {@link ng.$controllerProvider#register $controllerProvider.register()}. + */ + controller: invokeLater('$controllerProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#directive + * @methodOf angular.Module + * @param {string|Object} name Directive name, or an object map of directives where the + * keys are the names and the values are the factories. + * @param {Function} directiveFactory Factory function for creating new instance of + * directives. + * @description + * See {@link ng.$compileProvider#methods_directive $compileProvider.directive()}. + */ + directive: invokeLater('$compileProvider', 'directive'), + + /** + * @ngdoc method + * @name angular.Module#config + * @methodOf angular.Module + * @param {Function} configFn Execute this function on module load. Useful for service + * configuration. + * @description + * Use this method to register work which needs to be performed on module loading. + */ + config: config, + + /** + * @ngdoc method + * @name angular.Module#run + * @methodOf angular.Module + * @param {Function} initializationFn Execute this function after injector creation. + * Useful for application initialization. + * @description + * Use this method to register work which should be performed when the injector is done + * loading all modules. + */ + run: function(block) { + runBlocks.push(block); + return this; + } + }; + + if (configFn) { + config(configFn); + } + + return moduleInstance; + + /** + * @param {string} provider + * @param {string} method + * @param {String=} insertMethod + * @returns {angular.Module} + */ + function invokeLater(provider, method, insertMethod) { + return function() { + invokeQueue[insertMethod || 'push']([provider, method, arguments]); + return moduleInstance; + }; + } + }); + }; + }); + +} + +/* global + angularModule: true, + version: true, + + $LocaleProvider, + $CompileProvider, + + htmlAnchorDirective, + inputDirective, + inputDirective, + formDirective, + scriptDirective, + selectDirective, + styleDirective, + optionDirective, + ngBindDirective, + ngBindHtmlDirective, + ngBindTemplateDirective, + ngClassDirective, + ngClassEvenDirective, + ngClassOddDirective, + ngCspDirective, + ngCloakDirective, + ngControllerDirective, + ngFormDirective, + ngHideDirective, + ngIfDirective, + ngIncludeDirective, + ngInitDirective, + ngNonBindableDirective, + ngPluralizeDirective, + ngRepeatDirective, + ngShowDirective, + ngStyleDirective, + ngSwitchDirective, + ngSwitchWhenDirective, + ngSwitchDefaultDirective, + ngOptionsDirective, + ngTranscludeDirective, + ngModelDirective, + ngListDirective, + ngChangeDirective, + requiredDirective, + requiredDirective, + ngValueDirective, + ngAttributeAliasDirectives, + ngEventDirectives, + + $AnchorScrollProvider, + $AnimateProvider, + $BrowserProvider, + $CacheFactoryProvider, + $ControllerProvider, + $DocumentProvider, + $ExceptionHandlerProvider, + $FilterProvider, + $InterpolateProvider, + $IntervalProvider, + $HttpProvider, + $HttpBackendProvider, + $LocationProvider, + $LogProvider, + $ParseProvider, + $RootScopeProvider, + $QProvider, + $$SanitizeUriProvider, + $SceProvider, + $SceDelegateProvider, + $SnifferProvider, + $TemplateCacheProvider, + $TimeoutProvider, + $WindowProvider +*/ + + +/** + * @ngdoc property + * @name angular.version + * @description + * An object that contains information about the current AngularJS version. This object has the + * following properties: + * + * - `full` – `{string}` – Full version string, such as "0.9.18". + * - `major` – `{number}` – Major version number, such as "0". + * - `minor` – `{number}` – Minor version number, such as "9". + * - `dot` – `{number}` – Dot version number, such as "18". + * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". + */ +var version = { + full: '1.2.3', // all of these placeholder strings will be replaced by grunt's + major: 1, // package task + minor: 2, + dot: 3, + codeName: 'unicorn-zapper' +}; + + +function publishExternalAPI(angular){ + extend(angular, { + 'bootstrap': bootstrap, + 'copy': copy, + 'extend': extend, + 'equals': equals, + 'element': jqLite, + 'forEach': forEach, + 'injector': createInjector, + 'noop':noop, + 'bind':bind, + 'toJson': toJson, + 'fromJson': fromJson, + 'identity':identity, + 'isUndefined': isUndefined, + 'isDefined': isDefined, + 'isString': isString, + 'isFunction': isFunction, + 'isObject': isObject, + 'isNumber': isNumber, + 'isElement': isElement, + 'isArray': isArray, + 'version': version, + 'isDate': isDate, + 'lowercase': lowercase, + 'uppercase': uppercase, + 'callbacks': {counter: 0}, + '$$minErr': minErr, + '$$csp': csp + }); + + angularModule = setupModuleLoader(window); + try { + angularModule('ngLocale'); + } catch (e) { + angularModule('ngLocale', []).provider('$locale', $LocaleProvider); + } + + angularModule('ng', ['ngLocale'], ['$provide', + function ngModule($provide) { + // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it. + $provide.provider({ + $$sanitizeUri: $$SanitizeUriProvider + }); + $provide.provider('$compile', $CompileProvider). + directive({ + a: htmlAnchorDirective, + input: inputDirective, + textarea: inputDirective, + form: formDirective, + script: scriptDirective, + select: selectDirective, + style: styleDirective, + option: optionDirective, + ngBind: ngBindDirective, + ngBindHtml: ngBindHtmlDirective, + ngBindTemplate: ngBindTemplateDirective, + ngClass: ngClassDirective, + ngClassEven: ngClassEvenDirective, + ngClassOdd: ngClassOddDirective, + ngCloak: ngCloakDirective, + ngController: ngControllerDirective, + ngForm: ngFormDirective, + ngHide: ngHideDirective, + ngIf: ngIfDirective, + ngInclude: ngIncludeDirective, + ngInit: ngInitDirective, + ngNonBindable: ngNonBindableDirective, + ngPluralize: ngPluralizeDirective, + ngRepeat: ngRepeatDirective, + ngShow: ngShowDirective, + ngStyle: ngStyleDirective, + ngSwitch: ngSwitchDirective, + ngSwitchWhen: ngSwitchWhenDirective, + ngSwitchDefault: ngSwitchDefaultDirective, + ngOptions: ngOptionsDirective, + ngTransclude: ngTranscludeDirective, + ngModel: ngModelDirective, + ngList: ngListDirective, + ngChange: ngChangeDirective, + required: requiredDirective, + ngRequired: requiredDirective, + ngValue: ngValueDirective + }). + directive(ngAttributeAliasDirectives). + directive(ngEventDirectives); + $provide.provider({ + $anchorScroll: $AnchorScrollProvider, + $animate: $AnimateProvider, + $browser: $BrowserProvider, + $cacheFactory: $CacheFactoryProvider, + $controller: $ControllerProvider, + $document: $DocumentProvider, + $exceptionHandler: $ExceptionHandlerProvider, + $filter: $FilterProvider, + $interpolate: $InterpolateProvider, + $interval: $IntervalProvider, + $http: $HttpProvider, + $httpBackend: $HttpBackendProvider, + $location: $LocationProvider, + $log: $LogProvider, + $parse: $ParseProvider, + $rootScope: $RootScopeProvider, + $q: $QProvider, + $sce: $SceProvider, + $sceDelegate: $SceDelegateProvider, + $sniffer: $SnifferProvider, + $templateCache: $TemplateCacheProvider, + $timeout: $TimeoutProvider, + $window: $WindowProvider + }); + } + ]); +} + +/* global + + -JQLitePrototype, + -addEventListenerFn, + -removeEventListenerFn, + -BOOLEAN_ATTR +*/ + +////////////////////////////////// +//JQLite +////////////////////////////////// + +/** + * @ngdoc function + * @name angular.element + * @function + * + * @description + * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. + * + * If jQuery is available, `angular.element` is an alias for the + * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` + * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite." + * + *
jqLite is a tiny, API-compatible subset of jQuery that allows + * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most + * commonly needed functionality with the goal of having a very small footprint.
+ * + * To use jQuery, simply load it before `DOMContentLoaded` event fired. + * + *
**Note:** all element references in Angular are always wrapped with jQuery or + * jqLite; they are never raw DOM references.
+ * + * ## Angular's jqLite + * jqLite provides only the following jQuery methods: + * + * - [`addClass()`](http://api.jquery.com/addClass/) + * - [`after()`](http://api.jquery.com/after/) + * - [`append()`](http://api.jquery.com/append/) + * - [`attr()`](http://api.jquery.com/attr/) + * - [`bind()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData + * - [`children()`](http://api.jquery.com/children/) - Does not support selectors + * - [`clone()`](http://api.jquery.com/clone/) + * - [`contents()`](http://api.jquery.com/contents/) + * - [`css()`](http://api.jquery.com/css/) + * - [`data()`](http://api.jquery.com/data/) + * - [`eq()`](http://api.jquery.com/eq/) + * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name + * - [`hasClass()`](http://api.jquery.com/hasClass/) + * - [`html()`](http://api.jquery.com/html/) + * - [`next()`](http://api.jquery.com/next/) - Does not support selectors + * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData + * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors + * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors + * - [`prepend()`](http://api.jquery.com/prepend/) + * - [`prop()`](http://api.jquery.com/prop/) + * - [`ready()`](http://api.jquery.com/ready/) + * - [`remove()`](http://api.jquery.com/remove/) + * - [`removeAttr()`](http://api.jquery.com/removeAttr/) + * - [`removeClass()`](http://api.jquery.com/removeClass/) + * - [`removeData()`](http://api.jquery.com/removeData/) + * - [`replaceWith()`](http://api.jquery.com/replaceWith/) + * - [`text()`](http://api.jquery.com/text/) + * - [`toggleClass()`](http://api.jquery.com/toggleClass/) + * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. + * - [`unbind()`](http://api.jquery.com/off/) - Does not support namespaces + * - [`val()`](http://api.jquery.com/val/) + * - [`wrap()`](http://api.jquery.com/wrap/) + * + * ## jQuery/jqLite Extras + * Angular also provides the following additional methods and events to both jQuery and jqLite: + * + * ### Events + * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event + * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM + * element before it is removed. + * + * ### Methods + * - `controller(name)` - retrieves the controller of the current element or its parent. By default + * retrieves controller associated with the `ngController` directive. If `name` is provided as + * camelCase directive name, then the controller for this directive will be retrieved (e.g. + * `'ngModel'`). + * - `injector()` - retrieves the injector of the current element or its parent. + * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current + * element or its parent. + * - `isolateScope()` - retrieves an isolate {@link api/ng.$rootScope.Scope scope} if one is attached directly to the + * current element. This getter should be used only on elements that contain a directive which starts a new isolate + * scope. Calling `scope()` on this element always returns the original non-isolate scope. + * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top + * parent element is reached. + * + * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. + * @returns {Object} jQuery object. + */ + +var jqCache = JQLite.cache = {}, + jqName = JQLite.expando = 'ng-' + new Date().getTime(), + jqId = 1, + addEventListenerFn = (window.document.addEventListener + ? function(element, type, fn) {element.addEventListener(type, fn, false);} + : function(element, type, fn) {element.attachEvent('on' + type, fn);}), + removeEventListenerFn = (window.document.removeEventListener + ? function(element, type, fn) {element.removeEventListener(type, fn, false); } + : function(element, type, fn) {element.detachEvent('on' + type, fn); }); + +function jqNextId() { return ++jqId; } + + +var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; +var MOZ_HACK_REGEXP = /^moz([A-Z])/; +var jqLiteMinErr = minErr('jqLite'); + +/** + * Converts snake_case to camelCase. + * Also there is special case for Moz prefix starting with upper case letter. + * @param name Name to normalize + */ +function camelCase(name) { + return name. + replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }). + replace(MOZ_HACK_REGEXP, 'Moz$1'); +} + +///////////////////////////////////////////// +// jQuery mutation patch +// +// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a +// $destroy event on all DOM nodes being removed. +// +///////////////////////////////////////////// + +function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) { + var originalJqFn = jQuery.fn[name]; + originalJqFn = originalJqFn.$original || originalJqFn; + removePatch.$original = originalJqFn; + jQuery.fn[name] = removePatch; + + function removePatch(param) { + // jshint -W040 + var list = filterElems && param ? [this.filter(param)] : [this], + fireEvent = dispatchThis, + set, setIndex, setLength, + element, childIndex, childLength, children; + + if (!getterIfNoArguments || param != null) { + while(list.length) { + set = list.shift(); + for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) { + element = jqLite(set[setIndex]); + if (fireEvent) { + element.triggerHandler('$destroy'); + } else { + fireEvent = !fireEvent; + } + for(childIndex = 0, childLength = (children = element.children()).length; + childIndex < childLength; + childIndex++) { + list.push(jQuery(children[childIndex])); + } + } + } + } + return originalJqFn.apply(this, arguments); + } +} + +///////////////////////////////////////////// +function JQLite(element) { + if (element instanceof JQLite) { + return element; + } + if (!(this instanceof JQLite)) { + if (isString(element) && element.charAt(0) != '<') { + throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); + } + return new JQLite(element); + } + + if (isString(element)) { + var div = document.createElement('div'); + // Read about the NoScope elements here: + // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx + div.innerHTML = '
 
' + element; // IE insanity to make NoScope elements work! + div.removeChild(div.firstChild); // remove the superfluous div + jqLiteAddNodes(this, div.childNodes); + var fragment = jqLite(document.createDocumentFragment()); + fragment.append(this); // detach the elements from the temporary DOM div. + } else { + jqLiteAddNodes(this, element); + } +} + +function jqLiteClone(element) { + return element.cloneNode(true); +} + +function jqLiteDealoc(element){ + jqLiteRemoveData(element); + for ( var i = 0, children = element.childNodes || []; i < children.length; i++) { + jqLiteDealoc(children[i]); + } +} + +function jqLiteOff(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument'); + + var events = jqLiteExpandoStore(element, 'events'), + handle = jqLiteExpandoStore(element, 'handle'); + + if (!handle) return; //no listeners registered + + if (isUndefined(type)) { + forEach(events, function(eventHandler, type) { + removeEventListenerFn(element, type, eventHandler); + delete events[type]; + }); + } else { + forEach(type.split(' '), function(type) { + if (isUndefined(fn)) { + removeEventListenerFn(element, type, events[type]); + delete events[type]; + } else { + arrayRemove(events[type] || [], fn); + } + }); + } +} + +function jqLiteRemoveData(element, name) { + var expandoId = element[jqName], + expandoStore = jqCache[expandoId]; + + if (expandoStore) { + if (name) { + delete jqCache[expandoId].data[name]; + return; + } + + if (expandoStore.handle) { + expandoStore.events.$destroy && expandoStore.handle({}, '$destroy'); + jqLiteOff(element); + } + delete jqCache[expandoId]; + element[jqName] = undefined; // ie does not allow deletion of attributes on elements. + } +} + +function jqLiteExpandoStore(element, key, value) { + var expandoId = element[jqName], + expandoStore = jqCache[expandoId || -1]; + + if (isDefined(value)) { + if (!expandoStore) { + element[jqName] = expandoId = jqNextId(); + expandoStore = jqCache[expandoId] = {}; + } + expandoStore[key] = value; + } else { + return expandoStore && expandoStore[key]; + } +} + +function jqLiteData(element, key, value) { + var data = jqLiteExpandoStore(element, 'data'), + isSetter = isDefined(value), + keyDefined = !isSetter && isDefined(key), + isSimpleGetter = keyDefined && !isObject(key); + + if (!data && !isSimpleGetter) { + jqLiteExpandoStore(element, 'data', data = {}); + } + + if (isSetter) { + data[key] = value; + } else { + if (keyDefined) { + if (isSimpleGetter) { + // don't create data in this case. + return data && data[key]; + } else { + extend(data, key); + } + } else { + return data; + } + } +} + +function jqLiteHasClass(element, selector) { + if (!element.getAttribute) return false; + return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). + indexOf( " " + selector + " " ) > -1); +} + +function jqLiteRemoveClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + forEach(cssClasses.split(' '), function(cssClass) { + element.setAttribute('class', trim( + (" " + (element.getAttribute('class') || '') + " ") + .replace(/[\n\t]/g, " ") + .replace(" " + trim(cssClass) + " ", " ")) + ); + }); + } +} + +function jqLiteAddClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ') + .replace(/[\n\t]/g, " "); + + forEach(cssClasses.split(' '), function(cssClass) { + cssClass = trim(cssClass); + if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) { + existingClasses += cssClass + ' '; + } + }); + + element.setAttribute('class', trim(existingClasses)); + } +} + +function jqLiteAddNodes(root, elements) { + if (elements) { + elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements)) + ? elements + : [ elements ]; + for(var i=0; i < elements.length; i++) { + root.push(elements[i]); + } + } +} + +function jqLiteController(element, name) { + return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller'); +} + +function jqLiteInheritedData(element, name, value) { + element = jqLite(element); + + // if element is the document object work with the html element instead + // this makes $(document).scope() possible + if(element[0].nodeType == 9) { + element = element.find('html'); + } + var names = isArray(name) ? name : [name]; + + while (element.length) { + + for (var i = 0, ii = names.length; i < ii; i++) { + if ((value = element.data(names[i])) !== undefined) return value; + } + element = element.parent(); + } +} + +////////////////////////////////////////// +// Functions which are declared directly. +////////////////////////////////////////// +var JQLitePrototype = JQLite.prototype = { + ready: function(fn) { + var fired = false; + + function trigger() { + if (fired) return; + fired = true; + fn(); + } + + // check if document already is loaded + if (document.readyState === 'complete'){ + setTimeout(trigger); + } else { + this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 + // we can not use jqLite since we are not done loading and jQuery could be loaded later. + // jshint -W064 + JQLite(window).on('load', trigger); // fallback to window.onload for others + // jshint +W064 + } + }, + toString: function() { + var value = []; + forEach(this, function(e){ value.push('' + e);}); + return '[' + value.join(', ') + ']'; + }, + + eq: function(index) { + return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); + }, + + length: 0, + push: push, + sort: [].sort, + splice: [].splice +}; + +////////////////////////////////////////// +// Functions iterating getter/setters. +// these functions return self on setter and +// value on get. +////////////////////////////////////////// +var BOOLEAN_ATTR = {}; +forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) { + BOOLEAN_ATTR[lowercase(value)] = value; +}); +var BOOLEAN_ELEMENTS = {}; +forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { + BOOLEAN_ELEMENTS[uppercase(value)] = true; +}); + +function getBooleanAttrName(element, name) { + // check dom last since we will most likely fail on name + var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; + + // booleanAttr is here twice to minimize DOM access + return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr; +} + +forEach({ + data: jqLiteData, + inheritedData: jqLiteInheritedData, + + scope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite(element).data('$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']); + }, + + isolateScope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite(element).data('$isolateScope') || jqLite(element).data('$isolateScopeNoTemplate'); + }, + + controller: jqLiteController , + + injector: function(element) { + return jqLiteInheritedData(element, '$injector'); + }, + + removeAttr: function(element,name) { + element.removeAttribute(name); + }, + + hasClass: jqLiteHasClass, + + css: function(element, name, value) { + name = camelCase(name); + + if (isDefined(value)) { + element.style[name] = value; + } else { + var val; + + if (msie <= 8) { + // this is some IE specific weirdness that jQuery 1.6.4 does not sure why + val = element.currentStyle && element.currentStyle[name]; + if (val === '') val = 'auto'; + } + + val = val || element.style[name]; + + if (msie <= 8) { + // jquery weirdness :-/ + val = (val === '') ? undefined : val; + } + + return val; + } + }, + + attr: function(element, name, value){ + var lowercasedName = lowercase(name); + if (BOOLEAN_ATTR[lowercasedName]) { + if (isDefined(value)) { + if (!!value) { + element[name] = true; + element.setAttribute(name, lowercasedName); + } else { + element[name] = false; + element.removeAttribute(lowercasedName); + } + } else { + return (element[name] || + (element.attributes.getNamedItem(name)|| noop).specified) + ? lowercasedName + : undefined; + } + } else if (isDefined(value)) { + element.setAttribute(name, value); + } else if (element.getAttribute) { + // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code + // some elements (e.g. Document) don't have get attribute, so return undefined + var ret = element.getAttribute(name, 2); + // normalize non-existing attributes to undefined (as jQuery) + return ret === null ? undefined : ret; + } + }, + + prop: function(element, name, value) { + if (isDefined(value)) { + element[name] = value; + } else { + return element[name]; + } + }, + + text: (function() { + var NODE_TYPE_TEXT_PROPERTY = []; + if (msie < 9) { + NODE_TYPE_TEXT_PROPERTY[1] = 'innerText'; /** Element **/ + NODE_TYPE_TEXT_PROPERTY[3] = 'nodeValue'; /** Text **/ + } else { + NODE_TYPE_TEXT_PROPERTY[1] = /** Element **/ + NODE_TYPE_TEXT_PROPERTY[3] = 'textContent'; /** Text **/ + } + getText.$dv = ''; + return getText; + + function getText(element, value) { + var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType]; + if (isUndefined(value)) { + return textProp ? element[textProp] : ''; + } + element[textProp] = value; + } + })(), + + val: function(element, value) { + if (isUndefined(value)) { + if (nodeName_(element) === 'SELECT' && element.multiple) { + var result = []; + forEach(element.options, function (option) { + if (option.selected) { + result.push(option.value || option.text); + } + }); + return result.length === 0 ? null : result; + } + return element.value; + } + element.value = value; + }, + + html: function(element, value) { + if (isUndefined(value)) { + return element.innerHTML; + } + for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) { + jqLiteDealoc(childNodes[i]); + } + element.innerHTML = value; + } +}, function(fn, name){ + /** + * Properties: writes return selection, reads return first value + */ + JQLite.prototype[name] = function(arg1, arg2) { + var i, key; + + // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it + // in a way that survives minification. + if (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined) { + if (isObject(arg1)) { + + // we are a write, but the object properties are the key/values + for(i=0; i < this.length; i++) { + if (fn === jqLiteData) { + // data() takes the whole object in jQuery + fn(this[i], arg1); + } else { + for (key in arg1) { + fn(this[i], key, arg1[key]); + } + } + } + // return self for chaining + return this; + } else { + // we are a read, so read the first child. + var value = fn.$dv; + // Only if we have $dv do we iterate over all, otherwise it is just the first element. + var jj = (value === undefined) ? Math.min(this.length, 1) : this.length; + for (var j = 0; j < jj; j++) { + var nodeValue = fn(this[j], arg1, arg2); + value = value ? value + nodeValue : nodeValue; + } + return value; + } + } else { + // we are a write, so apply to all children + for(i=0; i < this.length; i++) { + fn(this[i], arg1, arg2); + } + // return self for chaining + return this; + } + }; +}); + +function createEventHandler(element, events) { + var eventHandler = function (event, type) { + if (!event.preventDefault) { + event.preventDefault = function() { + event.returnValue = false; //ie + }; + } + + if (!event.stopPropagation) { + event.stopPropagation = function() { + event.cancelBubble = true; //ie + }; + } + + if (!event.target) { + event.target = event.srcElement || document; + } + + if (isUndefined(event.defaultPrevented)) { + var prevent = event.preventDefault; + event.preventDefault = function() { + event.defaultPrevented = true; + prevent.call(event); + }; + event.defaultPrevented = false; + } + + event.isDefaultPrevented = function() { + return event.defaultPrevented || event.returnValue === false; + }; + + forEach(events[type || event.type], function(fn) { + fn.call(element, event); + }); + + // Remove monkey-patched methods (IE), + // as they would cause memory leaks in IE8. + if (msie <= 8) { + // IE7/8 does not allow to delete property on native object + event.preventDefault = null; + event.stopPropagation = null; + event.isDefaultPrevented = null; + } else { + // It shouldn't affect normal browsers (native methods are defined on prototype). + delete event.preventDefault; + delete event.stopPropagation; + delete event.isDefaultPrevented; + } + }; + eventHandler.elem = element; + return eventHandler; +} + +////////////////////////////////////////// +// Functions iterating traversal. +// These functions chain results into a single +// selector. +////////////////////////////////////////// +forEach({ + removeData: jqLiteRemoveData, + + dealoc: jqLiteDealoc, + + on: function onFn(element, type, fn, unsupported){ + if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters'); + + var events = jqLiteExpandoStore(element, 'events'), + handle = jqLiteExpandoStore(element, 'handle'); + + if (!events) jqLiteExpandoStore(element, 'events', events = {}); + if (!handle) jqLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events)); + + forEach(type.split(' '), function(type){ + var eventFns = events[type]; + + if (!eventFns) { + if (type == 'mouseenter' || type == 'mouseleave') { + var contains = document.body.contains || document.body.compareDocumentPosition ? + function( a, b ) { + // jshint bitwise: false + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + events[type] = []; + + // Refer to jQuery's implementation of mouseenter & mouseleave + // Read about mouseenter and mouseleave: + // http://www.quirksmode.org/js/events_mouse.html#link8 + var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"}; + + onFn(element, eventmap[type], function(event) { + var target = this, related = event.relatedTarget; + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !contains(target, related)) ){ + handle(event, type); + } + }); + + } else { + addEventListenerFn(element, type, handle); + events[type] = []; + } + eventFns = events[type]; + } + eventFns.push(fn); + }); + }, + + off: jqLiteOff, + + replaceWith: function(element, replaceNode) { + var index, parent = element.parentNode; + jqLiteDealoc(element); + forEach(new JQLite(replaceNode), function(node){ + if (index) { + parent.insertBefore(node, index.nextSibling); + } else { + parent.replaceChild(node, element); + } + index = node; + }); + }, + + children: function(element) { + var children = []; + forEach(element.childNodes, function(element){ + if (element.nodeType === 1) + children.push(element); + }); + return children; + }, + + contents: function(element) { + return element.childNodes || []; + }, + + append: function(element, node) { + forEach(new JQLite(node), function(child){ + if (element.nodeType === 1 || element.nodeType === 11) { + element.appendChild(child); + } + }); + }, + + prepend: function(element, node) { + if (element.nodeType === 1) { + var index = element.firstChild; + forEach(new JQLite(node), function(child){ + element.insertBefore(child, index); + }); + } + }, + + wrap: function(element, wrapNode) { + wrapNode = jqLite(wrapNode)[0]; + var parent = element.parentNode; + if (parent) { + parent.replaceChild(wrapNode, element); + } + wrapNode.appendChild(element); + }, + + remove: function(element) { + jqLiteDealoc(element); + var parent = element.parentNode; + if (parent) parent.removeChild(element); + }, + + after: function(element, newElement) { + var index = element, parent = element.parentNode; + forEach(new JQLite(newElement), function(node){ + parent.insertBefore(node, index.nextSibling); + index = node; + }); + }, + + addClass: jqLiteAddClass, + removeClass: jqLiteRemoveClass, + + toggleClass: function(element, selector, condition) { + if (isUndefined(condition)) { + condition = !jqLiteHasClass(element, selector); + } + (condition ? jqLiteAddClass : jqLiteRemoveClass)(element, selector); + }, + + parent: function(element) { + var parent = element.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + + next: function(element) { + if (element.nextElementSibling) { + return element.nextElementSibling; + } + + // IE8 doesn't have nextElementSibling + var elm = element.nextSibling; + while (elm != null && elm.nodeType !== 1) { + elm = elm.nextSibling; + } + return elm; + }, + + find: function(element, selector) { + return element.getElementsByTagName(selector); + }, + + clone: jqLiteClone, + + triggerHandler: function(element, eventName, eventData) { + var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName]; + + eventData = eventData || []; + + var event = [{ + preventDefault: noop, + stopPropagation: noop + }]; + + forEach(eventFns, function(fn) { + fn.apply(element, event.concat(eventData)); + }); + } +}, function(fn, name){ + /** + * chaining functions + */ + JQLite.prototype[name] = function(arg1, arg2, arg3) { + var value; + for(var i=0; i < this.length; i++) { + if (isUndefined(value)) { + value = fn(this[i], arg1, arg2, arg3); + if (isDefined(value)) { + // any function which returns a value needs to be wrapped + value = jqLite(value); + } + } else { + jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); + } + } + return isDefined(value) ? value : this; + }; + + // bind legacy bind/unbind to on/off + JQLite.prototype.bind = JQLite.prototype.on; + JQLite.prototype.unbind = JQLite.prototype.off; +}); + +/** + * Computes a hash of an 'obj'. + * Hash of a: + * string is string + * number is number as string + * object is either result of calling $$hashKey function on the object or uniquely generated id, + * that is also assigned to the $$hashKey property of the object. + * + * @param obj + * @returns {string} hash string such that the same input will have the same hash string. + * The resulting string key is in 'type:hashKey' format. + */ +function hashKey(obj) { + var objType = typeof obj, + key; + + if (objType == 'object' && obj !== null) { + if (typeof (key = obj.$$hashKey) == 'function') { + // must invoke on object to keep the right this + key = obj.$$hashKey(); + } else if (key === undefined) { + key = obj.$$hashKey = nextUid(); + } + } else { + key = obj; + } + + return objType + ':' + key; +} + +/** + * HashMap which can use objects as keys + */ +function HashMap(array){ + forEach(array, this.put, this); +} +HashMap.prototype = { + /** + * Store key value pair + * @param key key to store can be any type + * @param value value to store can be any type + */ + put: function(key, value) { + this[hashKey(key)] = value; + }, + + /** + * @param key + * @returns the value for the key + */ + get: function(key) { + return this[hashKey(key)]; + }, + + /** + * Remove the key/value pair + * @param key + */ + remove: function(key) { + var value = this[key = hashKey(key)]; + delete this[key]; + return value; + } +}; + +/** + * @ngdoc function + * @name angular.injector + * @function + * + * @description + * Creates an injector function that can be used for retrieving services as well as for + * dependency injection (see {@link guide/di dependency injection}). + * + + * @param {Array.} modules A list of module functions or their aliases. See + * {@link angular.module}. The `ng` module must be explicitly added. + * @returns {function()} Injector function. See {@link AUTO.$injector $injector}. + * + * @example + * Typical usage + *
+ *   // create an injector
+ *   var $injector = angular.injector(['ng']);
+ *
+ *   // use the injector to kick off your application
+ *   // use the type inference to auto inject arguments, or use implicit injection
+ *   $injector.invoke(function($rootScope, $compile, $document){
+ *     $compile($document)($rootScope);
+ *     $rootScope.$digest();
+ *   });
+ * 
+ */ + + +/** + * @ngdoc overview + * @name AUTO + * @description + * + * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}. + */ + +var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; +var FN_ARG_SPLIT = /,/; +var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; +var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; +var $injectorMinErr = minErr('$injector'); +function annotate(fn) { + var $inject, + fnText, + argDecl, + last; + + if (typeof fn == 'function') { + if (!($inject = fn.$inject)) { + $inject = []; + if (fn.length) { + fnText = fn.toString().replace(STRIP_COMMENTS, ''); + argDecl = fnText.match(FN_ARGS); + forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){ + arg.replace(FN_ARG, function(all, underscore, name){ + $inject.push(name); + }); + }); + } + fn.$inject = $inject; + } + } else if (isArray(fn)) { + last = fn.length - 1; + assertArgFn(fn[last], 'fn'); + $inject = fn.slice(0, last); + } else { + assertArgFn(fn, 'fn', true); + } + return $inject; +} + +/////////////////////////////////////// + +/** + * @ngdoc object + * @name AUTO.$injector + * @function + * + * @description + * + * `$injector` is used to retrieve object instances as defined by + * {@link AUTO.$provide provider}, instantiate types, invoke methods, + * and load modules. + * + * The following always holds true: + * + *
+ *   var $injector = angular.injector();
+ *   expect($injector.get('$injector')).toBe($injector);
+ *   expect($injector.invoke(function($injector){
+ *     return $injector;
+ *   }).toBe($injector);
+ * 
+ * + * # Injection Function Annotation + * + * JavaScript does not have annotations, and annotations are needed for dependency injection. The + * following are all valid ways of annotating function with injection arguments and are equivalent. + * + *
+ *   // inferred (only works if code not minified/obfuscated)
+ *   $injector.invoke(function(serviceA){});
+ *
+ *   // annotated
+ *   function explicit(serviceA) {};
+ *   explicit.$inject = ['serviceA'];
+ *   $injector.invoke(explicit);
+ *
+ *   // inline
+ *   $injector.invoke(['serviceA', function(serviceA){}]);
+ * 
+ * + * ## Inference + * + * In JavaScript calling `toString()` on a function returns the function definition. The definition + * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with + * minification, and obfuscation tools since these tools change the argument names. + * + * ## `$inject` Annotation + * By adding a `$inject` property onto a function the injection parameters can be specified. + * + * ## Inline + * As an array of injection names, where the last item in the array is the function to call. + */ + +/** + * @ngdoc method + * @name AUTO.$injector#get + * @methodOf AUTO.$injector + * + * @description + * Return an instance of the service. + * + * @param {string} name The name of the instance to retrieve. + * @return {*} The instance. + */ + +/** + * @ngdoc method + * @name AUTO.$injector#invoke + * @methodOf AUTO.$injector + * + * @description + * Invoke the method and supply the method arguments from the `$injector`. + * + * @param {!function} fn The function to invoke. Function parameters are injected according to the + * {@link guide/di $inject Annotation} rules. + * @param {Object=} self The `this` for the invoked method. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {*} the value returned by the invoked `fn` function. + */ + +/** + * @ngdoc method + * @name AUTO.$injector#has + * @methodOf AUTO.$injector + * + * @description + * Allows the user to query if the particular service exist. + * + * @param {string} Name of the service to query. + * @returns {boolean} returns true if injector has given service. + */ + +/** + * @ngdoc method + * @name AUTO.$injector#instantiate + * @methodOf AUTO.$injector + * @description + * Create a new instance of JS type. The method takes a constructor function invokes the new + * operator and supplies all of the arguments to the constructor function as specified by the + * constructor annotation. + * + * @param {function} Type Annotated constructor function. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {Object} new instance of `Type`. + */ + +/** + * @ngdoc method + * @name AUTO.$injector#annotate + * @methodOf AUTO.$injector + * + * @description + * Returns an array of service names which the function is requesting for injection. This API is + * used by the injector to determine which services need to be injected into the function when the + * function is invoked. There are three ways in which the function can be annotated with the needed + * dependencies. + * + * # Argument names + * + * The simplest form is to extract the dependencies from the arguments of the function. This is done + * by converting the function into a string using `toString()` method and extracting the argument + * names. + *
+ *   // Given
+ *   function MyController($scope, $route) {
+ *     // ...
+ *   }
+ *
+ *   // Then
+ *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * 
+ * + * This method does not work with code minification / obfuscation. For this reason the following + * annotation strategies are supported. + * + * # The `$inject` property + * + * If a function has an `$inject` property and its value is an array of strings, then the strings + * represent names of services to be injected into the function. + *
+ *   // Given
+ *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
+ *     // ...
+ *   }
+ *   // Define function dependencies
+ *   MyController.$inject = ['$scope', '$route'];
+ *
+ *   // Then
+ *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * 
+ * + * # The array notation + * + * It is often desirable to inline Injected functions and that's when setting the `$inject` property + * is very inconvenient. In these situations using the array notation to specify the dependencies in + * a way that survives minification is a better choice: + * + *
+ *   // We wish to write this (not minification / obfuscation safe)
+ *   injector.invoke(function($compile, $rootScope) {
+ *     // ...
+ *   });
+ *
+ *   // We are forced to write break inlining
+ *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
+ *     // ...
+ *   };
+ *   tmpFn.$inject = ['$compile', '$rootScope'];
+ *   injector.invoke(tmpFn);
+ *
+ *   // To better support inline function the inline annotation is supported
+ *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
+ *     // ...
+ *   }]);
+ *
+ *   // Therefore
+ *   expect(injector.annotate(
+ *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
+ *    ).toEqual(['$compile', '$rootScope']);
+ * 
+ * + * @param {function|Array.} fn Function for which dependent service names need to + * be retrieved as described above. + * + * @returns {Array.} The names of the services which the function requires. + */ + + + + +/** + * @ngdoc object + * @name AUTO.$provide + * + * @description + * + * The {@link AUTO.$provide $provide} service has a number of methods for registering components + * with the {@link AUTO.$injector $injector}. Many of these functions are also exposed on + * {@link angular.Module}. + * + * An Angular **service** is a singleton object created by a **service factory**. These **service + * factories** are functions which, in turn, are created by a **service provider**. + * The **service providers** are constructor functions. When instantiated they must contain a + * property called `$get`, which holds the **service factory** function. + * + * When you request a service, the {@link AUTO.$injector $injector} is responsible for finding the + * correct **service provider**, instantiating it and then calling its `$get` **service factory** + * function to get the instance of the **service**. + * + * Often services have no configuration options and there is no need to add methods to the service + * provider. The provider will be no more than a constructor function with a `$get` property. For + * these cases the {@link AUTO.$provide $provide} service has additional helper methods to register + * services without specifying a provider. + * + * * {@link AUTO.$provide#methods_provider provider(provider)} - registers a **service provider** with the + * {@link AUTO.$injector $injector} + * * {@link AUTO.$provide#methods_constant constant(obj)} - registers a value/object that can be accessed by + * providers and services. + * * {@link AUTO.$provide#methods_value value(obj)} - registers a value/object that can only be accessed by + * services, not providers. + * * {@link AUTO.$provide#methods_factory factory(fn)} - registers a service **factory function**, `fn`, + * that will be wrapped in a **service provider** object, whose `$get` property will contain the + * given factory function. + * * {@link AUTO.$provide#methods_service service(class)} - registers a **constructor function**, `class` that + * that will be wrapped in a **service provider** object, whose `$get` property will instantiate + * a new object using the given constructor function. + * + * See the individual methods for more information and examples. + */ + +/** + * @ngdoc method + * @name AUTO.$provide#provider + * @methodOf AUTO.$provide + * @description + * + * Register a **provider function** with the {@link AUTO.$injector $injector}. Provider functions + * are constructor functions, whose instances are responsible for "providing" a factory for a + * service. + * + * Service provider names start with the name of the service they provide followed by `Provider`. + * For example, the {@link ng.$log $log} service has a provider called + * {@link ng.$logProvider $logProvider}. + * + * Service provider objects can have additional methods which allow configuration of the provider + * and its service. Importantly, you can configure what kind of service is created by the `$get` + * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a + * method {@link ng.$logProvider#debugEnabled debugEnabled} + * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the + * console or not. + * + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + + 'Provider'` key. + * @param {(Object|function())} provider If the provider is: + * + * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using + * {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be + * created. + * - `Constructor`: a new instance of the provider will be created using + * {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as + * `object`. + * + * @returns {Object} registered provider instance + + * @example + * + * The following example shows how to create a simple event tracking service and register it using + * {@link AUTO.$provide#methods_provider $provide.provider()}. + * + *
+ *  // Define the eventTracker provider
+ *  function EventTrackerProvider() {
+ *    var trackingUrl = '/track';
+ *
+ *    // A provider method for configuring where the tracked events should been saved
+ *    this.setTrackingUrl = function(url) {
+ *      trackingUrl = url;
+ *    };
+ *
+ *    // The service factory function
+ *    this.$get = ['$http', function($http) {
+ *      var trackedEvents = {};
+ *      return {
+ *        // Call this to track an event
+ *        event: function(event) {
+ *          var count = trackedEvents[event] || 0;
+ *          count += 1;
+ *          trackedEvents[event] = count;
+ *          return count;
+ *        },
+ *        // Call this to save the tracked events to the trackingUrl
+ *        save: function() {
+ *          $http.post(trackingUrl, trackedEvents);
+ *        }
+ *      };
+ *    }];
+ *  }
+ *
+ *  describe('eventTracker', function() {
+ *    var postSpy;
+ *
+ *    beforeEach(module(function($provide) {
+ *      // Register the eventTracker provider
+ *      $provide.provider('eventTracker', EventTrackerProvider);
+ *    }));
+ *
+ *    beforeEach(module(function(eventTrackerProvider) {
+ *      // Configure eventTracker provider
+ *      eventTrackerProvider.setTrackingUrl('/custom-track');
+ *    }));
+ *
+ *    it('tracks events', inject(function(eventTracker) {
+ *      expect(eventTracker.event('login')).toEqual(1);
+ *      expect(eventTracker.event('login')).toEqual(2);
+ *    }));
+ *
+ *    it('saves to the tracking url', inject(function(eventTracker, $http) {
+ *      postSpy = spyOn($http, 'post');
+ *      eventTracker.event('login');
+ *      eventTracker.save();
+ *      expect(postSpy).toHaveBeenCalled();
+ *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
+ *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
+ *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
+ *    }));
+ *  });
+ * 
+ */ + +/** + * @ngdoc method + * @name AUTO.$provide#factory + * @methodOf AUTO.$provide + * @description + * + * Register a **service factory**, which will be called to return the service instance. + * This is short for registering a service where its provider consists of only a `$get` property, + * which is the given service factory function. + * You should use {@link AUTO.$provide#factory $provide.factory(getFn)} if you do not need to + * configure your service in a provider. + * + * @param {string} name The name of the instance. + * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand + * for `$provide.provider(name, {$get: $getFn})`. + * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service + *
+ *   $provide.factory('ping', ['$http', function($http) {
+ *     return function ping() {
+ *       return $http.send('/ping');
+ *     };
+ *   }]);
+ * 
+ * You would then inject and use this service like this: + *
+ *   someModule.controller('Ctrl', ['ping', function(ping) {
+ *     ping();
+ *   }]);
+ * 
+ */ + + +/** + * @ngdoc method + * @name AUTO.$provide#service + * @methodOf AUTO.$provide + * @description + * + * Register a **service constructor**, which will be invoked with `new` to create the service + * instance. + * This is short for registering a service where its provider's `$get` property is the service + * constructor function that will be used to instantiate the service instance. + * + * You should use {@link AUTO.$provide#methods_service $provide.service(class)} if you define your service + * as a type/class. This is common when using {@link http://coffeescript.org CoffeeScript}. + * + * @param {string} name The name of the instance. + * @param {Function} constructor A class (constructor function) that will be instantiated. + * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service using + * {@link AUTO.$provide#methods_service $provide.service(class)} that is defined as a CoffeeScript class. + *
+ *   class Ping
+ *     constructor: (@$http)->
+ *     send: ()=>
+ *       @$http.get('/ping')
+ *
+ *   $provide.service('ping', ['$http', Ping])
+ * 
+ * You would then inject and use this service like this: + *
+ *   someModule.controller 'Ctrl', ['ping', (ping)->
+ *     ping.send()
+ *   ]
+ * 
+ */ + + +/** + * @ngdoc method + * @name AUTO.$provide#value + * @methodOf AUTO.$provide + * @description + * + * Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a + * number, an array, an object or a function. This is short for registering a service where its + * provider's `$get` property is a factory function that takes no arguments and returns the **value + * service**. + * + * Value services are similar to constant services, except that they cannot be injected into a + * module configuration function (see {@link angular.Module#config}) but they can be overridden by + * an Angular + * {@link AUTO.$provide#decorator decorator}. + * + * @param {string} name The name of the instance. + * @param {*} value The value. + * @returns {Object} registered provider instance + * + * @example + * Here are some examples of creating value services. + *
+ *   $provide.value('ADMIN_USER', 'admin');
+ *
+ *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
+ *
+ *   $provide.value('halfOf', function(value) {
+ *     return value / 2;
+ *   });
+ * 
+ */ + + +/** + * @ngdoc method + * @name AUTO.$provide#constant + * @methodOf AUTO.$provide + * @description + * + * Register a **constant service**, such as a string, a number, an array, an object or a function, + * with the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be + * injected into a module configuration function (see {@link angular.Module#config}) and it cannot + * be overridden by an Angular {@link AUTO.$provide#decorator decorator}. + * + * @param {string} name The name of the constant. + * @param {*} value The constant value. + * @returns {Object} registered instance + * + * @example + * Here a some examples of creating constants: + *
+ *   $provide.constant('SHARD_HEIGHT', 306);
+ *
+ *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
+ *
+ *   $provide.constant('double', function(value) {
+ *     return value * 2;
+ *   });
+ * 
+ */ + + +/** + * @ngdoc method + * @name AUTO.$provide#decorator + * @methodOf AUTO.$provide + * @description + * + * Register a **service decorator** with the {@link AUTO.$injector $injector}. A service decorator + * intercepts the creation of a service, allowing it to override or modify the behaviour of the + * service. The object returned by the decorator may be the original service, or a new service + * object which replaces or wraps and delegates to the original service. + * + * @param {string} name The name of the service to decorate. + * @param {function()} decorator This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. The function is called using + * the {@link AUTO.$injector#invoke injector.invoke} method and is therefore fully injectable. + * Local injection arguments: + * + * * `$delegate` - The original service instance, which can be monkey patched, configured, + * decorated or delegated to. + * + * @example + * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting + * calls to {@link ng.$log#error $log.warn()}. + *
+ *   $provider.decorator('$log', ['$delegate', function($delegate) {
+ *     $delegate.warn = $delegate.error;
+ *     return $delegate;
+ *   }]);
+ * 
+ */ + + +function createInjector(modulesToLoad) { + var INSTANTIATING = {}, + providerSuffix = 'Provider', + path = [], + loadedModules = new HashMap(), + providerCache = { + $provide: { + provider: supportObject(provider), + factory: supportObject(factory), + service: supportObject(service), + value: supportObject(value), + constant: supportObject(constant), + decorator: decorator + } + }, + providerInjector = (providerCache.$injector = + createInternalInjector(providerCache, function() { + throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); + })), + instanceCache = {}, + instanceInjector = (instanceCache.$injector = + createInternalInjector(instanceCache, function(servicename) { + var provider = providerInjector.get(servicename + providerSuffix); + return instanceInjector.invoke(provider.$get, provider); + })); + + + forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); }); + + return instanceInjector; + + //////////////////////////////////// + // $provider + //////////////////////////////////// + + function supportObject(delegate) { + return function(key, value) { + if (isObject(key)) { + forEach(key, reverseParams(delegate)); + } else { + return delegate(key, value); + } + }; + } + + function provider(name, provider_) { + assertNotHasOwnProperty(name, 'service'); + if (isFunction(provider_) || isArray(provider_)) { + provider_ = providerInjector.instantiate(provider_); + } + if (!provider_.$get) { + throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); + } + return providerCache[name + providerSuffix] = provider_; + } + + function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } + + function service(name, constructor) { + return factory(name, ['$injector', function($injector) { + return $injector.instantiate(constructor); + }]); + } + + function value(name, val) { return factory(name, valueFn(val)); } + + function constant(name, value) { + assertNotHasOwnProperty(name, 'constant'); + providerCache[name] = value; + instanceCache[name] = value; + } + + function decorator(serviceName, decorFn) { + var origProvider = providerInjector.get(serviceName + providerSuffix), + orig$get = origProvider.$get; + + origProvider.$get = function() { + var origInstance = instanceInjector.invoke(orig$get, origProvider); + return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); + }; + } + + //////////////////////////////////// + // Module Loading + //////////////////////////////////// + function loadModules(modulesToLoad){ + var runBlocks = [], moduleFn, invokeQueue, i, ii; + forEach(modulesToLoad, function(module) { + if (loadedModules.get(module)) return; + loadedModules.put(module, true); + + try { + if (isString(module)) { + moduleFn = angularModule(module); + runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); + + for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) { + var invokeArgs = invokeQueue[i], + provider = providerInjector.get(invokeArgs[0]); + + provider[invokeArgs[1]].apply(provider, invokeArgs[2]); + } + } else if (isFunction(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else if (isArray(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else { + assertArgFn(module, 'module'); + } + } catch (e) { + if (isArray(module)) { + module = module[module.length - 1]; + } + if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { + // Safari & FF's stack traces don't contain error.message content + // unlike those of Chrome and IE + // So if stack doesn't contain message, we create a new string that contains both. + // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here. + /* jshint -W022 */ + e = e.message + '\n' + e.stack; + } + throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", + module, e.stack || e.message || e); + } + }); + return runBlocks; + } + + //////////////////////////////////// + // internal Injector + //////////////////////////////////// + + function createInternalInjector(cache, factory) { + + function getService(serviceName) { + if (cache.hasOwnProperty(serviceName)) { + if (cache[serviceName] === INSTANTIATING) { + throw $injectorMinErr('cdep', 'Circular dependency found: {0}', path.join(' <- ')); + } + return cache[serviceName]; + } else { + try { + path.unshift(serviceName); + cache[serviceName] = INSTANTIATING; + return cache[serviceName] = factory(serviceName); + } finally { + path.shift(); + } + } + } + + function invoke(fn, self, locals){ + var args = [], + $inject = annotate(fn), + length, i, + key; + + for(i = 0, length = $inject.length; i < length; i++) { + key = $inject[i]; + if (typeof key !== 'string') { + throw $injectorMinErr('itkn', + 'Incorrect injection token! Expected service name as string, got {0}', key); + } + args.push( + locals && locals.hasOwnProperty(key) + ? locals[key] + : getService(key) + ); + } + if (!fn.$inject) { + // this means that we must be an array. + fn = fn[length]; + } + + + // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke + switch (self ? -1 : args.length) { + case 0: return fn(); + case 1: return fn(args[0]); + case 2: return fn(args[0], args[1]); + case 3: return fn(args[0], args[1], args[2]); + case 4: return fn(args[0], args[1], args[2], args[3]); + case 5: return fn(args[0], args[1], args[2], args[3], args[4]); + case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); + case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8]); + case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9]); + default: return fn.apply(self, args); + } + } + + function instantiate(Type, locals) { + var Constructor = function() {}, + instance, returnedValue; + + // Check if Type is annotated and use just the given function at n-1 as parameter + // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); + Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype; + instance = new Constructor(); + returnedValue = invoke(Type, instance, locals); + + return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; + } + + return { + invoke: invoke, + instantiate: instantiate, + get: getService, + annotate: annotate, + has: function(name) { + return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); + } + }; + } +} + +/** + * @ngdoc function + * @name ng.$anchorScroll + * @requires $window + * @requires $location + * @requires $rootScope + * + * @description + * When called, it checks current value of `$location.hash()` and scroll to related element, + * according to rules specified in + * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}. + * + * It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor. + * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`. + * + * @example + + +
+ Go to bottom + You're at the bottom! +
+
+ + function ScrollCtrl($scope, $location, $anchorScroll) { + $scope.gotoBottom = function (){ + // set the location.hash to the id of + // the element you wish to scroll to. + $location.hash('bottom'); + + // call $anchorScroll() + $anchorScroll(); + } + } + + + #scrollArea { + height: 350px; + overflow: auto; + } + + #bottom { + display: block; + margin-top: 2000px; + } + +
+ */ +function $AnchorScrollProvider() { + + var autoScrollingEnabled = true; + + this.disableAutoScrolling = function() { + autoScrollingEnabled = false; + }; + + this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { + var document = $window.document; + + // helper function to get first anchor from a NodeList + // can't use filter.filter, as it accepts only instances of Array + // and IE can't convert NodeList to an array using [].slice + // TODO(vojta): use filter if we change it to accept lists as well + function getFirstAnchor(list) { + var result = null; + forEach(list, function(element) { + if (!result && lowercase(element.nodeName) === 'a') result = element; + }); + return result; + } + + function scroll() { + var hash = $location.hash(), elm; + + // empty hash, scroll to the top of the page + if (!hash) $window.scrollTo(0, 0); + + // element with given id + else if ((elm = document.getElementById(hash))) elm.scrollIntoView(); + + // first anchor with given name :-D + else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView(); + + // no element and hash == 'top', scroll to the top of the page + else if (hash === 'top') $window.scrollTo(0, 0); + } + + // does not scroll when user clicks on anchor link that is currently on + // (no url change, no $location.hash() change), browser native does scroll + if (autoScrollingEnabled) { + $rootScope.$watch(function autoScrollWatch() {return $location.hash();}, + function autoScrollWatchAction() { + $rootScope.$evalAsync(scroll); + }); + } + + return scroll; + }]; +} + +var $animateMinErr = minErr('$animate'); + +/** + * @ngdoc object + * @name ng.$animateProvider + * + * @description + * Default implementation of $animate that doesn't perform any animations, instead just + * synchronously performs DOM + * updates and calls done() callbacks. + * + * In order to enable animations the ngAnimate module has to be loaded. + * + * To see the functional implementation check out src/ngAnimate/animate.js + */ +var $AnimateProvider = ['$provide', function($provide) { + + + this.$$selectors = {}; + + + /** + * @ngdoc function + * @name ng.$animateProvider#register + * @methodOf ng.$animateProvider + * + * @description + * Registers a new injectable animation factory function. The factory function produces the + * animation object which contains callback functions for each event that is expected to be + * animated. + * + * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction` + * must be called once the element animation is complete. If a function is returned then the + * animation service will use this function to cancel the animation whenever a cancel event is + * triggered. + * + * + *
+   *   return {
+     *     eventFn : function(element, done) {
+     *       //code to run the animation
+     *       //once complete, then run done()
+     *       return function cancellationFunction() {
+     *         //code to cancel the animation
+     *       }
+     *     }
+     *   }
+   *
+ * + * @param {string} name The name of the animation. + * @param {function} factory The factory function that will be executed to return the animation + * object. + */ + this.register = function(name, factory) { + var key = name + '-animation'; + if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel', + "Expecting class selector starting with '.' got '{0}'.", name); + this.$$selectors[name.substr(1)] = key; + $provide.factory(key, factory); + }; + + this.$get = ['$timeout', function($timeout) { + + /** + * + * @ngdoc object + * @name ng.$animate + * @description The $animate service provides rudimentary DOM manipulation functions to + * insert, remove and move elements within the DOM, as well as adding and removing classes. + * This service is the core service used by the ngAnimate $animator service which provides + * high-level animation hooks for CSS and JavaScript. + * + * $animate is available in the AngularJS core, however, the ngAnimate module must be included + * to enable full out animation support. Otherwise, $animate will only perform simple DOM + * manipulation operations. + * + * To learn more about enabling animation support, click here to visit the {@link ngAnimate + * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service + * page}. + */ + return { + + /** + * + * @ngdoc function + * @name ng.$animate#enter + * @methodOf ng.$animate + * @function + * @description Inserts the element into the DOM either after the `after` element or within + * the `parent` element. Once complete, the done() callback will be fired (if provided). + * @param {jQuery/jqLite element} element the element which will be inserted into the DOM + * @param {jQuery/jqLite element} parent the parent element which will append the element as + * a child (if the after element is not present) + * @param {jQuery/jqLite element} after the sibling element which will append the element + * after itself + * @param {function=} done callback function that will be called after the element has been + * inserted into the DOM + */ + enter : function(element, parent, after, done) { + if (after) { + after.after(element); + } else { + if (!parent || !parent[0]) { + parent = after.parent(); + } + parent.append(element); + } + done && $timeout(done, 0, false); + }, + + /** + * + * @ngdoc function + * @name ng.$animate#leave + * @methodOf ng.$animate + * @function + * @description Removes the element from the DOM. Once complete, the done() callback will be + * fired (if provided). + * @param {jQuery/jqLite element} element the element which will be removed from the DOM + * @param {function=} done callback function that will be called after the element has been + * removed from the DOM + */ + leave : function(element, done) { + element.remove(); + done && $timeout(done, 0, false); + }, + + /** + * + * @ngdoc function + * @name ng.$animate#move + * @methodOf ng.$animate + * @function + * @description Moves the position of the provided element within the DOM to be placed + * either after the `after` element or inside of the `parent` element. Once complete, the + * done() callback will be fired (if provided). + * + * @param {jQuery/jqLite element} element the element which will be moved around within the + * DOM + * @param {jQuery/jqLite element} parent the parent element where the element will be + * inserted into (if the after element is not present) + * @param {jQuery/jqLite element} after the sibling element where the element will be + * positioned next to + * @param {function=} done the callback function (if provided) that will be fired after the + * element has been moved to its new position + */ + move : function(element, parent, after, done) { + // Do not remove element before insert. Removing will cause data associated with the + // element to be dropped. Insert will implicitly do the remove. + this.enter(element, parent, after, done); + }, + + /** + * + * @ngdoc function + * @name ng.$animate#addClass + * @methodOf ng.$animate + * @function + * @description Adds the provided className CSS class value to the provided element. Once + * complete, the done() callback will be fired (if provided). + * @param {jQuery/jqLite element} element the element which will have the className value + * added to it + * @param {string} className the CSS class which will be added to the element + * @param {function=} done the callback function (if provided) that will be fired after the + * className value has been added to the element + */ + addClass : function(element, className, done) { + className = isString(className) ? + className : + isArray(className) ? className.join(' ') : ''; + forEach(element, function (element) { + jqLiteAddClass(element, className); + }); + done && $timeout(done, 0, false); + }, + + /** + * + * @ngdoc function + * @name ng.$animate#removeClass + * @methodOf ng.$animate + * @function + * @description Removes the provided className CSS class value from the provided element. + * Once complete, the done() callback will be fired (if provided). + * @param {jQuery/jqLite element} element the element which will have the className value + * removed from it + * @param {string} className the CSS class which will be removed from the element + * @param {function=} done the callback function (if provided) that will be fired after the + * className value has been removed from the element + */ + removeClass : function(element, className, done) { + className = isString(className) ? + className : + isArray(className) ? className.join(' ') : ''; + forEach(element, function (element) { + jqLiteRemoveClass(element, className); + }); + done && $timeout(done, 0, false); + }, + + enabled : noop + }; + }]; +}]; + +/** + * ! This is a private undocumented service ! + * + * @name ng.$browser + * @requires $log + * @description + * This object has two goals: + * + * - hide all the global state in the browser caused by the window object + * - abstract away all the browser specific features and inconsistencies + * + * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser` + * service, which can be used for convenient testing of the application without the interaction with + * the real browser apis. + */ +/** + * @param {object} window The global window object. + * @param {object} document jQuery wrapped document. + * @param {function()} XHR XMLHttpRequest constructor. + * @param {object} $log console.log or an object with the same interface. + * @param {object} $sniffer $sniffer service + */ +function Browser(window, document, $log, $sniffer) { + var self = this, + rawDocument = document[0], + location = window.location, + history = window.history, + setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + pendingDeferIds = {}; + + self.isMock = false; + + var outstandingRequestCount = 0; + var outstandingRequestCallbacks = []; + + // TODO(vojta): remove this temporary api + self.$$completeOutstandingRequest = completeOutstandingRequest; + self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; }; + + /** + * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks` + * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed. + */ + function completeOutstandingRequest(fn) { + try { + fn.apply(null, sliceArgs(arguments, 1)); + } finally { + outstandingRequestCount--; + if (outstandingRequestCount === 0) { + while(outstandingRequestCallbacks.length) { + try { + outstandingRequestCallbacks.pop()(); + } catch (e) { + $log.error(e); + } + } + } + } + } + + /** + * @private + * Note: this method is used only by scenario runner + * TODO(vojta): prefix this method with $$ ? + * @param {function()} callback Function that will be called when no outstanding request + */ + self.notifyWhenNoOutstandingRequests = function(callback) { + // force browser to execute all pollFns - this is needed so that cookies and other pollers fire + // at some deterministic time in respect to the test runner's actions. Leaving things up to the + // regular poller would result in flaky tests. + forEach(pollFns, function(pollFn){ pollFn(); }); + + if (outstandingRequestCount === 0) { + callback(); + } else { + outstandingRequestCallbacks.push(callback); + } + }; + + ////////////////////////////////////////////////////////////// + // Poll Watcher API + ////////////////////////////////////////////////////////////// + var pollFns = [], + pollTimeout; + + /** + * @name ng.$browser#addPollFn + * @methodOf ng.$browser + * + * @param {function()} fn Poll function to add + * + * @description + * Adds a function to the list of functions that poller periodically executes, + * and starts polling if not started yet. + * + * @returns {function()} the added function + */ + self.addPollFn = function(fn) { + if (isUndefined(pollTimeout)) startPoller(100, setTimeout); + pollFns.push(fn); + return fn; + }; + + /** + * @param {number} interval How often should browser call poll functions (ms) + * @param {function()} setTimeout Reference to a real or fake `setTimeout` function. + * + * @description + * Configures the poller to run in the specified intervals, using the specified + * setTimeout fn and kicks it off. + */ + function startPoller(interval, setTimeout) { + (function check() { + forEach(pollFns, function(pollFn){ pollFn(); }); + pollTimeout = setTimeout(check, interval); + })(); + } + + ////////////////////////////////////////////////////////////// + // URL API + ////////////////////////////////////////////////////////////// + + var lastBrowserUrl = location.href, + baseElement = document.find('base'), + newLocation = null; + + /** + * @name ng.$browser#url + * @methodOf ng.$browser + * + * @description + * GETTER: + * Without any argument, this method just returns current value of location.href. + * + * SETTER: + * With at least one argument, this method sets url to new value. + * If html5 history api supported, pushState/replaceState is used, otherwise + * location.href/location.replace is used. + * Returns its own instance to allow chaining + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to change url. + * + * @param {string} url New url (when used as setter) + * @param {boolean=} replace Should new url replace current history record ? + */ + self.url = function(url, replace) { + // Android Browser BFCache causes location reference to become stale. + if (location !== window.location) location = window.location; + + // setter + if (url) { + if (lastBrowserUrl == url) return; + lastBrowserUrl = url; + if ($sniffer.history) { + if (replace) history.replaceState(null, '', url); + else { + history.pushState(null, '', url); + // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462 + baseElement.attr('href', baseElement.attr('href')); + } + } else { + newLocation = url; + if (replace) { + location.replace(url); + } else { + location.href = url; + } + } + return self; + // getter + } else { + // - newLocation is a workaround for an IE7-9 issue with location.replace and location.href + // methods not updating location.href synchronously. + // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 + return newLocation || location.href.replace(/%27/g,"'"); + } + }; + + var urlChangeListeners = [], + urlChangeInit = false; + + function fireUrlChange() { + newLocation = null; + if (lastBrowserUrl == self.url()) return; + + lastBrowserUrl = self.url(); + forEach(urlChangeListeners, function(listener) { + listener(self.url()); + }); + } + + /** + * @name ng.$browser#onUrlChange + * @methodOf ng.$browser + * @TODO(vojta): refactor to use node's syntax for events + * + * @description + * Register callback function that will be called, when url changes. + * + * It's only called when the url is changed by outside of angular: + * - user types different url into address bar + * - user clicks on history (forward/back) button + * - user clicks on a link + * + * It's not called when url is changed by $browser.url() method + * + * The listener gets called with new url as parameter. + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to monitor url changes in angular apps. + * + * @param {function(string)} listener Listener function to be called when url changes. + * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. + */ + self.onUrlChange = function(callback) { + if (!urlChangeInit) { + // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera) + // don't fire popstate when user change the address bar and don't fire hashchange when url + // changed by push/replaceState + + // html5 history api - popstate event + if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange); + // hashchange event + if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange); + // polling + else self.addPollFn(fireUrlChange); + + urlChangeInit = true; + } + + urlChangeListeners.push(callback); + return callback; + }; + + ////////////////////////////////////////////////////////////// + // Misc API + ////////////////////////////////////////////////////////////// + + /** + * @name ng.$browser#baseHref + * @methodOf ng.$browser + * + * @description + * Returns current + * (always relative - without domain) + * + * @returns {string=} current + */ + self.baseHref = function() { + var href = baseElement.attr('href'); + return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : ''; + }; + + ////////////////////////////////////////////////////////////// + // Cookies API + ////////////////////////////////////////////////////////////// + var lastCookies = {}; + var lastCookieString = ''; + var cookiePath = self.baseHref(); + + /** + * @name ng.$browser#cookies + * @methodOf ng.$browser + * + * @param {string=} name Cookie name + * @param {string=} value Cookie value + * + * @description + * The cookies method provides a 'private' low level access to browser cookies. + * It is not meant to be used directly, use the $cookie service instead. + * + * The return values vary depending on the arguments that the method was called with as follows: + * + * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify + * it + * - cookies(name, value) -> set name to value, if value is undefined delete the cookie + * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that + * way) + * + * @returns {Object} Hash of all cookies (if called without any parameter) + */ + self.cookies = function(name, value) { + /* global escape: false, unescape: false */ + var cookieLength, cookieArray, cookie, i, index; + + if (name) { + if (value === undefined) { + rawDocument.cookie = escape(name) + "=;path=" + cookiePath + + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; + } else { + if (isString(value)) { + cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + + ';path=' + cookiePath).length + 1; + + // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: + // - 300 cookies + // - 20 cookies per unique domain + // - 4096 bytes per cookie + if (cookieLength > 4096) { + $log.warn("Cookie '"+ name + + "' possibly not set or overflowed because it was too large ("+ + cookieLength + " > 4096 bytes)!"); + } + } + } + } else { + if (rawDocument.cookie !== lastCookieString) { + lastCookieString = rawDocument.cookie; + cookieArray = lastCookieString.split("; "); + lastCookies = {}; + + for (i = 0; i < cookieArray.length; i++) { + cookie = cookieArray[i]; + index = cookie.indexOf('='); + if (index > 0) { //ignore nameless cookies + name = unescape(cookie.substring(0, index)); + // the first value that is seen for a cookie is the most + // specific one. values for the same cookie name that + // follow are for less specific paths. + if (lastCookies[name] === undefined) { + lastCookies[name] = unescape(cookie.substring(index + 1)); + } + } + } + } + return lastCookies; + } + }; + + + /** + * @name ng.$browser#defer + * @methodOf ng.$browser + * @param {function()} fn A function, who's execution should be deferred. + * @param {number=} [delay=0] of milliseconds to defer the function execution. + * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. + * + * @description + * Executes a fn asynchronously via `setTimeout(fn, delay)`. + * + * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using + * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed + * via `$browser.defer.flush()`. + * + */ + self.defer = function(fn, delay) { + var timeoutId; + outstandingRequestCount++; + timeoutId = setTimeout(function() { + delete pendingDeferIds[timeoutId]; + completeOutstandingRequest(fn); + }, delay || 0); + pendingDeferIds[timeoutId] = true; + return timeoutId; + }; + + + /** + * @name ng.$browser#defer.cancel + * @methodOf ng.$browser.defer + * + * @description + * Cancels a deferred task identified with `deferId`. + * + * @param {*} deferId Token returned by the `$browser.defer` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + self.defer.cancel = function(deferId) { + if (pendingDeferIds[deferId]) { + delete pendingDeferIds[deferId]; + clearTimeout(deferId); + completeOutstandingRequest(noop); + return true; + } + return false; + }; + +} + +function $BrowserProvider(){ + this.$get = ['$window', '$log', '$sniffer', '$document', + function( $window, $log, $sniffer, $document){ + return new Browser($window, $document, $log, $sniffer); + }]; +} + +/** + * @ngdoc object + * @name ng.$cacheFactory + * + * @description + * Factory that constructs cache objects and gives access to them. + * + *
+ *
+ *  var cache = $cacheFactory('cacheId');
+ *  expect($cacheFactory.get('cacheId')).toBe(cache);
+ *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
+ *
+ *  cache.put("key", "value");
+ *  cache.put("another key", "another value");
+ *
+ *  // We've specified no options on creation
+ *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});
+ *
+ * 
+ * + * + * @param {string} cacheId Name or id of the newly created cache. + * @param {object=} options Options object that specifies the cache behavior. Properties: + * + * - `{number=}` `capacity` — turns the cache into LRU cache. + * + * @returns {object} Newly created cache object with the following set of methods: + * + * - `{object}` `info()` — Returns id, size, and options of cache. + * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns + * it. + * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss. + * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache. + * - `{void}` `removeAll()` — Removes all cached values. + * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory. + * + */ +function $CacheFactoryProvider() { + + this.$get = function() { + var caches = {}; + + function cacheFactory(cacheId, options) { + if (cacheId in caches) { + throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId); + } + + var size = 0, + stats = extend({}, options, {id: cacheId}), + data = {}, + capacity = (options && options.capacity) || Number.MAX_VALUE, + lruHash = {}, + freshEnd = null, + staleEnd = null; + + return caches[cacheId] = { + + put: function(key, value) { + var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); + + refresh(lruEntry); + + if (isUndefined(value)) return; + if (!(key in data)) size++; + data[key] = value; + + if (size > capacity) { + this.remove(staleEnd.key); + } + + return value; + }, + + + get: function(key) { + var lruEntry = lruHash[key]; + + if (!lruEntry) return; + + refresh(lruEntry); + + return data[key]; + }, + + + remove: function(key) { + var lruEntry = lruHash[key]; + + if (!lruEntry) return; + + if (lruEntry == freshEnd) freshEnd = lruEntry.p; + if (lruEntry == staleEnd) staleEnd = lruEntry.n; + link(lruEntry.n,lruEntry.p); + + delete lruHash[key]; + delete data[key]; + size--; + }, + + + removeAll: function() { + data = {}; + size = 0; + lruHash = {}; + freshEnd = staleEnd = null; + }, + + + destroy: function() { + data = null; + stats = null; + lruHash = null; + delete caches[cacheId]; + }, + + + info: function() { + return extend({}, stats, {size: size}); + } + }; + + + /** + * makes the `entry` the freshEnd of the LRU linked list + */ + function refresh(entry) { + if (entry != freshEnd) { + if (!staleEnd) { + staleEnd = entry; + } else if (staleEnd == entry) { + staleEnd = entry.n; + } + + link(entry.n, entry.p); + link(entry, freshEnd); + freshEnd = entry; + freshEnd.n = null; + } + } + + + /** + * bidirectionally links two entries of the LRU linked list + */ + function link(nextEntry, prevEntry) { + if (nextEntry != prevEntry) { + if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify + if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify + } + } + } + + + /** + * @ngdoc method + * @name ng.$cacheFactory#info + * @methodOf ng.$cacheFactory + * + * @description + * Get information about all the of the caches that have been created + * + * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info` + */ + cacheFactory.info = function() { + var info = {}; + forEach(caches, function(cache, cacheId) { + info[cacheId] = cache.info(); + }); + return info; + }; + + + /** + * @ngdoc method + * @name ng.$cacheFactory#get + * @methodOf ng.$cacheFactory + * + * @description + * Get access to a cache object by the `cacheId` used when it was created. + * + * @param {string} cacheId Name or id of a cache to access. + * @returns {object} Cache object identified by the cacheId or undefined if no such cache. + */ + cacheFactory.get = function(cacheId) { + return caches[cacheId]; + }; + + + return cacheFactory; + }; +} + +/** + * @ngdoc object + * @name ng.$templateCache + * + * @description + * The first time a template is used, it is loaded in the template cache for quick retrieval. You + * can load templates directly into the cache in a `script` tag, or by consuming the + * `$templateCache` service directly. + * + * Adding via the `script` tag: + *
+ * 
+ * 
+ * 
+ * 
+ *   ...
+ * 
+ * 
+ * + * **Note:** the `script` tag containing the template does not need to be included in the `head` of + * the document, but it must be below the `ng-app` definition. + * + * Adding via the $templateCache service: + * + *
+ * var myApp = angular.module('myApp', []);
+ * myApp.run(function($templateCache) {
+ *   $templateCache.put('templateId.html', 'This is the content of the template');
+ * });
+ * 
+ * + * To retrieve the template later, simply use it in your HTML: + *
+ * 
+ *
+ * + * or get it via Javascript: + *
+ * $templateCache.get('templateId.html')
+ * 
+ * + * See {@link ng.$cacheFactory $cacheFactory}. + * + */ +function $TemplateCacheProvider() { + this.$get = ['$cacheFactory', function($cacheFactory) { + return $cacheFactory('templates'); + }]; +} + +/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! + * + * DOM-related variables: + * + * - "node" - DOM Node + * - "element" - DOM Element or Node + * - "$node" or "$element" - jqLite-wrapped node or element + * + * + * Compiler related stuff: + * + * - "linkFn" - linking fn of a single directive + * - "nodeLinkFn" - function that aggregates all linking fns for a particular node + * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node + * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList) + */ + + +/** + * @ngdoc function + * @name ng.$compile + * @function + * + * @description + * Compiles a piece of HTML string or DOM into a template and produces a template function, which + * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together. + * + * The compilation is a process of walking the DOM tree and matching DOM elements to + * {@link ng.$compileProvider#methods_directive directives}. + * + *
+ * **Note:** This document is an in-depth reference of all directive options. + * For a gentle introduction to directives with examples of common use cases, + * see the {@link guide/directive directive guide}. + *
+ * + * ## Comprehensive Directive API + * + * There are many different options for a directive. + * + * The difference resides in the return value of the factory function. + * You can either return a "Directive Definition Object" (see below) that defines the directive properties, + * or just the `postLink` function (all other properties will have the default values). + * + *
+ * **Best Practice:** It's recommended to use the "directive definition object" form. + *
+ * + * Here's an example directive declared with a Directive Definition Object: + * + *
+ *   var myModule = angular.module(...);
+ *
+ *   myModule.directive('directiveName', function factory(injectables) {
+ *     var directiveDefinitionObject = {
+ *       priority: 0,
+ *       template: '
', // or // function(tElement, tAttrs) { ... }, + * // or + * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, + * replace: false, + * transclude: false, + * restrict: 'A', + * scope: false, + * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, + * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], + * compile: function compile(tElement, tAttrs, transclude) { + * return { + * pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * post: function postLink(scope, iElement, iAttrs, controller) { ... } + * } + * // or + * // return function postLink( ... ) { ... } + * }, + * // or + * // link: { + * // pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * // post: function postLink(scope, iElement, iAttrs, controller) { ... } + * // } + * // or + * // link: function postLink( ... ) { ... } + * }; + * return directiveDefinitionObject; + * }); + *
+ * + *
+ * **Note:** Any unspecified options will use the default value. You can see the default values below. + *
+ * + * Therefore the above can be simplified as: + * + *
+ *   var myModule = angular.module(...);
+ *
+ *   myModule.directive('directiveName', function factory(injectables) {
+ *     var directiveDefinitionObject = {
+ *       link: function postLink(scope, iElement, iAttrs) { ... }
+ *     };
+ *     return directiveDefinitionObject;
+ *     // or
+ *     // return function postLink(scope, iElement, iAttrs) { ... }
+ *   });
+ * 
+ * + * + * + * ### Directive Definition Object + * + * The directive definition object provides instructions to the {@link api/ng.$compile + * compiler}. The attributes are: + * + * #### `priority` + * When there are multiple directives defined on a single DOM element, sometimes it + * is necessary to specify the order in which the directives are applied. The `priority` is used + * to sort the directives before their `compile` functions get called. Priority is defined as a + * number. Directives with greater numerical `priority` are compiled first. Pre-link functions + * are also run in priority order, but post-link functions are run in reverse order. The order + * of directives with the same priority is undefined. The default priority is `0`. + * + * #### `terminal` + * If set to true then the current `priority` will be the last set of directives + * which will execute (any directives at the current priority will still execute + * as the order of execution on same `priority` is undefined). + * + * #### `scope` + * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the + * same element request a new scope, only one new scope is created. The new scope rule does not + * apply for the root of the template since the root of the template always gets a new scope. + * + * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from + * normal scope in that it does not prototypically inherit from the parent scope. This is useful + * when creating reusable components, which should not accidentally read or modify data in the + * parent scope. + * + * The 'isolate' scope takes an object hash which defines a set of local scope properties + * derived from the parent scope. These local properties are useful for aliasing values for + * templates. Locals definition is a hash of local scope property to its source: + * + * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is + * always a string since DOM attributes are strings. If no `attr` name is specified then the + * attribute name is assumed to be the same as the local name. + * Given `` and widget definition + * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect + * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the + * `localName` property on the widget scope. The `name` is read from the parent scope (not + * component scope). + * + * * `=` or `=attr` - set up bi-directional binding between a local scope property and the + * parent scope property of name defined via the value of the `attr` attribute. If no `attr` + * name is specified then the attribute name is assumed to be the same as the local name. + * Given `` and widget definition of + * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the + * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected + * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent + * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You + * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. + * + * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. + * If no `attr` name is specified then the attribute name is assumed to be the same as the + * local name. Given `` and widget definition of + * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to + * a function wrapper for the `count = count + value` expression. Often it's desirable to + * pass data from the isolated scope via an expression and to the parent scope, this can be + * done by passing a map of local variable names and values into the expression wrapper fn. + * For example, if the expression is `increment(amount)` then we can specify the amount value + * by calling the `localFn` as `localFn({amount: 22})`. + * + * + * + * #### `controller` + * Controller constructor function. The controller is instantiated before the + * pre-linking phase and it is shared with other directives (see + * `require` attribute). This allows the directives to communicate with each other and augment + * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals: + * + * * `$scope` - Current scope associated with the element + * * `$element` - Current element + * * `$attrs` - Current attributes object for the element + * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope. + * The scope can be overridden by an optional first argument. + * `function([scope], cloneLinkingFn)`. + * + * + * #### `require` + * Require another directive and inject its controller as the fourth argument to the linking function. The + * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the + * injected argument will be an array in corresponding order. If no such directive can be + * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with: + * + * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. + * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. + * * `^` - Locate the required controller by searching the element's parents. Throw an error if not found. + * * `?^` - Attempt to locate the required controller by searching the element's parentsor pass `null` to the + * `link` fn if not found. + * + * + * #### `controllerAs` + * Controller alias at the directive scope. An alias for the controller so it + * can be referenced at the directive template. The directive needs to define a scope for this + * configuration to be used. Useful in the case when directive is used as component. + * + * + * #### `restrict` + * String of subset of `EACM` which restricts the directive to a specific directive + * declaration style. If omitted, the default (attributes only) is used. + * + * * `E` - Element name: `` + * * `A` - Attribute (default): `
` + * * `C` - Class: `
` + * * `M` - Comment: `` + * + * + * #### `template` + * replace the current element with the contents of the HTML. The replacement process + * migrates all of the attributes / classes from the old element to the new one. See the + * {@link guide/directive#creating-custom-directives_creating-directives_template-expanding-directive + * Directives Guide} for an example. + * + * You can specify `template` as a string representing the template or as a function which takes + * two arguments `tElement` and `tAttrs` (described in the `compile` function api below) and + * returns a string value representing the template. + * + * + * #### `templateUrl` + * Same as `template` but the template is loaded from the specified URL. Because + * the template loading is asynchronous the compilation/linking is suspended until the template + * is loaded. + * + * You can specify `templateUrl` as a string representing the URL or as a function which takes two + * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns + * a string value representing the url. In either case, the template URL is passed through {@link + * api/ng.$sce#methods_getTrustedResourceUrl $sce.getTrustedResourceUrl}. + * + * + * #### `replace` + * specify where the template should be inserted. Defaults to `false`. + * + * * `true` - the template will replace the current element. + * * `false` - the template will replace the contents of the current element. + * + * + * #### `transclude` + * compile the content of the element and make it available to the directive. + * Typically used with {@link api/ng.directive:ngTransclude + * ngTransclude}. The advantage of transclusion is that the linking function receives a + * transclusion function which is pre-bound to the correct scope. In a typical setup the widget + * creates an `isolate` scope, but the transclusion is not a child, but a sibling of the `isolate` + * scope. This makes it possible for the widget to have private state, and the transclusion to + * be bound to the parent (pre-`isolate`) scope. + * + * * `true` - transclude the content of the directive. + * * `'element'` - transclude the whole element including any directives defined at lower priority. + * + * + * #### `compile` + * + *
+ *   function compile(tElement, tAttrs, transclude) { ... }
+ * 
+ * + * The compile function deals with transforming the template DOM. Since most directives do not do + * template transformation, it is not used often. Examples that require compile functions are + * directives that transform template DOM, such as {@link + * api/ng.directive:ngRepeat ngRepeat}, or load the contents + * asynchronously, such as {@link api/ngRoute.directive:ngView ngView}. The + * compile function takes the following arguments. + * + * * `tElement` - template element - The element where the directive has been declared. It is + * safe to do template transformation on the element and child elements only. + * + * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared + * between all directive compile functions. + * + * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)` + * + *
+ * **Note:** The template instance and the link instance may be different objects if the template has + * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that + * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration + * should be done in a linking function rather than in a compile function. + *
+ * + *
+ * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it + * e.g. does not know about the right outer scope. Please use the transclude function that is passed + * to the link function instead. + *
+ + * A compile function can have a return value which can be either a function or an object. + * + * * returning a (post-link) function - is equivalent to registering the linking function via the + * `link` property of the config object when the compile function is empty. + * + * * returning an object with function(s) registered via `pre` and `post` properties - allows you to + * control when a linking function should be called during the linking phase. See info about + * pre-linking and post-linking functions below. + * + * + * #### `link` + * This property is used only if the `compile` property is not defined. + * + *
+ *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
+ * 
+ * + * The link function is responsible for registering DOM listeners as well as updating the DOM. It is + * executed after the template has been cloned. This is where most of the directive logic will be + * put. + * + * * `scope` - {@link api/ng.$rootScope.Scope Scope} - The scope to be used by the + * directive for registering {@link api/ng.$rootScope.Scope#methods_$watch watches}. + * + * * `iElement` - instance element - The element where the directive is to be used. It is safe to + * manipulate the children of the element only in `postLink` function since the children have + * already been linked. + * + * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared + * between all directive linking functions. + * + * * `controller` - a controller instance - A controller instance if at least one directive on the + * element defines a controller. The controller is shared among all the directives, which allows + * the directives to use the controllers as a communication channel. + * + * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. + * The scope can be overridden by an optional first argument. This is the same as the `$transclude` + * parameter of directive controllers. + * `function([scope], cloneLinkingFn)`. + * + * + * #### Pre-linking function + * + * Executed before the child elements are linked. Not safe to do DOM transformation since the + * compiler linking function will fail to locate the correct elements for linking. + * + * #### Post-linking function + * + * Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function. + * + * + * ### Attributes + * + * The {@link api/ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the + * `link()` or `compile()` functions. It has a variety of uses. + * + * accessing *Normalized attribute names:* + * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. + * the attributes object allows for normalized access to + * the attributes. + * + * * *Directive inter-communication:* All directives share the same instance of the attributes + * object which allows the directives to use the attributes object as inter directive + * communication. + * + * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object + * allowing other directives to read the interpolated value. + * + * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes + * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also + * the only way to easily get the actual value because during the linking phase the interpolation + * hasn't been evaluated yet and so the value is at this time set to `undefined`. + * + *
+ * function linkingFn(scope, elm, attrs, ctrl) {
+ *   // get the attribute value
+ *   console.log(attrs.ngModel);
+ *
+ *   // change the attribute
+ *   attrs.$set('ngModel', 'new value');
+ *
+ *   // observe changes to interpolated attribute
+ *   attrs.$observe('ngModel', function(value) {
+ *     console.log('ngModel has changed value to ' + value);
+ *   });
+ * }
+ * 
+ * + * Below is an example using `$compileProvider`. + * + *
+ * **Note**: Typically directives are registered with `module.directive`. The example below is + * to illustrate how `$compile` works. + *
+ * + + + +
+
+
+
+
+
+ + it('should auto compile', function() { + expect(element('div[compile]').text()).toBe('Hello Angular'); + input('html').enter('{{name}}!'); + expect(element('div[compile]').text()).toBe('Angular!'); + }); + +
+ + * + * + * @param {string|DOMElement} element Element or HTML string to compile into a template function. + * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives. + * @param {number} maxPriority only apply directives lower then given priority (Only effects the + * root element(s), not their children) + * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template + * (a DOM element/tree) to a scope. Where: + * + * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. + * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the + * `template` and call the `cloneAttachFn` function allowing the caller to attach the + * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is + * called as:
`cloneAttachFn(clonedElement, scope)` where: + * + * * `clonedElement` - is a clone of the original `element` passed into the compiler. + * * `scope` - is the current scope with which the linking function is working with. + * + * Calling the linking function returns the element of the template. It is either the original + * element passed in, or the clone of the element if the `cloneAttachFn` is provided. + * + * After linking the view is not updated until after a call to $digest which typically is done by + * Angular automatically. + * + * If you need access to the bound view, there are two ways to do it: + * + * - If you are not asking the linking function to clone the template, create the DOM element(s) + * before you send them to the compiler and keep this reference around. + *
+ *     var element = $compile('

{{total}}

')(scope); + *
+ * + * - if on the other hand, you need the element to be cloned, the view reference from the original + * example would not point to the clone, but rather to the original template that was cloned. In + * this case, you can access the clone via the cloneAttachFn: + *
+ *     var templateHTML = angular.element('

{{total}}

'), + * scope = ....; + * + * var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) { + * //attach the clone to DOM document at the right place + * }); + * + * //now we have reference to the cloned DOM via `clone` + *
+ * + * + * For information on how the compiler works, see the + * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide. + */ + +var $compileMinErr = minErr('$compile'); + +/** + * @ngdoc service + * @name ng.$compileProvider + * @function + * + * @description + */ +$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider']; +function $CompileProvider($provide, $$sanitizeUriProvider) { + var hasDirectives = {}, + Suffix = 'Directive', + COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/, + CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/; + + // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes + // The assumption is that future DOM event attribute names will begin with + // 'on' and be composed of only English letters. + var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; + + /** + * @ngdoc function + * @name ng.$compileProvider#directive + * @methodOf ng.$compileProvider + * @function + * + * @description + * Register a new directive with the compiler. + * + * @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which + * will match as ng-bind), or an object map of directives where the keys are the + * names and the values are the factories. + * @param {function|Array} directiveFactory An injectable directive factory function. See + * {@link guide/directive} for more info. + * @returns {ng.$compileProvider} Self for chaining. + */ + this.directive = function registerDirective(name, directiveFactory) { + assertNotHasOwnProperty(name, 'directive'); + if (isString(name)) { + assertArg(directiveFactory, 'directiveFactory'); + if (!hasDirectives.hasOwnProperty(name)) { + hasDirectives[name] = []; + $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', + function($injector, $exceptionHandler) { + var directives = []; + forEach(hasDirectives[name], function(directiveFactory, index) { + try { + var directive = $injector.invoke(directiveFactory); + if (isFunction(directive)) { + directive = { compile: valueFn(directive) }; + } else if (!directive.compile && directive.link) { + directive.compile = valueFn(directive.link); + } + directive.priority = directive.priority || 0; + directive.index = index; + directive.name = directive.name || name; + directive.require = directive.require || (directive.controller && directive.name); + directive.restrict = directive.restrict || 'A'; + directives.push(directive); + } catch (e) { + $exceptionHandler(e); + } + }); + return directives; + }]); + } + hasDirectives[name].push(directiveFactory); + } else { + forEach(name, reverseParams(registerDirective)); + } + return this; + }; + + + /** + * @ngdoc function + * @name ng.$compileProvider#aHrefSanitizationWhitelist + * @methodOf ng.$compileProvider + * @function + * + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); + } + }; + + + /** + * @ngdoc function + * @name ng.$compileProvider#imgSrcSanitizationWhitelist + * @methodOf ng.$compileProvider + * @function + * + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); + } + }; + + this.$get = [ + '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse', + '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri', + function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse, + $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { + + var Attributes = function(element, attr) { + this.$$element = element; + this.$attr = attr || {}; + }; + + Attributes.prototype = { + $normalize: directiveNormalize, + + + /** + * @ngdoc function + * @name ng.$compile.directive.Attributes#$addClass + * @methodOf ng.$compile.directive.Attributes + * @function + * + * @description + * Adds the CSS class value specified by the classVal parameter to the element. If animations + * are enabled then an animation will be triggered for the class addition. + * + * @param {string} classVal The className value that will be added to the element + */ + $addClass : function(classVal) { + if(classVal && classVal.length > 0) { + $animate.addClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc function + * @name ng.$compile.directive.Attributes#$removeClass + * @methodOf ng.$compile.directive.Attributes + * @function + * + * @description + * Removes the CSS class value specified by the classVal parameter from the element. If + * animations are enabled then an animation will be triggered for the class removal. + * + * @param {string} classVal The className value that will be removed from the element + */ + $removeClass : function(classVal) { + if(classVal && classVal.length > 0) { + $animate.removeClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc function + * @name ng.$compile.directive.Attributes#$updateClass + * @methodOf ng.$compile.directive.Attributes + * @function + * + * @description + * Adds and removes the appropriate CSS class values to the element based on the difference + * between the new and old CSS class values (specified as newClasses and oldClasses). + * + * @param {string} newClasses The current CSS className value + * @param {string} oldClasses The former CSS className value + */ + $updateClass : function(newClasses, oldClasses) { + this.$removeClass(tokenDifference(oldClasses, newClasses)); + this.$addClass(tokenDifference(newClasses, oldClasses)); + }, + + /** + * Set a normalized attribute on the element in a way such that all directives + * can share the attribute. This function properly handles boolean attributes. + * @param {string} key Normalized key. (ie ngAttribute) + * @param {string|boolean} value The value to set. If `null` attribute will be deleted. + * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. + * Defaults to true. + * @param {string=} attrName Optional none normalized name. Defaults to key. + */ + $set: function(key, value, writeAttr, attrName) { + // TODO: decide whether or not to throw an error if "class" + //is set through this function since it may cause $updateClass to + //become unstable. + + var booleanKey = getBooleanAttrName(this.$$element[0], key), + normalizedVal, + nodeName; + + if (booleanKey) { + this.$$element.prop(key, value); + attrName = booleanKey; + } + + this[key] = value; + + // translate normalized key to actual key + if (attrName) { + this.$attr[key] = attrName; + } else { + attrName = this.$attr[key]; + if (!attrName) { + this.$attr[key] = attrName = snake_case(key, '-'); + } + } + + nodeName = nodeName_(this.$$element); + + // sanitize a[href] and img[src] values + if ((nodeName === 'A' && key === 'href') || + (nodeName === 'IMG' && key === 'src')) { + this[key] = value = $$sanitizeUri(value, key === 'src'); + } + + if (writeAttr !== false) { + if (value === null || value === undefined) { + this.$$element.removeAttr(attrName); + } else { + this.$$element.attr(attrName, value); + } + } + + // fire observers + var $$observers = this.$$observers; + $$observers && forEach($$observers[key], function(fn) { + try { + fn(value); + } catch (e) { + $exceptionHandler(e); + } + }); + }, + + + /** + * @ngdoc function + * @name ng.$compile.directive.Attributes#$observe + * @methodOf ng.$compile.directive.Attributes + * @function + * + * @description + * Observes an interpolated attribute. + * + * The observer function will be invoked once during the next `$digest` following + * compilation. The observer is then invoked whenever the interpolated value + * changes. + * + * @param {string} key Normalized key. (ie ngAttribute) . + * @param {function(interpolatedValue)} fn Function that will be called whenever + the interpolated value of the attribute changes. + * See the {@link guide/directive#Attributes Directives} guide for more info. + * @returns {function()} the `fn` parameter. + */ + $observe: function(key, fn) { + var attrs = this, + $$observers = (attrs.$$observers || (attrs.$$observers = {})), + listeners = ($$observers[key] || ($$observers[key] = [])); + + listeners.push(fn); + $rootScope.$evalAsync(function() { + if (!listeners.$$inter) { + // no one registered attribute interpolation function, so lets call it manually + fn(attrs[key]); + } + }); + return fn; + } + }; + + var startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') + ? identity + : function denormalizeTemplate(template) { + return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); + }, + NG_ATTR_BINDING = /^ngAttr[A-Z]/; + + + return compile; + + //================================ + + function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, + previousCompileContext) { + if (!($compileNodes instanceof jqLite)) { + // jquery always rewraps, whereas we need to preserve the original selector so that we can + // modify it. + $compileNodes = jqLite($compileNodes); + } + // We can not compile top level text elements since text nodes can be merged and we will + // not be able to attach scope data to them, so we will wrap them in + forEach($compileNodes, function(node, index){ + if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) { + $compileNodes[index] = node = jqLite(node).wrap('').parent()[0]; + } + }); + var compositeLinkFn = + compileNodes($compileNodes, transcludeFn, $compileNodes, + maxPriority, ignoreDirective, previousCompileContext); + return function publicLinkFn(scope, cloneConnectFn, transcludeControllers){ + assertArg(scope, 'scope'); + // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart + // and sometimes changes the structure of the DOM. + var $linkNode = cloneConnectFn + ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!! + : $compileNodes; + + forEach(transcludeControllers, function(instance, name) { + $linkNode.data('$' + name + 'Controller', instance); + }); + + // Attach scope only to non-text nodes. + for(var i = 0, ii = $linkNode.length; i + addDirective(directives, + directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective); + + // iterate over the attributes + for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes, + j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { + var attrStartName = false; + var attrEndName = false; + + attr = nAttrs[j]; + if (!msie || msie >= 8 || attr.specified) { + name = attr.name; + // support ngAttr attribute binding + ngAttrName = directiveNormalize(name); + if (NG_ATTR_BINDING.test(ngAttrName)) { + name = snake_case(ngAttrName.substr(6), '-'); + } + + var directiveNName = ngAttrName.replace(/(Start|End)$/, ''); + if (ngAttrName === directiveNName + 'Start') { + attrStartName = name; + attrEndName = name.substr(0, name.length - 5) + 'end'; + name = name.substr(0, name.length - 6); + } + + nName = directiveNormalize(name.toLowerCase()); + attrsMap[nName] = name; + attrs[nName] = value = trim((msie && name == 'href') + ? decodeURIComponent(node.getAttribute(name, 2)) + : attr.value); + if (getBooleanAttrName(node, nName)) { + attrs[nName] = true; // presence means true + } + addAttrInterpolateDirective(node, directives, value, nName); + addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, + attrEndName); + } + } + + // use class as directive + className = node.className; + if (isString(className) && className !== '') { + while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { + nName = directiveNormalize(match[2]); + if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[3]); + } + className = className.substr(match.index + match[0].length); + } + } + break; + case 3: /* Text Node */ + addTextInterpolateDirective(directives, node.nodeValue); + break; + case 8: /* Comment */ + try { + match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); + if (match) { + nName = directiveNormalize(match[1]); + if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[2]); + } + } + } catch (e) { + // turns out that under some circumstances IE9 throws errors when one attempts to read + // comment's node value. + // Just ignore it and continue. (Can't seem to reproduce in test case.) + } + break; + } + + directives.sort(byPriority); + return directives; + } + + /** + * Given a node with an directive-start it collects all of the siblings until it finds + * directive-end. + * @param node + * @param attrStart + * @param attrEnd + * @returns {*} + */ + function groupScan(node, attrStart, attrEnd) { + var nodes = []; + var depth = 0; + if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { + var startNode = node; + do { + if (!node) { + throw $compileMinErr('uterdir', + "Unterminated attribute, found '{0}' but no matching '{1}' found.", + attrStart, attrEnd); + } + if (node.nodeType == 1 /** Element **/) { + if (node.hasAttribute(attrStart)) depth++; + if (node.hasAttribute(attrEnd)) depth--; + } + nodes.push(node); + node = node.nextSibling; + } while (depth > 0); + } else { + nodes.push(node); + } + + return jqLite(nodes); + } + + /** + * Wrapper for linking function which converts normal linking function into a grouped + * linking function. + * @param linkFn + * @param attrStart + * @param attrEnd + * @returns {Function} + */ + function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { + return function(scope, element, attrs, controllers, transcludeFn) { + element = groupScan(element[0], attrStart, attrEnd); + return linkFn(scope, element, attrs, controllers, transcludeFn); + }; + } + + /** + * Once the directives have been collected, their compile functions are executed. This method + * is responsible for inlining directive templates as well as terminating the application + * of the directives if the terminal directive has been reached. + * + * @param {Array} directives Array of collected directives to execute their compile function. + * this needs to be pre-sorted by priority order. + * @param {Node} compileNode The raw DOM node to apply the compile functions to + * @param {Object} templateAttrs The shared attribute function + * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the + * scope argument is auto-generated to the new + * child of the transcluded parent scope. + * @param {JQLite} jqCollection If we are working on the root of the compile tree then this + * argument has the root jqLite array so that we can replace nodes + * on it. + * @param {Object=} originalReplaceDirective An optional directive that will be ignored when + * compiling the transclusion. + * @param {Array.} preLinkFns + * @param {Array.} postLinkFns + * @param {Object} previousCompileContext Context used for previous compilation of the current + * node + * @returns linkFn + */ + function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, + jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, + previousCompileContext) { + previousCompileContext = previousCompileContext || {}; + + var terminalPriority = -Number.MAX_VALUE, + newScopeDirective, + controllerDirectives = previousCompileContext.controllerDirectives, + newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, + templateDirective = previousCompileContext.templateDirective, + nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, + hasTranscludeDirective = false, + hasElementTranscludeDirective = false, + $compileNode = templateAttrs.$$element = jqLite(compileNode), + directive, + directiveName, + $template, + replaceDirective = originalReplaceDirective, + childTranscludeFn = transcludeFn, + linkFn, + directiveValue; + + // executes all directives on the current element + for(var i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + var attrStart = directive.$$start; + var attrEnd = directive.$$end; + + // collect multiblock sections + if (attrStart) { + $compileNode = groupScan(compileNode, attrStart, attrEnd); + } + $template = undefined; + + if (terminalPriority > directive.priority) { + break; // prevent further processing of directives + } + + if (directiveValue = directive.scope) { + newScopeDirective = newScopeDirective || directive; + + // skip the check for directives with async templates, we'll check the derived sync + // directive when the template arrives + if (!directive.templateUrl) { + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive, + $compileNode); + if (isObject(directiveValue)) { + newIsolateScopeDirective = directive; + } + } + } + + directiveName = directive.name; + + if (!directive.templateUrl && directive.controller) { + directiveValue = directive.controller; + controllerDirectives = controllerDirectives || {}; + assertNoDuplicate("'" + directiveName + "' controller", + controllerDirectives[directiveName], directive, $compileNode); + controllerDirectives[directiveName] = directive; + } + + if (directiveValue = directive.transclude) { + hasTranscludeDirective = true; + + // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. + // This option should only be used by directives that know how to how to safely handle element transclusion, + // where the transcluded nodes are added or replaced after linking. + if (!directive.$$tlb) { + assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); + nonTlbTranscludeDirective = directive; + } + + if (directiveValue == 'element') { + hasElementTranscludeDirective = true; + terminalPriority = directive.priority; + $template = groupScan(compileNode, attrStart, attrEnd); + $compileNode = templateAttrs.$$element = + jqLite(document.createComment(' ' + directiveName + ': ' + + templateAttrs[directiveName] + ' ')); + compileNode = $compileNode[0]; + replaceWith(jqCollection, jqLite(sliceArgs($template)), compileNode); + + childTranscludeFn = compile($template, transcludeFn, terminalPriority, + replaceDirective && replaceDirective.name, { + // Don't pass in: + // - controllerDirectives - otherwise we'll create duplicates controllers + // - newIsolateScopeDirective or templateDirective - combining templates with + // element transclusion doesn't make sense. + // + // We need only nonTlbTranscludeDirective so that we prevent putting transclusion + // on the same element more than once. + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + } else { + $template = jqLite(jqLiteClone(compileNode)).contents(); + $compileNode.html(''); // clear contents + childTranscludeFn = compile($template, transcludeFn); + } + } + + if (directive.template) { + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + directiveValue = (isFunction(directive.template)) + ? directive.template($compileNode, templateAttrs) + : directive.template; + + directiveValue = denormalizeTemplate(directiveValue); + + if (directive.replace) { + replaceDirective = directive; + $template = jqLite('
' + + trim(directiveValue) + + '
').contents(); + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== 1) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + directiveName, ''); + } + + replaceWith(jqCollection, $compileNode, compileNode); + + var newTemplateAttrs = {$attr: {}}; + + // combine directives from the original node and from the template: + // - take the array of directives for this element + // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed) + // - collect directives from the template and sort them by priority + // - combine directives as: processed + template + unprocessed + var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); + var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); + + if (newIsolateScopeDirective) { + markDirectivesAsIsolate(templateDirectives); + } + directives = directives.concat(templateDirectives).concat(unprocessedDirectives); + mergeTemplateAttributes(templateAttrs, newTemplateAttrs); + + ii = directives.length; + } else { + $compileNode.html(directiveValue); + } + } + + if (directive.templateUrl) { + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + if (directive.replace) { + replaceDirective = directive; + } + + nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, + templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns, { + controllerDirectives: controllerDirectives, + newIsolateScopeDirective: newIsolateScopeDirective, + templateDirective: templateDirective, + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + ii = directives.length; + } else if (directive.compile) { + try { + linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); + if (isFunction(linkFn)) { + addLinkFns(null, linkFn, attrStart, attrEnd); + } else if (linkFn) { + addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd); + } + } catch (e) { + $exceptionHandler(e, startingTag($compileNode)); + } + } + + if (directive.terminal) { + nodeLinkFn.terminal = true; + terminalPriority = Math.max(terminalPriority, directive.priority); + } + + } + + nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; + nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn; + + // might be normal or delayed nodeLinkFn depending on if templateUrl is present + return nodeLinkFn; + + //////////////////// + + function addLinkFns(pre, post, attrStart, attrEnd) { + if (pre) { + if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); + pre.require = directive.require; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + pre = cloneAndAnnotateFn(pre, {isolateScope: true}); + } + preLinkFns.push(pre); + } + if (post) { + if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); + post.require = directive.require; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + post = cloneAndAnnotateFn(post, {isolateScope: true}); + } + postLinkFns.push(post); + } + } + + + function getControllers(require, $element, elementControllers) { + var value, retrievalMethod = 'data', optional = false; + if (isString(require)) { + while((value = require.charAt(0)) == '^' || value == '?') { + require = require.substr(1); + if (value == '^') { + retrievalMethod = 'inheritedData'; + } + optional = optional || value == '?'; + } + value = null; + + if (elementControllers && retrievalMethod === 'data') { + value = elementControllers[require]; + } + value = value || $element[retrievalMethod]('$' + require + 'Controller'); + + if (!value && !optional) { + throw $compileMinErr('ctreq', + "Controller '{0}', required by directive '{1}', can't be found!", + require, directiveName); + } + return value; + } else if (isArray(require)) { + value = []; + forEach(require, function(require) { + value.push(getControllers(require, $element, elementControllers)); + }); + } + return value; + } + + + function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { + var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn; + + if (compileNode === linkNode) { + attrs = templateAttrs; + } else { + attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr)); + } + $element = attrs.$$element; + + if (newIsolateScopeDirective) { + var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/; + var $linkNode = jqLite(linkNode); + + isolateScope = scope.$new(true); + + if (templateDirective && (templateDirective === newIsolateScopeDirective.$$originalDirective)) { + $linkNode.data('$isolateScope', isolateScope) ; + } else { + $linkNode.data('$isolateScopeNoTemplate', isolateScope); + } + + + + safeAddClass($linkNode, 'ng-isolate-scope'); + + forEach(newIsolateScopeDirective.scope, function(definition, scopeName) { + var match = definition.match(LOCAL_REGEXP) || [], + attrName = match[3] || scopeName, + optional = (match[2] == '?'), + mode = match[1], // @, =, or & + lastValue, + parentGet, parentSet; + + isolateScope.$$isolateBindings[scopeName] = mode + attrName; + + switch (mode) { + + case '@': + attrs.$observe(attrName, function(value) { + isolateScope[scopeName] = value; + }); + attrs.$$observers[attrName].$$scope = scope; + if( attrs[attrName] ) { + // If the attribute has been provided then we trigger an interpolation to ensure + // the value is there for use in the link fn + isolateScope[scopeName] = $interpolate(attrs[attrName])(scope); + } + break; + + case '=': + if (optional && !attrs[attrName]) { + return; + } + parentGet = $parse(attrs[attrName]); + parentSet = parentGet.assign || function() { + // reset the change, or we will throw this exception on every $digest + lastValue = isolateScope[scopeName] = parentGet(scope); + throw $compileMinErr('nonassign', + "Expression '{0}' used with directive '{1}' is non-assignable!", + attrs[attrName], newIsolateScopeDirective.name); + }; + lastValue = isolateScope[scopeName] = parentGet(scope); + isolateScope.$watch(function parentValueWatch() { + var parentValue = parentGet(scope); + + if (parentValue !== isolateScope[scopeName]) { + // we are out of sync and need to copy + if (parentValue !== lastValue) { + // parent changed and it has precedence + lastValue = isolateScope[scopeName] = parentValue; + } else { + // if the parent can be assigned then do so + parentSet(scope, parentValue = lastValue = isolateScope[scopeName]); + } + } + return parentValue; + }); + break; + + case '&': + parentGet = $parse(attrs[attrName]); + isolateScope[scopeName] = function(locals) { + return parentGet(scope, locals); + }; + break; + + default: + throw $compileMinErr('iscp', + "Invalid isolate scope definition for directive '{0}'." + + " Definition: {... {1}: '{2}' ...}", + newIsolateScopeDirective.name, scopeName, definition); + } + }); + } + transcludeFn = boundTranscludeFn && controllersBoundTransclude; + if (controllerDirectives) { + forEach(controllerDirectives, function(directive) { + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }, controllerInstance; + + controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + controllerInstance = $controller(controller, locals); + // For directives with element transclusion the element is a comment, + // but jQuery .data doesn't support attaching data to comment nodes as it's hard to + // clean up (http://bugs.jquery.com/ticket/8335). + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + if (!hasElementTranscludeDirective) { + $element.data('$' + directive.name + 'Controller', controllerInstance); + } + + if (directive.controllerAs) { + locals.$scope[directive.controllerAs] = controllerInstance; + } + }); + } + + // PRELINKING + for(i = 0, ii = preLinkFns.length; i < ii; i++) { + try { + linkFn = preLinkFns[i]; + linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs, + linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn); + } catch (e) { + $exceptionHandler(e, startingTag($element)); + } + } + + // RECURSION + // We only pass the isolate scope, if the isolate directive has a template, + // otherwise the child elements do not belong to the isolate directive. + var scopeToChild = scope; + if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { + scopeToChild = isolateScope; + } + childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); + + // POSTLINKING + for(i = postLinkFns.length - 1; i >= 0; i--) { + try { + linkFn = postLinkFns[i]; + linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs, + linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn); + } catch (e) { + $exceptionHandler(e, startingTag($element)); + } + } + + // This is the function that is injected as `$transclude`. + function controllersBoundTransclude(scope, cloneAttachFn) { + var transcludeControllers; + + // no scope passed + if (arguments.length < 2) { + cloneAttachFn = scope; + scope = undefined; + } + + if (hasElementTranscludeDirective) { + transcludeControllers = elementControllers; + } + + return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers); + } + } + } + + function markDirectivesAsIsolate(directives) { + // mark all directives as needing isolate scope. + for (var j = 0, jj = directives.length; j < jj; j++) { + directives[j] = inherit(directives[j], {$$isolateScope: true}); + } + } + + /** + * looks up the directive and decorates it with exception handling and proper parameters. We + * call this the boundDirective. + * + * @param {string} name name of the directive to look up. + * @param {string} location The directive must be found in specific format. + * String containing any of theses characters: + * + * * `E`: element name + * * `A': attribute + * * `C`: class + * * `M`: comment + * @returns true if directive was added. + */ + function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, + endAttrName) { + if (name === ignoreDirective) return null; + var match = null; + if (hasDirectives.hasOwnProperty(name)) { + for(var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i directive.priority) && + directive.restrict.indexOf(location) != -1) { + if (startAttrName) { + directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); + } + tDirectives.push(directive); + match = directive; + } + } catch(e) { $exceptionHandler(e); } + } + } + return match; + } + + + /** + * When the element is replaced with HTML template then the new attributes + * on the template need to be merged with the existing attributes in the DOM. + * The desired effect is to have both of the attributes present. + * + * @param {object} dst destination attributes (original DOM) + * @param {object} src source attributes (from the directive template) + */ + function mergeTemplateAttributes(dst, src) { + var srcAttr = src.$attr, + dstAttr = dst.$attr, + $element = dst.$$element; + + // reapply the old attributes to the new element + forEach(dst, function(value, key) { + if (key.charAt(0) != '$') { + if (src[key]) { + value += (key === 'style' ? ';' : ' ') + src[key]; + } + dst.$set(key, value, true, srcAttr[key]); + } + }); + + // copy the new attributes on the old attrs object + forEach(src, function(value, key) { + if (key == 'class') { + safeAddClass($element, value); + dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; + } else if (key == 'style') { + $element.attr('style', $element.attr('style') + ';' + value); + dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value; + // `dst` will never contain hasOwnProperty as DOM parser won't let it. + // You will get an "InvalidCharacterError: DOM Exception 5" error if you + // have an attribute like "has-own-property" or "data-has-own-property", etc. + } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { + dst[key] = value; + dstAttr[key] = srcAttr[key]; + } + }); + } + + + function compileTemplateUrl(directives, $compileNode, tAttrs, + $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { + var linkQueue = [], + afterTemplateNodeLinkFn, + afterTemplateChildLinkFn, + beforeTemplateCompileNode = $compileNode[0], + origAsyncDirective = directives.shift(), + // The fact that we have to copy and patch the directive seems wrong! + derivedSyncDirective = extend({}, origAsyncDirective, { + templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective + }), + templateUrl = (isFunction(origAsyncDirective.templateUrl)) + ? origAsyncDirective.templateUrl($compileNode, tAttrs) + : origAsyncDirective.templateUrl; + + $compileNode.html(''); + + $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}). + success(function(content) { + var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; + + content = denormalizeTemplate(content); + + if (origAsyncDirective.replace) { + $template = jqLite('
' + trim(content) + '
').contents(); + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== 1) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + origAsyncDirective.name, templateUrl); + } + + tempTemplateAttrs = {$attr: {}}; + replaceWith($rootElement, $compileNode, compileNode); + var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); + + if (isObject(origAsyncDirective.scope)) { + markDirectivesAsIsolate(templateDirectives); + } + directives = templateDirectives.concat(directives); + mergeTemplateAttributes(tAttrs, tempTemplateAttrs); + } else { + compileNode = beforeTemplateCompileNode; + $compileNode.html(content); + } + + directives.unshift(derivedSyncDirective); + + afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, + childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, + previousCompileContext); + forEach($rootElement, function(node, i) { + if (node == compileNode) { + $rootElement[i] = $compileNode[0]; + } + }); + afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); + + + while(linkQueue.length) { + var scope = linkQueue.shift(), + beforeTemplateLinkNode = linkQueue.shift(), + linkRootElement = linkQueue.shift(), + boundTranscludeFn = linkQueue.shift(), + linkNode = $compileNode[0]; + + if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { + // it was cloned therefore we have to clone as well. + linkNode = jqLiteClone(compileNode); + replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); + } + if (afterTemplateNodeLinkFn.transclude) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude); + } else { + childBoundTranscludeFn = boundTranscludeFn; + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, + childBoundTranscludeFn); + } + linkQueue = null; + }). + error(function(response, code, headers, config) { + throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url); + }); + + return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { + if (linkQueue) { + linkQueue.push(scope); + linkQueue.push(node); + linkQueue.push(rootElement); + linkQueue.push(boundTranscludeFn); + } else { + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, boundTranscludeFn); + } + }; + } + + + /** + * Sorting function for bound directives. + */ + function byPriority(a, b) { + var diff = b.priority - a.priority; + if (diff !== 0) return diff; + if (a.name !== b.name) return (a.name < b.name) ? -1 : 1; + return a.index - b.index; + } + + + function assertNoDuplicate(what, previousDirective, directive, element) { + if (previousDirective) { + throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}', + previousDirective.name, directive.name, what, startingTag(element)); + } + } + + + function addTextInterpolateDirective(directives, text) { + var interpolateFn = $interpolate(text, true); + if (interpolateFn) { + directives.push({ + priority: 0, + compile: valueFn(function textInterpolateLinkFn(scope, node) { + var parent = node.parent(), + bindings = parent.data('$binding') || []; + bindings.push(interpolateFn); + safeAddClass(parent.data('$binding', bindings), 'ng-binding'); + scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { + node[0].nodeValue = value; + }); + }) + }); + } + } + + + function getTrustedContext(node, attrNormalizedName) { + if (attrNormalizedName == "srcdoc") { + return $sce.HTML; + } + var tag = nodeName_(node); + // maction[xlink:href] can source SVG. It's not limited to . + if (attrNormalizedName == "xlinkHref" || + (tag == "FORM" && attrNormalizedName == "action") || + (tag != "IMG" && (attrNormalizedName == "src" || + attrNormalizedName == "ngSrc"))) { + return $sce.RESOURCE_URL; + } + } + + + function addAttrInterpolateDirective(node, directives, value, name) { + var interpolateFn = $interpolate(value, true); + + // no interpolation found -> ignore + if (!interpolateFn) return; + + + if (name === "multiple" && nodeName_(node) === "SELECT") { + throw $compileMinErr("selmulti", + "Binding to the 'multiple' attribute is not supported. Element: {0}", + startingTag(node)); + } + + directives.push({ + priority: 100, + compile: function() { + return { + pre: function attrInterpolatePreLinkFn(scope, element, attr) { + var $$observers = (attr.$$observers || (attr.$$observers = {})); + + if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { + throw $compileMinErr('nodomevents', + "Interpolations for HTML DOM event attributes are disallowed. Please use the " + + "ng- versions (such as ng-click instead of onclick) instead."); + } + + // we need to interpolate again, in case the attribute value has been updated + // (e.g. by another directive's compile function) + interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name)); + + // if attribute was updated so that there is no interpolation going on we don't want to + // register any observers + if (!interpolateFn) return; + + // TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the + // actual attr value + attr[name] = interpolateFn(scope); + ($$observers[name] || ($$observers[name] = [])).$$inter = true; + (attr.$$observers && attr.$$observers[name].$$scope || scope). + $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { + //special case for class attribute addition + removal + //so that class changes can tap into the animation + //hooks provided by the $animate service. Be sure to + //skip animations when the first digest occurs (when + //both the new and the old values are the same) since + //the CSS classes are the non-interpolated values + if(name === 'class' && newValue != oldValue) { + attr.$updateClass(newValue, oldValue); + } else { + attr.$set(name, newValue); + } + }); + } + }; + } + }); + } + + + /** + * This is a special jqLite.replaceWith, which can replace items which + * have no parents, provided that the containing jqLite collection is provided. + * + * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes + * in the root of the tree. + * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep + * the shell, but replace its DOM node reference. + * @param {Node} newNode The new DOM node. + */ + function replaceWith($rootElement, elementsToRemove, newNode) { + var firstElementToRemove = elementsToRemove[0], + removeCount = elementsToRemove.length, + parent = firstElementToRemove.parentNode, + i, ii; + + if ($rootElement) { + for(i = 0, ii = $rootElement.length; i < ii; i++) { + if ($rootElement[i] == firstElementToRemove) { + $rootElement[i++] = newNode; + for (var j = i, j2 = j + removeCount - 1, + jj = $rootElement.length; + j < jj; j++, j2++) { + if (j2 < jj) { + $rootElement[j] = $rootElement[j2]; + } else { + delete $rootElement[j]; + } + } + $rootElement.length -= removeCount - 1; + break; + } + } + } + + if (parent) { + parent.replaceChild(newNode, firstElementToRemove); + } + var fragment = document.createDocumentFragment(); + fragment.appendChild(firstElementToRemove); + newNode[jqLite.expando] = firstElementToRemove[jqLite.expando]; + for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { + var element = elementsToRemove[k]; + jqLite(element).remove(); // must do this way to clean up expando + fragment.appendChild(element); + delete elementsToRemove[k]; + } + + elementsToRemove[0] = newNode; + elementsToRemove.length = 1; + } + + + function cloneAndAnnotateFn(fn, annotation) { + return extend(function() { return fn.apply(null, arguments); }, fn, annotation); + } + }]; +} + +var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i; +/** + * Converts all accepted directives format into proper directive name. + * All of these will become 'myDirective': + * my:Directive + * my-directive + * x-my-directive + * data-my:directive + * + * Also there is special case for Moz prefix starting with upper case letter. + * @param name Name to normalize + */ +function directiveNormalize(name) { + return camelCase(name.replace(PREFIX_REGEXP, '')); +} + +/** + * @ngdoc object + * @name ng.$compile.directive.Attributes + * + * @description + * A shared object between directive compile / linking functions which contains normalized DOM + * element attributes. The values reflect current binding state `{{ }}`. The normalization is + * needed since all of these are treated as equivalent in Angular: + * + * + */ + +/** + * @ngdoc property + * @name ng.$compile.directive.Attributes#$attr + * @propertyOf ng.$compile.directive.Attributes + * @returns {object} A map of DOM element attribute names to the normalized name. This is + * needed to do reverse lookup from normalized name back to actual name. + */ + + +/** + * @ngdoc function + * @name ng.$compile.directive.Attributes#$set + * @methodOf ng.$compile.directive.Attributes + * @function + * + * @description + * Set DOM element attribute value. + * + * + * @param {string} name Normalized element attribute name of the property to modify. The name is + * revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr} + * property to the original name. + * @param {string} value Value to set the attribute to. The value can be an interpolated string. + */ + + + +/** + * Closure compiler type information + */ + +function nodesetLinkingFn( + /* angular.Scope */ scope, + /* NodeList */ nodeList, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +){} + +function directiveLinkingFn( + /* nodesetLinkingFn */ nodesetLinkingFn, + /* angular.Scope */ scope, + /* Node */ node, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +){} + +function tokenDifference(str1, str2) { + var values = '', + tokens1 = str1.split(/\s+/), + tokens2 = str2.split(/\s+/); + + outer: + for(var i = 0; i < tokens1.length; i++) { + var token = tokens1[i]; + for(var j = 0; j < tokens2.length; j++) { + if(token == tokens2[j]) continue outer; + } + values += (values.length > 0 ? ' ' : '') + token; + } + return values; +} + +/** + * @ngdoc object + * @name ng.$controllerProvider + * @description + * The {@link ng.$controller $controller service} is used by Angular to create new + * controllers. + * + * This provider allows controller registration via the + * {@link ng.$controllerProvider#methods_register register} method. + */ +function $ControllerProvider() { + var controllers = {}, + CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; + + + /** + * @ngdoc function + * @name ng.$controllerProvider#register + * @methodOf ng.$controllerProvider + * @param {string|Object} name Controller name, or an object map of controllers where the keys are + * the names and the values are the constructors. + * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI + * annotations in the array notation). + */ + this.register = function(name, constructor) { + assertNotHasOwnProperty(name, 'controller'); + if (isObject(name)) { + extend(controllers, name); + } else { + controllers[name] = constructor; + } + }; + + + this.$get = ['$injector', '$window', function($injector, $window) { + + /** + * @ngdoc function + * @name ng.$controller + * @requires $injector + * + * @param {Function|string} constructor If called with a function then it's considered to be the + * controller constructor function. Otherwise it's considered to be a string which is used + * to retrieve the controller constructor using the following steps: + * + * * check if a controller with given name is registered via `$controllerProvider` + * * check if evaluating the string on the current scope returns a constructor + * * check `window[constructor]` on the global `window` object + * + * @param {Object} locals Injection locals for Controller. + * @return {Object} Instance of given controller. + * + * @description + * `$controller` service is responsible for instantiating controllers. + * + * It's just a simple call to {@link AUTO.$injector $injector}, but extracted into + * a service, so that one can override this service with {@link https://gist.github.com/1649788 + * BC version}. + */ + return function(expression, locals) { + var instance, match, constructor, identifier; + + if(isString(expression)) { + match = expression.match(CNTRL_REG), + constructor = match[1], + identifier = match[3]; + expression = controllers.hasOwnProperty(constructor) + ? controllers[constructor] + : getter(locals.$scope, constructor, true) || getter($window, constructor, true); + + assertArgFn(expression, constructor, true); + } + + instance = $injector.instantiate(expression, locals); + + if (identifier) { + if (!(locals && typeof locals.$scope == 'object')) { + throw minErr('$controller')('noscp', + "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", + constructor || expression.name, identifier); + } + + locals.$scope[identifier] = instance; + } + + return instance; + }; + }]; +} + +/** + * @ngdoc object + * @name ng.$document + * @requires $window + * + * @description + * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document` + * element. + */ +function $DocumentProvider(){ + this.$get = ['$window', function(window){ + return jqLite(window.document); + }]; +} + +/** + * @ngdoc function + * @name ng.$exceptionHandler + * @requires $log + * + * @description + * Any uncaught exception in angular expressions is delegated to this service. + * The default implementation simply delegates to `$log.error` which logs it into + * the browser console. + * + * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by + * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. + * + * ## Example: + * + *
+ *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {
+ *     return function (exception, cause) {
+ *       exception.message += ' (caused by "' + cause + '")';
+ *       throw exception;
+ *     };
+ *   });
+ * 
+ * + * This example will override the normal action of `$exceptionHandler`, to make angular + * exceptions fail hard when they happen, instead of just logging to the console. + * + * @param {Error} exception Exception associated with the error. + * @param {string=} cause optional information about the context in which + * the error was thrown. + * + */ +function $ExceptionHandlerProvider() { + this.$get = ['$log', function($log) { + return function(exception, cause) { + $log.error.apply($log, arguments); + }; + }]; +} + +/** + * Parse headers into key value object + * + * @param {string} headers Raw headers as a string + * @returns {Object} Parsed headers as key value object + */ +function parseHeaders(headers) { + var parsed = {}, key, val, i; + + if (!headers) return parsed; + + forEach(headers.split('\n'), function(line) { + i = line.indexOf(':'); + key = lowercase(trim(line.substr(0, i))); + val = trim(line.substr(i + 1)); + + if (key) { + if (parsed[key]) { + parsed[key] += ', ' + val; + } else { + parsed[key] = val; + } + } + }); + + return parsed; +} + + +/** + * Returns a function that provides access to parsed headers. + * + * Headers are lazy parsed when first requested. + * @see parseHeaders + * + * @param {(string|Object)} headers Headers to provide access to. + * @returns {function(string=)} Returns a getter function which if called with: + * + * - if called with single an argument returns a single header value or null + * - if called with no arguments returns an object containing all headers. + */ +function headersGetter(headers) { + var headersObj = isObject(headers) ? headers : undefined; + + return function(name) { + if (!headersObj) headersObj = parseHeaders(headers); + + if (name) { + return headersObj[lowercase(name)] || null; + } + + return headersObj; + }; +} + + +/** + * Chain all given functions + * + * This function is used for both request and response transforming + * + * @param {*} data Data to transform. + * @param {function(string=)} headers Http headers getter fn. + * @param {(function|Array.)} fns Function or an array of functions. + * @returns {*} Transformed data. + */ +function transformData(data, headers, fns) { + if (isFunction(fns)) + return fns(data, headers); + + forEach(fns, function(fn) { + data = fn(data, headers); + }); + + return data; +} + + +function isSuccess(status) { + return 200 <= status && status < 300; +} + + +function $HttpProvider() { + var JSON_START = /^\s*(\[|\{[^\{])/, + JSON_END = /[\}\]]\s*$/, + PROTECTION_PREFIX = /^\)\]\}',?\n/, + CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'}; + + var defaults = this.defaults = { + // transform incoming response data + transformResponse: [function(data) { + if (isString(data)) { + // strip json vulnerability protection prefix + data = data.replace(PROTECTION_PREFIX, ''); + if (JSON_START.test(data) && JSON_END.test(data)) + data = fromJson(data); + } + return data; + }], + + // transform outgoing request data + transformRequest: [function(d) { + return isObject(d) && !isFile(d) ? toJson(d) : d; + }], + + // default headers + headers: { + common: { + 'Accept': 'application/json, text/plain, */*' + }, + post: CONTENT_TYPE_APPLICATION_JSON, + put: CONTENT_TYPE_APPLICATION_JSON, + patch: CONTENT_TYPE_APPLICATION_JSON + }, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN' + }; + + /** + * Are ordered by request, i.e. they are applied in the same order as the + * array, on request, but reverse order, on response. + */ + var interceptorFactories = this.interceptors = []; + + /** + * For historical reasons, response interceptors are ordered by the order in which + * they are applied to the response. (This is the opposite of interceptorFactories) + */ + var responseInterceptorFactories = this.responseInterceptors = []; + + this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector', + function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) { + + var defaultCache = $cacheFactory('$http'); + + /** + * Interceptors stored in reverse order. Inner interceptors before outer interceptors. + * The reversal is needed so that we can build up the interception chain around the + * server request. + */ + var reversedInterceptors = []; + + forEach(interceptorFactories, function(interceptorFactory) { + reversedInterceptors.unshift(isString(interceptorFactory) + ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); + }); + + forEach(responseInterceptorFactories, function(interceptorFactory, index) { + var responseFn = isString(interceptorFactory) + ? $injector.get(interceptorFactory) + : $injector.invoke(interceptorFactory); + + /** + * Response interceptors go before "around" interceptors (no real reason, just + * had to pick one.) But they are already reversed, so we can't use unshift, hence + * the splice. + */ + reversedInterceptors.splice(index, 0, { + response: function(response) { + return responseFn($q.when(response)); + }, + responseError: function(response) { + return responseFn($q.reject(response)); + } + }); + }); + + + /** + * @ngdoc function + * @name ng.$http + * @requires $httpBackend + * @requires $browser + * @requires $cacheFactory + * @requires $rootScope + * @requires $q + * @requires $injector + * + * @description + * The `$http` service is a core Angular service that facilitates communication with the remote + * HTTP servers via the browser's {@link https://developer.mozilla.org/en/xmlhttprequest + * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}. + * + * For unit testing applications that use `$http` service, see + * {@link ngMock.$httpBackend $httpBackend mock}. + * + * For a higher level of abstraction, please check out the {@link ngResource.$resource + * $resource} service. + * + * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by + * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage + * it is important to familiarize yourself with these APIs and the guarantees they provide. + * + * + * # General usage + * The `$http` service is a function which takes a single argument — a configuration object — + * that is used to generate an HTTP request and returns a {@link ng.$q promise} + * with two $http specific methods: `success` and `error`. + * + *
+     *   $http({method: 'GET', url: '/someUrl'}).
+     *     success(function(data, status, headers, config) {
+     *       // this callback will be called asynchronously
+     *       // when the response is available
+     *     }).
+     *     error(function(data, status, headers, config) {
+     *       // called asynchronously if an error occurs
+     *       // or server returns response with an error status.
+     *     });
+     * 
+ * + * Since the returned value of calling the $http function is a `promise`, you can also use + * the `then` method to register callbacks, and these callbacks will receive a single argument – + * an object representing the response. See the API signature and type info below for more + * details. + * + * A response status code between 200 and 299 is considered a success status and + * will result in the success callback being called. Note that if the response is a redirect, + * XMLHttpRequest will transparently follow it, meaning that the error callback will not be + * called for such responses. + * + * # Calling $http from outside AngularJS + * The `$http` service will not actually send the request until the next `$digest()` is + * executed. Normally this is not an issue, since almost all the time your call to `$http` will + * be from within a `$apply()` block. + * If you are calling `$http` from outside Angular, then you should wrap it in a call to + * `$apply` to cause a $digest to occur and also to handle errors in the block correctly. + * + * ``` + * $scope.$apply(function() { + * $http(...); + * }); + * ``` + * + * # Writing Unit Tests that use $http + * When unit testing you are mostly responsible for scheduling the `$digest` cycle. If you do + * not trigger a `$digest` before calling `$httpBackend.flush()` then the request will not have + * been made and `$httpBackend.expect(...)` expectations will fail. The solution is to run the + * code that calls the `$http()` method inside a $apply block as explained in the previous + * section. + * + * ``` + * $httpBackend.expectGET(...); + * $scope.$apply(function() { + * $http.get(...); + * }); + * $httpBackend.flush(); + * ``` + * + * # Shortcut methods + * + * Since all invocations of the $http service require passing in an HTTP method and URL, and + * POST/PUT requests require request data to be provided as well, shortcut methods + * were created: + * + *
+     *   $http.get('/someUrl').success(successCallback);
+     *   $http.post('/someUrl', data).success(successCallback);
+     * 
+ * + * Complete list of shortcut methods: + * + * - {@link ng.$http#methods_get $http.get} + * - {@link ng.$http#methods_head $http.head} + * - {@link ng.$http#methods_post $http.post} + * - {@link ng.$http#methods_put $http.put} + * - {@link ng.$http#methods_delete $http.delete} + * - {@link ng.$http#methods_jsonp $http.jsonp} + * + * + * # Setting HTTP Headers + * + * The $http service will automatically add certain HTTP headers to all requests. These defaults + * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration + * object, which currently contains this default configuration: + * + * - `$httpProvider.defaults.headers.common` (headers that are common for all requests): + * - `Accept: application/json, text/plain, * / *` + * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests) + * - `Content-Type: application/json` + * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests) + * - `Content-Type: application/json` + * + * To add or overwrite these defaults, simply add or remove a property from these configuration + * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object + * with the lowercased HTTP method name as the key, e.g. + * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }. + * + * The defaults can also be set at runtime via the `$http.defaults` object in the same + * fashion. In addition, you can supply a `headers` property in the config object passed when + * calling `$http(config)`, which overrides the defaults without changing them globally. + * + * + * # Transforming Requests and Responses + * + * Both requests and responses can be transformed using transform functions. By default, Angular + * applies these transformations: + * + * Request transformations: + * + * - If the `data` property of the request configuration object contains an object, serialize it + * into JSON format. + * + * Response transformations: + * + * - If XSRF prefix is detected, strip it (see Security Considerations section below). + * - If JSON response is detected, deserialize it using a JSON parser. + * + * To globally augment or override the default transforms, modify the + * `$httpProvider.defaults.transformRequest` and `$httpProvider.defaults.transformResponse` + * properties. These properties are by default an array of transform functions, which allows you + * to `push` or `unshift` a new transformation function into the transformation chain. You can + * also decide to completely override any default transformations by assigning your + * transformation functions to these properties directly without the array wrapper. + * + * Similarly, to locally override the request/response transforms, augment the + * `transformRequest` and/or `transformResponse` properties of the configuration object passed + * into `$http`. + * + * + * # Caching + * + * To enable caching, set the request configuration `cache` property to `true` (to use default + * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}). + * When the cache is enabled, `$http` stores the response from the server in the specified + * cache. The next time the same request is made, the response is served from the cache without + * sending a request to the server. + * + * Note that even if the response is served from cache, delivery of the data is asynchronous in + * the same way that real requests are. + * + * If there are multiple GET requests for the same URL that should be cached using the same + * cache, but the cache is not populated yet, only one request to the server will be made and + * the remaining requests will be fulfilled using the response from the first request. + * + * You can change the default cache to a new object (built with + * {@link ng.$cacheFactory `$cacheFactory`}) by updating the + * {@link ng.$http#properties_defaults `$http.defaults.cache`} property. All requests who set + * their `cache` property to `true` will now use this cache object. + * + * If you set the default cache to `false` then only requests that specify their own custom + * cache object will be cached. + * + * # Interceptors + * + * Before you start creating interceptors, be sure to understand the + * {@link ng.$q $q and deferred/promise APIs}. + * + * For purposes of global error handling, authentication, or any kind of synchronous or + * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be + * able to intercept requests before they are handed to the server and + * responses before they are handed over to the application code that + * initiated these requests. The interceptors leverage the {@link ng.$q + * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing. + * + * The interceptors are service factories that are registered with the `$httpProvider` by + * adding them to the `$httpProvider.interceptors` array. The factory is called and + * injected with dependencies (if specified) and returns the interceptor. + * + * There are two kinds of interceptors (and two kinds of rejection interceptors): + * + * * `request`: interceptors get called with http `config` object. The function is free to + * modify the `config` or create a new one. The function needs to return the `config` + * directly or as a promise. + * * `requestError`: interceptor gets called when a previous interceptor threw an error or + * resolved with a rejection. + * * `response`: interceptors get called with http `response` object. The function is free to + * modify the `response` or create a new one. The function needs to return the `response` + * directly or as a promise. + * * `responseError`: interceptor gets called when a previous interceptor threw an error or + * resolved with a rejection. + * + * + *
+     *   // register the interceptor as a service
+     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
+     *     return {
+     *       // optional method
+     *       'request': function(config) {
+     *         // do something on success
+     *         return config || $q.when(config);
+     *       },
+     *
+     *       // optional method
+     *      'requestError': function(rejection) {
+     *         // do something on error
+     *         if (canRecover(rejection)) {
+     *           return responseOrNewPromise
+     *         }
+     *         return $q.reject(rejection);
+     *       },
+     *
+     *
+     *
+     *       // optional method
+     *       'response': function(response) {
+     *         // do something on success
+     *         return response || $q.when(response);
+     *       },
+     *
+     *       // optional method
+     *      'responseError': function(rejection) {
+     *         // do something on error
+     *         if (canRecover(rejection)) {
+     *           return responseOrNewPromise
+     *         }
+     *         return $q.reject(rejection);
+     *       };
+     *     }
+     *   });
+     *
+     *   $httpProvider.interceptors.push('myHttpInterceptor');
+     *
+     *
+     *   // register the interceptor via an anonymous factory
+     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
+     *     return {
+     *      'request': function(config) {
+     *          // same as above
+     *       },
+     *       'response': function(response) {
+     *          // same as above
+     *       }
+     *     };
+     *   });
+     * 
+ * + * # Response interceptors (DEPRECATED) + * + * Before you start creating interceptors, be sure to understand the + * {@link ng.$q $q and deferred/promise APIs}. + * + * For purposes of global error handling, authentication or any kind of synchronous or + * asynchronous preprocessing of received responses, it is desirable to be able to intercept + * responses for http requests before they are handed over to the application code that + * initiated these requests. The response interceptors leverage the {@link ng.$q + * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing. + * + * The interceptors are service factories that are registered with the $httpProvider by + * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and + * injected with dependencies (if specified) and returns the interceptor — a function that + * takes a {@link ng.$q promise} and returns the original or a new promise. + * + *
+     *   // register the interceptor as a service
+     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
+     *     return function(promise) {
+     *       return promise.then(function(response) {
+     *         // do something on success
+     *         return response;
+     *       }, function(response) {
+     *         // do something on error
+     *         if (canRecover(response)) {
+     *           return responseOrNewPromise
+     *         }
+     *         return $q.reject(response);
+     *       });
+     *     }
+     *   });
+     *
+     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');
+     *
+     *
+     *   // register the interceptor via an anonymous factory
+     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
+     *     return function(promise) {
+     *       // same as above
+     *     }
+     *   });
+     * 
+ * + * + * # Security Considerations + * + * When designing web applications, consider security threats from: + * + * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx + * JSON vulnerability} + * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} + * + * Both server and the client must cooperate in order to eliminate these threats. Angular comes + * pre-configured with strategies that address these issues, but for this to work backend server + * cooperation is required. + * + * ## JSON Vulnerability Protection + * + * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx + * JSON vulnerability} allows third party website to turn your JSON resource URL into + * {@link http://en.wikipedia.org/wiki/JSONP JSONP} request under some conditions. To + * counter this your server can prefix all JSON requests with following string `")]}',\n"`. + * Angular will automatically strip the prefix before processing it as JSON. + * + * For example if your server needs to return: + *
+     * ['one','two']
+     * 
+ * + * which is vulnerable to attack, your server can return: + *
+     * )]}',
+     * ['one','two']
+     * 
+ * + * Angular will strip the prefix, before processing the JSON. + * + * + * ## Cross Site Request Forgery (XSRF) Protection + * + * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which + * an unauthorized site can gain your user's private data. Angular provides a mechanism + * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie + * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only + * JavaScript that runs on your domain could read the cookie, your server can be assured that + * the XHR came from JavaScript running on your domain. The header will not be set for + * cross-domain requests. + * + * To take advantage of this, your server needs to set a token in a JavaScript readable session + * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the + * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure + * that only JavaScript running on your domain could have sent the request. The token must be + * unique for each user and must be verifiable by the server (to prevent the JavaScript from + * making up its own tokens). We recommend that the token is a digest of your site's + * authentication cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt} + * for added security. + * + * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName + * properties of either $httpProvider.defaults, or the per-request config object. + * + * + * @param {object} config Object describing the request to be made and how it should be + * processed. The object has following properties: + * + * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) + * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. + * - **params** – `{Object.}` – Map of strings or objects which will be turned + * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be + * JSONified. + * - **data** – `{string|Object}` – Data to be sent as the request message data. + * - **headers** – `{Object}` – Map of strings or functions which return strings representing + * HTTP headers to send to the server. If the return value of a function is null, the + * header will not be sent. + * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. + * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. + * - **transformRequest** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * - **transformResponse** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body and headers and returns its transformed (typically deserialized) version. + * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} + * that should abort the request when resolved. + * - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the + * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 + * requests with credentials} for more information. + * - **responseType** - `{string}` - see {@link + * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. + * + * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the + * standard `then` method and two http specific methods: `success` and `error`. The `then` + * method takes two arguments a success and an error callback which will be called with a + * response object. The `success` and `error` methods take a single argument - a function that + * will be called when the request succeeds or fails respectively. The arguments passed into + * these functions are destructured representation of the response object passed into the + * `then` method. The response object has these properties: + * + * - **data** – `{string|Object}` – The response body transformed with the transform + * functions. + * - **status** – `{number}` – HTTP status code of the response. + * - **headers** – `{function([headerName])}` – Header getter function. + * - **config** – `{Object}` – The configuration object that was used to generate the request. + * + * @property {Array.} pendingRequests Array of config objects for currently pending + * requests. This is primarily meant to be used for debugging purposes. + * + * + * @example + + +
+ + +
+ + + +
http status code: {{status}}
+
http response data: {{data}}
+
+
+ + function FetchCtrl($scope, $http, $templateCache) { + $scope.method = 'GET'; + $scope.url = 'http-hello.html'; + + $scope.fetch = function() { + $scope.code = null; + $scope.response = null; + + $http({method: $scope.method, url: $scope.url, cache: $templateCache}). + success(function(data, status) { + $scope.status = status; + $scope.data = data; + }). + error(function(data, status) { + $scope.data = data || "Request failed"; + $scope.status = status; + }); + }; + + $scope.updateModel = function(method, url) { + $scope.method = method; + $scope.url = url; + }; + } + + + Hello, $http! + + + it('should make an xhr GET request', function() { + element(':button:contains("Sample GET")').click(); + element(':button:contains("fetch")').click(); + expect(binding('status')).toBe('200'); + expect(binding('data')).toMatch(/Hello, \$http!/); + }); + + it('should make a JSONP request to angularjs.org', function() { + element(':button:contains("Sample JSONP")').click(); + element(':button:contains("fetch")').click(); + expect(binding('status')).toBe('200'); + expect(binding('data')).toMatch(/Super Hero!/); + }); + + it('should make JSONP request to invalid URL and invoke the error handler', + function() { + element(':button:contains("Invalid JSONP")').click(); + element(':button:contains("fetch")').click(); + expect(binding('status')).toBe('0'); + expect(binding('data')).toBe('Request failed'); + }); + +
+ */ + function $http(requestConfig) { + var config = { + transformRequest: defaults.transformRequest, + transformResponse: defaults.transformResponse + }; + var headers = mergeHeaders(requestConfig); + + extend(config, requestConfig); + config.headers = headers; + config.method = uppercase(config.method); + + var xsrfValue = urlIsSameOrigin(config.url) + ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName] + : undefined; + if (xsrfValue) { + headers[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; + } + + + var serverRequest = function(config) { + headers = config.headers; + var reqData = transformData(config.data, headersGetter(headers), config.transformRequest); + + // strip content-type if data is undefined + if (isUndefined(config.data)) { + forEach(headers, function(value, header) { + if (lowercase(header) === 'content-type') { + delete headers[header]; + } + }); + } + + if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { + config.withCredentials = defaults.withCredentials; + } + + // send request + return sendReq(config, reqData, headers).then(transformResponse, transformResponse); + }; + + var chain = [serverRequest, undefined]; + var promise = $q.when(config); + + // apply interceptors + forEach(reversedInterceptors, function(interceptor) { + if (interceptor.request || interceptor.requestError) { + chain.unshift(interceptor.request, interceptor.requestError); + } + if (interceptor.response || interceptor.responseError) { + chain.push(interceptor.response, interceptor.responseError); + } + }); + + while(chain.length) { + var thenFn = chain.shift(); + var rejectFn = chain.shift(); + + promise = promise.then(thenFn, rejectFn); + } + + promise.success = function(fn) { + promise.then(function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + promise.error = function(fn) { + promise.then(null, function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + return promise; + + function transformResponse(response) { + // make a copy since the response must be cacheable + var resp = extend({}, response, { + data: transformData(response.data, response.headers, config.transformResponse) + }); + return (isSuccess(response.status)) + ? resp + : $q.reject(resp); + } + + function mergeHeaders(config) { + var defHeaders = defaults.headers, + reqHeaders = extend({}, config.headers), + defHeaderName, lowercaseDefHeaderName, reqHeaderName; + + defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); + + // execute if header value is function + execHeaders(defHeaders); + execHeaders(reqHeaders); + + // using for-in instead of forEach to avoid unecessary iteration after header has been found + defaultHeadersIteration: + for (defHeaderName in defHeaders) { + lowercaseDefHeaderName = lowercase(defHeaderName); + + for (reqHeaderName in reqHeaders) { + if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { + continue defaultHeadersIteration; + } + } + + reqHeaders[defHeaderName] = defHeaders[defHeaderName]; + } + + return reqHeaders; + + function execHeaders(headers) { + var headerContent; + + forEach(headers, function(headerFn, header) { + if (isFunction(headerFn)) { + headerContent = headerFn(); + if (headerContent != null) { + headers[header] = headerContent; + } else { + delete headers[header]; + } + } + }); + } + } + } + + $http.pendingRequests = []; + + /** + * @ngdoc method + * @name ng.$http#get + * @methodOf ng.$http + * + * @description + * Shortcut method to perform `GET` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name ng.$http#delete + * @methodOf ng.$http + * + * @description + * Shortcut method to perform `DELETE` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name ng.$http#head + * @methodOf ng.$http + * + * @description + * Shortcut method to perform `HEAD` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name ng.$http#jsonp + * @methodOf ng.$http + * + * @description + * Shortcut method to perform `JSONP` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request. + * Should contain `JSON_CALLBACK` string. + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethods('get', 'delete', 'head', 'jsonp'); + + /** + * @ngdoc method + * @name ng.$http#post + * @methodOf ng.$http + * + * @description + * Shortcut method to perform `POST` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name ng.$http#put + * @methodOf ng.$http + * + * @description + * Shortcut method to perform `PUT` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethodsWithData('post', 'put'); + + /** + * @ngdoc property + * @name ng.$http#defaults + * @propertyOf ng.$http + * + * @description + * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of + * default headers, withCredentials as well as request and response transformations. + * + * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. + */ + $http.defaults = defaults; + + + return $http; + + + function createShortMethods(names) { + forEach(arguments, function(name) { + $http[name] = function(url, config) { + return $http(extend(config || {}, { + method: name, + url: url + })); + }; + }); + } + + + function createShortMethodsWithData(name) { + forEach(arguments, function(name) { + $http[name] = function(url, data, config) { + return $http(extend(config || {}, { + method: name, + url: url, + data: data + })); + }; + }); + } + + + /** + * Makes the request. + * + * !!! ACCESSES CLOSURE VARS: + * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests + */ + function sendReq(config, reqData, reqHeaders) { + var deferred = $q.defer(), + promise = deferred.promise, + cache, + cachedResp, + url = buildUrl(config.url, config.params); + + $http.pendingRequests.push(config); + promise.then(removePendingReq, removePendingReq); + + + if ((config.cache || defaults.cache) && config.cache !== false && config.method == 'GET') { + cache = isObject(config.cache) ? config.cache + : isObject(defaults.cache) ? defaults.cache + : defaultCache; + } + + if (cache) { + cachedResp = cache.get(url); + if (isDefined(cachedResp)) { + if (cachedResp.then) { + // cached request has already been sent, but there is no response yet + cachedResp.then(removePendingReq, removePendingReq); + return cachedResp; + } else { + // serving from cache + if (isArray(cachedResp)) { + resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2])); + } else { + resolvePromise(cachedResp, 200, {}); + } + } + } else { + // put the promise for the non-transformed response into cache as a placeholder + cache.put(url, promise); + } + } + + // if we won't have the response in cache, send the request to the backend + if (isUndefined(cachedResp)) { + $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, + config.withCredentials, config.responseType); + } + + return promise; + + + /** + * Callback registered to $httpBackend(): + * - caches the response if desired + * - resolves the raw $http promise + * - calls $apply + */ + function done(status, response, headersString) { + if (cache) { + if (isSuccess(status)) { + cache.put(url, [status, response, parseHeaders(headersString)]); + } else { + // remove promise from the cache + cache.remove(url); + } + } + + resolvePromise(response, status, headersString); + if (!$rootScope.$$phase) $rootScope.$apply(); + } + + + /** + * Resolves the raw $http promise. + */ + function resolvePromise(response, status, headers) { + // normalize internal statuses to 0 + status = Math.max(status, 0); + + (isSuccess(status) ? deferred.resolve : deferred.reject)({ + data: response, + status: status, + headers: headersGetter(headers), + config: config + }); + } + + + function removePendingReq() { + var idx = indexOf($http.pendingRequests, config); + if (idx !== -1) $http.pendingRequests.splice(idx, 1); + } + } + + + function buildUrl(url, params) { + if (!params) return url; + var parts = []; + forEachSorted(params, function(value, key) { + if (value === null || isUndefined(value)) return; + if (!isArray(value)) value = [value]; + + forEach(value, function(v) { + if (isObject(v)) { + v = toJson(v); + } + parts.push(encodeUriQuery(key) + '=' + + encodeUriQuery(v)); + }); + }); + return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); + } + + + }]; +} + +var XHR = window.XMLHttpRequest || function() { + /* global ActiveXObject */ + try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {} + try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {} + try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {} + throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest."); +}; + + +/** + * @ngdoc object + * @name ng.$httpBackend + * @requires $browser + * @requires $window + * @requires $document + * + * @description + * HTTP backend used by the {@link ng.$http service} that delegates to + * XMLHttpRequest object or JSONP and deals with browser incompatibilities. + * + * You should never need to use this service directly, instead use the higher-level abstractions: + * {@link ng.$http $http} or {@link ngResource.$resource $resource}. + * + * During testing this implementation is swapped with {@link ngMock.$httpBackend mock + * $httpBackend} which can be trained with responses. + */ +function $HttpBackendProvider() { + this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { + return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks, $document[0]); + }]; +} + +function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument) { + var ABORTED = -1; + + // TODO(vojta): fix the signature + return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { + var status; + $browser.$$incOutstandingRequestCount(); + url = url || $browser.url(); + + if (lowercase(method) == 'jsonp') { + var callbackId = '_' + (callbacks.counter++).toString(36); + callbacks[callbackId] = function(data) { + callbacks[callbackId].data = data; + }; + + var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId), + function() { + if (callbacks[callbackId].data) { + completeRequest(callback, 200, callbacks[callbackId].data); + } else { + completeRequest(callback, status || -2); + } + delete callbacks[callbackId]; + }); + } else { + var xhr = new XHR(); + xhr.open(method, url, true); + forEach(headers, function(value, key) { + if (isDefined(value)) { + xhr.setRequestHeader(key, value); + } + }); + + // In IE6 and 7, this might be called synchronously when xhr.send below is called and the + // response is in the cache. the promise api will ensure that to the app code the api is + // always async + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + var responseHeaders = null, + response = null; + + if(status !== ABORTED) { + responseHeaders = xhr.getAllResponseHeaders(); + response = xhr.responseType ? xhr.response : xhr.responseText; + } + + // responseText is the old-school way of retrieving response (supported by IE8 & 9) + // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) + completeRequest(callback, + status || xhr.status, + response, + responseHeaders); + } + }; + + if (withCredentials) { + xhr.withCredentials = true; + } + + if (responseType) { + xhr.responseType = responseType; + } + + xhr.send(post || null); + } + + if (timeout > 0) { + var timeoutId = $browserDefer(timeoutRequest, timeout); + } else if (timeout && timeout.then) { + timeout.then(timeoutRequest); + } + + + function timeoutRequest() { + status = ABORTED; + jsonpDone && jsonpDone(); + xhr && xhr.abort(); + } + + function completeRequest(callback, status, response, headersString) { + var protocol = urlResolve(url).protocol; + + // cancel timeout and subsequent timeout promise resolution + timeoutId && $browserDefer.cancel(timeoutId); + jsonpDone = xhr = null; + + // fix status code for file protocol (it's always 0) + status = (protocol == 'file' && status === 0) ? (response ? 200 : 404) : status; + + // normalize IE bug (http://bugs.jquery.com/ticket/1450) + status = status == 1223 ? 204 : status; + + callback(status, response, headersString); + $browser.$$completeOutstandingRequest(noop); + } + }; + + function jsonpReq(url, done) { + // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.: + // - fetches local scripts via XHR and evals them + // - adds and immediately removes script elements from the document + var script = rawDocument.createElement('script'), + doneWrapper = function() { + script.onreadystatechange = script.onload = script.onerror = null; + rawDocument.body.removeChild(script); + if (done) done(); + }; + + script.type = 'text/javascript'; + script.src = url; + + if (msie && msie <= 8) { + script.onreadystatechange = function() { + if (/loaded|complete/.test(script.readyState)) { + doneWrapper(); + } + }; + } else { + script.onload = script.onerror = function() { + doneWrapper(); + }; + } + + rawDocument.body.appendChild(script); + return doneWrapper; + } +} + +var $interpolateMinErr = minErr('$interpolate'); + +/** + * @ngdoc object + * @name ng.$interpolateProvider + * @function + * + * @description + * + * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. + * + * @example + + + +
+ //demo.label// +
+
+ + it('should interpolate binding with custom symbols', function() { + expect(binding('demo.label')).toBe('This binding is brought you by // interpolation symbols.'); + }); + +
+ */ +function $InterpolateProvider() { + var startSymbol = '{{'; + var endSymbol = '}}'; + + /** + * @ngdoc method + * @name ng.$interpolateProvider#startSymbol + * @methodOf ng.$interpolateProvider + * @description + * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. + * + * @param {string=} value new value to set the starting symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.startSymbol = function(value){ + if (value) { + startSymbol = value; + return this; + } else { + return startSymbol; + } + }; + + /** + * @ngdoc method + * @name ng.$interpolateProvider#endSymbol + * @methodOf ng.$interpolateProvider + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * @param {string=} value new value to set the ending symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.endSymbol = function(value){ + if (value) { + endSymbol = value; + return this; + } else { + return endSymbol; + } + }; + + + this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) { + var startSymbolLength = startSymbol.length, + endSymbolLength = endSymbol.length; + + /** + * @ngdoc function + * @name ng.$interpolate + * @function + * + * @requires $parse + * @requires $sce + * + * @description + * + * Compiles a string with markup into an interpolation function. This service is used by the + * HTML {@link ng.$compile $compile} service for data binding. See + * {@link ng.$interpolateProvider $interpolateProvider} for configuring the + * interpolation markup. + * + * +
+         var $interpolate = ...; // injected
+         var exp = $interpolate('Hello {{name}}!');
+         expect(exp({name:'Angular'}).toEqual('Hello Angular!');
+       
+ * + * + * @param {string} text The text with markup to interpolate. + * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have + * embedded expression in order to return an interpolation function. Strings with no + * embedded expression will return null for the interpolation function. + * @param {string=} trustedContext when provided, the returned function passes the interpolated + * result through {@link ng.$sce#methods_getTrusted $sce.getTrusted(interpolatedResult, + * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that + * provides Strict Contextual Escaping for details. + * @returns {function(context)} an interpolation function which is used to compute the + * interpolated string. The function has these parameters: + * + * * `context`: an object against which any expressions embedded in the strings are evaluated + * against. + * + */ + function $interpolate(text, mustHaveExpression, trustedContext) { + var startIndex, + endIndex, + index = 0, + parts = [], + length = text.length, + hasInterpolation = false, + fn, + exp, + concat = []; + + while(index < length) { + if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) && + ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) { + (index != startIndex) && parts.push(text.substring(index, startIndex)); + parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex))); + fn.exp = exp; + index = endIndex + endSymbolLength; + hasInterpolation = true; + } else { + // we did not find anything, so we have to add the remainder to the parts array + (index != length) && parts.push(text.substring(index)); + index = length; + } + } + + if (!(length = parts.length)) { + // we added, nothing, must have been an empty string. + parts.push(''); + length = 1; + } + + // Concatenating expressions makes it hard to reason about whether some combination of + // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a + // single expression be used for iframe[src], object[src], etc., we ensure that the value + // that's used is assigned or constructed by some JS code somewhere that is more testable or + // make it obvious that you bound the value to some user controlled value. This helps reduce + // the load when auditing for XSS issues. + if (trustedContext && parts.length > 1) { + throw $interpolateMinErr('noconcat', + "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + + "interpolations that concatenate multiple expressions when a trusted value is " + + "required. See http://docs.angularjs.org/api/ng.$sce", text); + } + + if (!mustHaveExpression || hasInterpolation) { + concat.length = length; + fn = function(context) { + try { + for(var i = 0, ii = length, part; i 0 && iteration >= count) { + deferred.resolve(iteration); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + } + + if (!skipApply) $rootScope.$apply(); + + }, delay); + + intervals[promise.$$intervalId] = deferred; + + return promise; + } + + + /** + * @ngdoc function + * @name ng.$interval#cancel + * @methodOf ng.$interval + * + * @description + * Cancels a task associated with the `promise`. + * + * @param {number} promise Promise returned by the `$interval` function. + * @returns {boolean} Returns `true` if the task was successfully canceled. + */ + interval.cancel = function(promise) { + if (promise && promise.$$intervalId in intervals) { + intervals[promise.$$intervalId].reject('canceled'); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + return true; + } + return false; + }; + + return interval; + }]; +} + +/** + * @ngdoc object + * @name ng.$locale + * + * @description + * $locale service provides localization rules for various Angular components. As of right now the + * only public api is: + * + * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) + */ +function $LocaleProvider(){ + this.$get = function() { + return { + id: 'en-us', + + NUMBER_FORMATS: { + DECIMAL_SEP: '.', + GROUP_SEP: ',', + PATTERNS: [ + { // Decimal Pattern + minInt: 1, + minFrac: 0, + maxFrac: 3, + posPre: '', + posSuf: '', + negPre: '-', + negSuf: '', + gSize: 3, + lgSize: 3 + },{ //Currency Pattern + minInt: 1, + minFrac: 2, + maxFrac: 2, + posPre: '\u00A4', + posSuf: '', + negPre: '(\u00A4', + negSuf: ')', + gSize: 3, + lgSize: 3 + } + ], + CURRENCY_SYM: '$' + }, + + DATETIME_FORMATS: { + MONTH: + 'January,February,March,April,May,June,July,August,September,October,November,December' + .split(','), + SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), + DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), + SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), + AMPMS: ['AM','PM'], + medium: 'MMM d, y h:mm:ss a', + short: 'M/d/yy h:mm a', + fullDate: 'EEEE, MMMM d, y', + longDate: 'MMMM d, y', + mediumDate: 'MMM d, y', + shortDate: 'M/d/yy', + mediumTime: 'h:mm:ss a', + shortTime: 'h:mm a' + }, + + pluralCat: function(num) { + if (num === 1) { + return 'one'; + } + return 'other'; + } + }; + }; +} + +var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, + DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; +var $locationMinErr = minErr('$location'); + + +/** + * Encode path using encodeUriSegment, ignoring forward slashes + * + * @param {string} path Path to encode + * @returns {string} + */ +function encodePath(path) { + var segments = path.split('/'), + i = segments.length; + + while (i--) { + segments[i] = encodeUriSegment(segments[i]); + } + + return segments.join('/'); +} + +function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) { + var parsedUrl = urlResolve(absoluteUrl, appBase); + + locationObj.$$protocol = parsedUrl.protocol; + locationObj.$$host = parsedUrl.hostname; + locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; +} + + +function parseAppUrl(relativeUrl, locationObj, appBase) { + var prefixed = (relativeUrl.charAt(0) !== '/'); + if (prefixed) { + relativeUrl = '/' + relativeUrl; + } + var match = urlResolve(relativeUrl, appBase); + locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ? + match.pathname.substring(1) : match.pathname); + locationObj.$$search = parseKeyValue(match.search); + locationObj.$$hash = decodeURIComponent(match.hash); + + // make sure path starts with '/'; + if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') { + locationObj.$$path = '/' + locationObj.$$path; + } +} + + +/** + * + * @param {string} begin + * @param {string} whole + * @returns {string} returns text from whole after begin or undefined if it does not begin with + * expected string. + */ +function beginsWith(begin, whole) { + if (whole.indexOf(begin) === 0) { + return whole.substr(begin.length); + } +} + + +function stripHash(url) { + var index = url.indexOf('#'); + return index == -1 ? url : url.substr(0, index); +} + + +function stripFile(url) { + return url.substr(0, stripHash(url).lastIndexOf('/') + 1); +} + +/* return the server only (scheme://host:port) */ +function serverBase(url) { + return url.substring(0, url.indexOf('/', url.indexOf('//') + 2)); +} + + +/** + * LocationHtml5Url represents an url + * This object is exposed as $location service when HTML5 mode is enabled and supported + * + * @constructor + * @param {string} appBase application base URL + * @param {string} basePrefix url path prefix + */ +function LocationHtml5Url(appBase, basePrefix) { + this.$$html5 = true; + basePrefix = basePrefix || ''; + var appBaseNoFile = stripFile(appBase); + parseAbsoluteUrl(appBase, this, appBase); + + + /** + * Parse given html5 (regular) url string into properties + * @param {string} newAbsoluteUrl HTML5 url + * @private + */ + this.$$parse = function(url) { + var pathUrl = beginsWith(appBaseNoFile, url); + if (!isString(pathUrl)) { + throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, + appBaseNoFile); + } + + parseAppUrl(pathUrl, this, appBase); + + if (!this.$$path) { + this.$$path = '/'; + } + + this.$$compose(); + }; + + /** + * Compose url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/' + }; + + this.$$rewrite = function(url) { + var appUrl, prevAppUrl; + + if ( (appUrl = beginsWith(appBase, url)) !== undefined ) { + prevAppUrl = appUrl; + if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) { + return appBaseNoFile + (beginsWith('/', appUrl) || appUrl); + } else { + return appBase + prevAppUrl; + } + } else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) { + return appBaseNoFile + appUrl; + } else if (appBaseNoFile == url + '/') { + return appBaseNoFile; + } + }; +} + + +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when developer doesn't opt into html5 mode. + * It also serves as the base class for html5 mode fallback on legacy browsers. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangUrl(appBase, hashPrefix) { + var appBaseNoFile = stripFile(appBase); + + parseAbsoluteUrl(appBase, this, appBase); + + + /** + * Parse given hashbang url into properties + * @param {string} url Hashbang url + * @private + */ + this.$$parse = function(url) { + var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); + var withoutHashUrl = withoutBaseUrl.charAt(0) == '#' + ? beginsWith(hashPrefix, withoutBaseUrl) + : (this.$$html5) + ? withoutBaseUrl + : ''; + + if (!isString(withoutHashUrl)) { + throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url, + hashPrefix); + } + parseAppUrl(withoutHashUrl, this, appBase); + + this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); + + this.$$compose(); + + /* + * In Windows, on an anchor node on documents loaded from + * the filesystem, the browser will return a pathname + * prefixed with the drive name ('/C:/path') when a + * pathname without a drive is set: + * * a.setAttribute('href', '/foo') + * * a.pathname === '/C:/foo' //true + * + * Inside of Angular, we're always using pathnames that + * do not include drive names for routing. + */ + function removeWindowsDriveName (path, url, base) { + /* + Matches paths for file protocol on windows, + such as /C:/foo/bar, and captures only /foo/bar. + */ + var windowsFilePathExp = /^\/?.*?:(\/.*)/; + + var firstPathSegmentMatch; + + //Get the relative path from the input URL. + if (url.indexOf(base) === 0) { + url = url.replace(base, ''); + } + + /* + * The input URL intentionally contains a + * first path segment that ends with a colon. + */ + if (windowsFilePathExp.exec(url)) { + return path; + } + + firstPathSegmentMatch = windowsFilePathExp.exec(path); + return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; + } + }; + + /** + * Compose hashbang url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : ''); + }; + + this.$$rewrite = function(url) { + if(stripHash(appBase) == stripHash(url)) { + return url; + } + }; +} + + +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when html5 history api is enabled but the browser + * does not support it. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangInHtml5Url(appBase, hashPrefix) { + this.$$html5 = true; + LocationHashbangUrl.apply(this, arguments); + + var appBaseNoFile = stripFile(appBase); + + this.$$rewrite = function(url) { + var appUrl; + + if ( appBase == stripHash(url) ) { + return url; + } else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) { + return appBase + hashPrefix + appUrl; + } else if ( appBaseNoFile === url + '/') { + return appBaseNoFile; + } + }; +} + + +LocationHashbangInHtml5Url.prototype = + LocationHashbangUrl.prototype = + LocationHtml5Url.prototype = { + + /** + * Are we in html5 mode? + * @private + */ + $$html5: false, + + /** + * Has any change been replacing ? + * @private + */ + $$replace: false, + + /** + * @ngdoc method + * @name ng.$location#absUrl + * @methodOf ng.$location + * + * @description + * This method is getter only. + * + * Return full url representation with all segments encoded according to rules specified in + * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}. + * + * @return {string} full url + */ + absUrl: locationGetter('$$absUrl'), + + /** + * @ngdoc method + * @name ng.$location#url + * @methodOf ng.$location + * + * @description + * This method is getter / setter. + * + * Return url (e.g. `/path?a=b#hash`) when called without any parameter. + * + * Change path, search and hash, when called with parameter and return `$location`. + * + * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`) + * @param {string=} replace The path that will be changed + * @return {string} url + */ + url: function(url, replace) { + if (isUndefined(url)) + return this.$$url; + + var match = PATH_MATCH.exec(url); + if (match[1]) this.path(decodeURIComponent(match[1])); + if (match[2] || match[1]) this.search(match[3] || ''); + this.hash(match[5] || '', replace); + + return this; + }, + + /** + * @ngdoc method + * @name ng.$location#protocol + * @methodOf ng.$location + * + * @description + * This method is getter only. + * + * Return protocol of current url. + * + * @return {string} protocol of current url + */ + protocol: locationGetter('$$protocol'), + + /** + * @ngdoc method + * @name ng.$location#host + * @methodOf ng.$location + * + * @description + * This method is getter only. + * + * Return host of current url. + * + * @return {string} host of current url. + */ + host: locationGetter('$$host'), + + /** + * @ngdoc method + * @name ng.$location#port + * @methodOf ng.$location + * + * @description + * This method is getter only. + * + * Return port of current url. + * + * @return {Number} port + */ + port: locationGetter('$$port'), + + /** + * @ngdoc method + * @name ng.$location#path + * @methodOf ng.$location + * + * @description + * This method is getter / setter. + * + * Return path of current url when called without any parameter. + * + * Change path when called with parameter and return `$location`. + * + * Note: Path should always begin with forward slash (/), this method will add the forward slash + * if it is missing. + * + * @param {string=} path New path + * @return {string} path + */ + path: locationGetterSetter('$$path', function(path) { + return path.charAt(0) == '/' ? path : '/' + path; + }), + + /** + * @ngdoc method + * @name ng.$location#search + * @methodOf ng.$location + * + * @description + * This method is getter / setter. + * + * Return search part (as object) of current url when called without any parameter. + * + * Change search part when called with parameter and return `$location`. + * + * @param {string|Object.|Object.>} search New search params - string or + * hash object. Hash object may contain an array of values, which will be decoded as duplicates in + * the url. + * + * @param {(string|Array)=} paramValue If `search` is a string, then `paramValue` will override only a + * single search parameter. If `paramValue` is an array, it will set the parameter as a + * comma-separated value. If `paramValue` is `null`, the parameter will be deleted. + * + * @return {string} search + */ + search: function(search, paramValue) { + switch (arguments.length) { + case 0: + return this.$$search; + case 1: + if (isString(search)) { + this.$$search = parseKeyValue(search); + } else if (isObject(search)) { + this.$$search = search; + } else { + throw $locationMinErr('isrcharg', + 'The first argument of the `$location#search()` call must be a string or an object.'); + } + break; + default: + if (isUndefined(paramValue) || paramValue === null) { + delete this.$$search[search]; + } else { + this.$$search[search] = paramValue; + } + } + + this.$$compose(); + return this; + }, + + /** + * @ngdoc method + * @name ng.$location#hash + * @methodOf ng.$location + * + * @description + * This method is getter / setter. + * + * Return hash fragment when called without any parameter. + * + * Change hash fragment when called with parameter and return `$location`. + * + * @param {string=} hash New hash fragment + * @return {string} hash + */ + hash: locationGetterSetter('$$hash', identity), + + /** + * @ngdoc method + * @name ng.$location#replace + * @methodOf ng.$location + * + * @description + * If called, all changes to $location during current `$digest` will be replacing current history + * record, instead of adding new one. + */ + replace: function() { + this.$$replace = true; + return this; + } +}; + +function locationGetter(property) { + return function() { + return this[property]; + }; +} + + +function locationGetterSetter(property, preprocess) { + return function(value) { + if (isUndefined(value)) + return this[property]; + + this[property] = preprocess(value); + this.$$compose(); + + return this; + }; +} + + +/** + * @ngdoc object + * @name ng.$location + * + * @requires $browser + * @requires $sniffer + * @requires $rootElement + * + * @description + * The $location service parses the URL in the browser address bar (based on the + * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL + * available to your application. Changes to the URL in the address bar are reflected into + * $location service and changes to $location are reflected into the browser address bar. + * + * **The $location service:** + * + * - Exposes the current URL in the browser address bar, so you can + * - Watch and observe the URL. + * - Change the URL. + * - Synchronizes the URL with the browser when the user + * - Changes the address bar. + * - Clicks the back or forward button (or clicks a History link). + * - Clicks on a link. + * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). + * + * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular + * Services: Using $location} + */ + +/** + * @ngdoc object + * @name ng.$locationProvider + * @description + * Use the `$locationProvider` to configure how the application deep linking paths are stored. + */ +function $LocationProvider(){ + var hashPrefix = '', + html5Mode = false; + + /** + * @ngdoc property + * @name ng.$locationProvider#hashPrefix + * @methodOf ng.$locationProvider + * @description + * @param {string=} prefix Prefix for hash part (containing path and search) + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.hashPrefix = function(prefix) { + if (isDefined(prefix)) { + hashPrefix = prefix; + return this; + } else { + return hashPrefix; + } + }; + + /** + * @ngdoc property + * @name ng.$locationProvider#html5Mode + * @methodOf ng.$locationProvider + * @description + * @param {boolean=} mode Use HTML5 strategy if available. + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.html5Mode = function(mode) { + if (isDefined(mode)) { + html5Mode = mode; + return this; + } else { + return html5Mode; + } + }; + + /** + * @ngdoc event + * @name ng.$location#$locationChangeStart + * @eventOf ng.$location + * @eventType broadcast on root scope + * @description + * Broadcasted before a URL will change. This change can be prevented by calling + * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more + * details about event object. Upon successful change + * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + */ + + /** + * @ngdoc event + * @name ng.$location#$locationChangeSuccess + * @eventOf ng.$location + * @eventType broadcast on root scope + * @description + * Broadcasted after a URL was changed. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + */ + + this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', + function( $rootScope, $browser, $sniffer, $rootElement) { + var $location, + LocationMode, + baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to '' + initialUrl = $browser.url(), + appBase; + + if (html5Mode) { + appBase = serverBase(initialUrl) + (baseHref || '/'); + LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; + } else { + appBase = stripHash(initialUrl); + LocationMode = LocationHashbangUrl; + } + $location = new LocationMode(appBase, '#' + hashPrefix); + $location.$$parse($location.$$rewrite(initialUrl)); + + $rootElement.on('click', function(event) { + // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) + // currently we open nice url link and redirect then + + if (event.ctrlKey || event.metaKey || event.which == 2) return; + + var elm = jqLite(event.target); + + // traverse the DOM up to find first A tag + while (lowercase(elm[0].nodeName) !== 'a') { + // ignore rewriting if no A tag (reached root element, or no parent - removed from document) + if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; + } + + var absHref = elm.prop('href'); + var rewrittenUrl = $location.$$rewrite(absHref); + + if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) { + event.preventDefault(); + if (rewrittenUrl != $browser.url()) { + // update location manually + $location.$$parse(rewrittenUrl); + $rootScope.$apply(); + // hack to work around FF6 bug 684208 when scenario runner clicks on links + window.angular['ff-684208-preventDefault'] = true; + } + } + }); + + + // rewrite hashbang url <> html5 url + if ($location.absUrl() != initialUrl) { + $browser.url($location.absUrl(), true); + } + + // update $location when $browser url changes + $browser.onUrlChange(function(newUrl) { + if ($location.absUrl() != newUrl) { + if ($rootScope.$broadcast('$locationChangeStart', newUrl, + $location.absUrl()).defaultPrevented) { + $browser.url($location.absUrl()); + return; + } + $rootScope.$evalAsync(function() { + var oldUrl = $location.absUrl(); + + $location.$$parse(newUrl); + afterLocationChange(oldUrl); + }); + if (!$rootScope.$$phase) $rootScope.$digest(); + } + }); + + // update browser + var changeCounter = 0; + $rootScope.$watch(function $locationWatch() { + var oldUrl = $browser.url(); + var currentReplace = $location.$$replace; + + if (!changeCounter || oldUrl != $location.absUrl()) { + changeCounter++; + $rootScope.$evalAsync(function() { + if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl). + defaultPrevented) { + $location.$$parse(oldUrl); + } else { + $browser.url($location.absUrl(), currentReplace); + afterLocationChange(oldUrl); + } + }); + } + $location.$$replace = false; + + return changeCounter; + }); + + return $location; + + function afterLocationChange(oldUrl) { + $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl); + } +}]; +} + +/** + * @ngdoc object + * @name ng.$log + * @requires $window + * + * @description + * Simple service for logging. Default implementation safely writes the message + * into the browser's console (if present). + * + * The main purpose of this service is to simplify debugging and troubleshooting. + * + * The default is to log `debug` messages. You can use + * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this. + * + * @example + + + function LogCtrl($scope, $log) { + $scope.$log = $log; + $scope.message = 'Hello World!'; + } + + +
+

Reload this page with open console, enter text and hit the log button...

+ Message: + + + + + +
+
+
+ */ + +/** + * @ngdoc object + * @name ng.$logProvider + * @description + * Use the `$logProvider` to configure how the application logs messages + */ +function $LogProvider(){ + var debug = true, + self = this; + + /** + * @ngdoc property + * @name ng.$logProvider#debugEnabled + * @methodOf ng.$logProvider + * @description + * @param {string=} flag enable or disable debug level messages + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.debugEnabled = function(flag) { + if (isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } + }; + + this.$get = ['$window', function($window){ + return { + /** + * @ngdoc method + * @name ng.$log#log + * @methodOf ng.$log + * + * @description + * Write a log message + */ + log: consoleLog('log'), + + /** + * @ngdoc method + * @name ng.$log#info + * @methodOf ng.$log + * + * @description + * Write an information message + */ + info: consoleLog('info'), + + /** + * @ngdoc method + * @name ng.$log#warn + * @methodOf ng.$log + * + * @description + * Write a warning message + */ + warn: consoleLog('warn'), + + /** + * @ngdoc method + * @name ng.$log#error + * @methodOf ng.$log + * + * @description + * Write an error message + */ + error: consoleLog('error'), + + /** + * @ngdoc method + * @name ng.$log#debug + * @methodOf ng.$log + * + * @description + * Write a debug message + */ + debug: (function () { + var fn = consoleLog('debug'); + + return function() { + if (debug) { + fn.apply(self, arguments); + } + }; + }()) + }; + + function formatError(arg) { + if (arg instanceof Error) { + if (arg.stack) { + arg = (arg.message && arg.stack.indexOf(arg.message) === -1) + ? 'Error: ' + arg.message + '\n' + arg.stack + : arg.stack; + } else if (arg.sourceURL) { + arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; + } + } + return arg; + } + + function consoleLog(type) { + var console = $window.console || {}, + logFn = console[type] || console.log || noop; + + if (logFn.apply) { + return function() { + var args = []; + forEach(arguments, function(arg) { + args.push(formatError(arg)); + }); + return logFn.apply(console, args); + }; + } + + // we are IE which either doesn't have window.console => this is noop and we do nothing, + // or we are IE where console.log doesn't have apply so we log at least first 2 args + return function(arg1, arg2) { + logFn(arg1, arg2 == null ? '' : arg2); + }; + } + }]; +} + +var $parseMinErr = minErr('$parse'); +var promiseWarningCache = {}; +var promiseWarning; + +// Sandboxing Angular Expressions +// ------------------------------ +// Angular expressions are generally considered safe because these expressions only have direct +// access to $scope and locals. However, one can obtain the ability to execute arbitrary JS code by +// obtaining a reference to native JS functions such as the Function constructor. +// +// As an example, consider the following Angular expression: +// +// {}.toString.constructor(alert("evil JS code")) +// +// We want to prevent this type of access. For the sake of performance, during the lexing phase we +// disallow any "dotted" access to any member named "constructor". +// +// For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor +// while evaluating the expression, which is a stronger but more expensive test. Since reflective +// calls are expensive anyway, this is not such a big deal compared to static dereferencing. +// +// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits +// against the expression language, but not to prevent exploits that were enabled by exposing +// sensitive JavaScript or browser apis on Scope. Exposing such objects on a Scope is never a good +// practice and therefore we are not even trying to protect against interaction with an object +// explicitly exposed in this way. +// +// A developer could foil the name check by aliasing the Function constructor under a different +// name on the scope. +// +// In general, it is not possible to access a Window object from an angular expression unless a +// window or some DOM object that has a reference to window is published onto a Scope. + +function ensureSafeMemberName(name, fullExpression) { + if (name === "constructor") { + throw $parseMinErr('isecfld', + 'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } + return name; +} + +function ensureSafeObject(obj, fullExpression) { + // nifty check if obj is Function that is fast and works across iframes and other contexts + if (obj && obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isWindow(obj) + obj && obj.document && obj.location && obj.alert && obj.setInterval) { + throw $parseMinErr('isecwindow', + 'Referencing the Window in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isElement(obj) + obj && (obj.nodeName || (obj.on && obj.find))) { + throw $parseMinErr('isecdom', + 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else { + return obj; + } +} + +var OPERATORS = { + /* jshint bitwise : false */ + 'null':function(){return null;}, + 'true':function(){return true;}, + 'false':function(){return false;}, + undefined:noop, + '+':function(self, locals, a,b){ + a=a(self, locals); b=b(self, locals); + if (isDefined(a)) { + if (isDefined(b)) { + return a + b; + } + return a; + } + return isDefined(b)?b:undefined;}, + '-':function(self, locals, a,b){ + a=a(self, locals); b=b(self, locals); + return (isDefined(a)?a:0)-(isDefined(b)?b:0); + }, + '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);}, + '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);}, + '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);}, + '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);}, + '=':noop, + '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);}, + '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);}, + '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);}, + '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);}, + '<':function(self, locals, a,b){return a(self, locals)':function(self, locals, a,b){return a(self, locals)>b(self, locals);}, + '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);}, + '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);}, + '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);}, + '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);}, + '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);}, +// '|':function(self, locals, a,b){return a|b;}, + '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));}, + '!':function(self, locals, a){return !a(self, locals);} +}; +/* jshint bitwise: true */ +var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; + + +///////////////////////////////////////// + + +/** + * @constructor + */ +var Lexer = function (options) { + this.options = options; +}; + +Lexer.prototype = { + constructor: Lexer, + + lex: function (text) { + this.text = text; + + this.index = 0; + this.ch = undefined; + this.lastCh = ':'; // can start regexp + + this.tokens = []; + + var token; + var json = []; + + while (this.index < this.text.length) { + this.ch = this.text.charAt(this.index); + if (this.is('"\'')) { + this.readString(this.ch); + } else if (this.isNumber(this.ch) || this.is('.') && this.isNumber(this.peek())) { + this.readNumber(); + } else if (this.isIdent(this.ch)) { + this.readIdent(); + // identifiers can only be if the preceding char was a { or , + if (this.was('{,') && json[0] === '{' && + (token = this.tokens[this.tokens.length - 1])) { + token.json = token.text.indexOf('.') === -1; + } + } else if (this.is('(){}[].,;:?')) { + this.tokens.push({ + index: this.index, + text: this.ch, + json: (this.was(':[,') && this.is('{[')) || this.is('}]:,') + }); + if (this.is('{[')) json.unshift(this.ch); + if (this.is('}]')) json.shift(); + this.index++; + } else if (this.isWhitespace(this.ch)) { + this.index++; + continue; + } else { + var ch2 = this.ch + this.peek(); + var ch3 = ch2 + this.peek(2); + var fn = OPERATORS[this.ch]; + var fn2 = OPERATORS[ch2]; + var fn3 = OPERATORS[ch3]; + if (fn3) { + this.tokens.push({index: this.index, text: ch3, fn: fn3}); + this.index += 3; + } else if (fn2) { + this.tokens.push({index: this.index, text: ch2, fn: fn2}); + this.index += 2; + } else if (fn) { + this.tokens.push({ + index: this.index, + text: this.ch, + fn: fn, + json: (this.was('[,:') && this.is('+-')) + }); + this.index += 1; + } else { + this.throwError('Unexpected next character ', this.index, this.index + 1); + } + } + this.lastCh = this.ch; + } + return this.tokens; + }, + + is: function(chars) { + return chars.indexOf(this.ch) !== -1; + }, + + was: function(chars) { + return chars.indexOf(this.lastCh) !== -1; + }, + + peek: function(i) { + var num = i || 1; + return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false; + }, + + isNumber: function(ch) { + return ('0' <= ch && ch <= '9'); + }, + + isWhitespace: function(ch) { + // IE treats non-breaking space as \u00A0 + return (ch === ' ' || ch === '\r' || ch === '\t' || + ch === '\n' || ch === '\v' || ch === '\u00A0'); + }, + + isIdent: function(ch) { + return ('a' <= ch && ch <= 'z' || + 'A' <= ch && ch <= 'Z' || + '_' === ch || ch === '$'); + }, + + isExpOperator: function(ch) { + return (ch === '-' || ch === '+' || this.isNumber(ch)); + }, + + throwError: function(error, start, end) { + end = end || this.index; + var colStr = (isDefined(start) + ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']' + : ' ' + end); + throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].', + error, colStr, this.text); + }, + + readNumber: function() { + var number = ''; + var start = this.index; + while (this.index < this.text.length) { + var ch = lowercase(this.text.charAt(this.index)); + if (ch == '.' || this.isNumber(ch)) { + number += ch; + } else { + var peekCh = this.peek(); + if (ch == 'e' && this.isExpOperator(peekCh)) { + number += ch; + } else if (this.isExpOperator(ch) && + peekCh && this.isNumber(peekCh) && + number.charAt(number.length - 1) == 'e') { + number += ch; + } else if (this.isExpOperator(ch) && + (!peekCh || !this.isNumber(peekCh)) && + number.charAt(number.length - 1) == 'e') { + this.throwError('Invalid exponent'); + } else { + break; + } + } + this.index++; + } + number = 1 * number; + this.tokens.push({ + index: start, + text: number, + json: true, + fn: function() { return number; } + }); + }, + + readIdent: function() { + var parser = this; + + var ident = ''; + var start = this.index; + + var lastDot, peekIndex, methodName, ch; + + while (this.index < this.text.length) { + ch = this.text.charAt(this.index); + if (ch === '.' || this.isIdent(ch) || this.isNumber(ch)) { + if (ch === '.') lastDot = this.index; + ident += ch; + } else { + break; + } + this.index++; + } + + //check if this is not a method invocation and if it is back out to last dot + if (lastDot) { + peekIndex = this.index; + while (peekIndex < this.text.length) { + ch = this.text.charAt(peekIndex); + if (ch === '(') { + methodName = ident.substr(lastDot - start + 1); + ident = ident.substr(0, lastDot - start); + this.index = peekIndex; + break; + } + if (this.isWhitespace(ch)) { + peekIndex++; + } else { + break; + } + } + } + + + var token = { + index: start, + text: ident + }; + + // OPERATORS is our own object so we don't need to use special hasOwnPropertyFn + if (OPERATORS.hasOwnProperty(ident)) { + token.fn = OPERATORS[ident]; + token.json = OPERATORS[ident]; + } else { + var getter = getterFn(ident, this.options, this.text); + token.fn = extend(function(self, locals) { + return (getter(self, locals)); + }, { + assign: function(self, value) { + return setter(self, ident, value, parser.text, parser.options); + } + }); + } + + this.tokens.push(token); + + if (methodName) { + this.tokens.push({ + index:lastDot, + text: '.', + json: false + }); + this.tokens.push({ + index: lastDot + 1, + text: methodName, + json: false + }); + } + }, + + readString: function(quote) { + var start = this.index; + this.index++; + var string = ''; + var rawString = quote; + var escape = false; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + rawString += ch; + if (escape) { + if (ch === 'u') { + var hex = this.text.substring(this.index + 1, this.index + 5); + if (!hex.match(/[\da-f]{4}/i)) + this.throwError('Invalid unicode escape [\\u' + hex + ']'); + this.index += 4; + string += String.fromCharCode(parseInt(hex, 16)); + } else { + var rep = ESCAPE[ch]; + if (rep) { + string += rep; + } else { + string += ch; + } + } + escape = false; + } else if (ch === '\\') { + escape = true; + } else if (ch === quote) { + this.index++; + this.tokens.push({ + index: start, + text: rawString, + string: string, + json: true, + fn: function() { return string; } + }); + return; + } else { + string += ch; + } + this.index++; + } + this.throwError('Unterminated quote', start); + } +}; + + +/** + * @constructor + */ +var Parser = function (lexer, $filter, options) { + this.lexer = lexer; + this.$filter = $filter; + this.options = options; +}; + +Parser.ZERO = function () { return 0; }; + +Parser.prototype = { + constructor: Parser, + + parse: function (text, json) { + this.text = text; + + //TODO(i): strip all the obsolte json stuff from this file + this.json = json; + + this.tokens = this.lexer.lex(text); + + if (json) { + // The extra level of aliasing is here, just in case the lexer misses something, so that + // we prevent any accidental execution in JSON. + this.assignment = this.logicalOR; + + this.functionCall = + this.fieldAccess = + this.objectIndex = + this.filterChain = function() { + this.throwError('is not valid json', {text: text, index: 0}); + }; + } + + var value = json ? this.primary() : this.statements(); + + if (this.tokens.length !== 0) { + this.throwError('is an unexpected token', this.tokens[0]); + } + + value.literal = !!value.literal; + value.constant = !!value.constant; + + return value; + }, + + primary: function () { + var primary; + if (this.expect('(')) { + primary = this.filterChain(); + this.consume(')'); + } else if (this.expect('[')) { + primary = this.arrayDeclaration(); + } else if (this.expect('{')) { + primary = this.object(); + } else { + var token = this.expect(); + primary = token.fn; + if (!primary) { + this.throwError('not a primary expression', token); + } + if (token.json) { + primary.constant = true; + primary.literal = true; + } + } + + var next, context; + while ((next = this.expect('(', '[', '.'))) { + if (next.text === '(') { + primary = this.functionCall(primary, context); + context = null; + } else if (next.text === '[') { + context = primary; + primary = this.objectIndex(primary); + } else if (next.text === '.') { + context = primary; + primary = this.fieldAccess(primary); + } else { + this.throwError('IMPOSSIBLE'); + } + } + return primary; + }, + + throwError: function(msg, token) { + throw $parseMinErr('syntax', + 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', + token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); + }, + + peekToken: function() { + if (this.tokens.length === 0) + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + return this.tokens[0]; + }, + + peek: function(e1, e2, e3, e4) { + if (this.tokens.length > 0) { + var token = this.tokens[0]; + var t = token.text; + if (t === e1 || t === e2 || t === e3 || t === e4 || + (!e1 && !e2 && !e3 && !e4)) { + return token; + } + } + return false; + }, + + expect: function(e1, e2, e3, e4){ + var token = this.peek(e1, e2, e3, e4); + if (token) { + if (this.json && !token.json) { + this.throwError('is not valid json', token); + } + this.tokens.shift(); + return token; + } + return false; + }, + + consume: function(e1){ + if (!this.expect(e1)) { + this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); + } + }, + + unaryFn: function(fn, right) { + return extend(function(self, locals) { + return fn(self, locals, right); + }, { + constant:right.constant + }); + }, + + ternaryFn: function(left, middle, right){ + return extend(function(self, locals){ + return left(self, locals) ? middle(self, locals) : right(self, locals); + }, { + constant: left.constant && middle.constant && right.constant + }); + }, + + binaryFn: function(left, fn, right) { + return extend(function(self, locals) { + return fn(self, locals, left, right); + }, { + constant:left.constant && right.constant + }); + }, + + statements: function() { + var statements = []; + while (true) { + if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) + statements.push(this.filterChain()); + if (!this.expect(';')) { + // optimize for the common case where there is only one statement. + // TODO(size): maybe we should not support multiple statements? + return (statements.length === 1) + ? statements[0] + : function(self, locals) { + var value; + for (var i = 0; i < statements.length; i++) { + var statement = statements[i]; + if (statement) { + value = statement(self, locals); + } + } + return value; + }; + } + } + }, + + filterChain: function() { + var left = this.expression(); + var token; + while (true) { + if ((token = this.expect('|'))) { + left = this.binaryFn(left, token.fn, this.filter()); + } else { + return left; + } + } + }, + + filter: function() { + var token = this.expect(); + var fn = this.$filter(token.text); + var argsFn = []; + while (true) { + if ((token = this.expect(':'))) { + argsFn.push(this.expression()); + } else { + var fnInvoke = function(self, locals, input) { + var args = [input]; + for (var i = 0; i < argsFn.length; i++) { + args.push(argsFn[i](self, locals)); + } + return fn.apply(self, args); + }; + return function() { + return fnInvoke; + }; + } + } + }, + + expression: function() { + return this.assignment(); + }, + + assignment: function() { + var left = this.ternary(); + var right; + var token; + if ((token = this.expect('='))) { + if (!left.assign) { + this.throwError('implies assignment but [' + + this.text.substring(0, token.index) + '] can not be assigned to', token); + } + right = this.ternary(); + return function(scope, locals) { + return left.assign(scope, right(scope, locals), locals); + }; + } + return left; + }, + + ternary: function() { + var left = this.logicalOR(); + var middle; + var token; + if ((token = this.expect('?'))) { + middle = this.ternary(); + if ((token = this.expect(':'))) { + return this.ternaryFn(left, middle, this.ternary()); + } else { + this.throwError('expected :', token); + } + } else { + return left; + } + }, + + logicalOR: function() { + var left = this.logicalAND(); + var token; + while (true) { + if ((token = this.expect('||'))) { + left = this.binaryFn(left, token.fn, this.logicalAND()); + } else { + return left; + } + } + }, + + logicalAND: function() { + var left = this.equality(); + var token; + if ((token = this.expect('&&'))) { + left = this.binaryFn(left, token.fn, this.logicalAND()); + } + return left; + }, + + equality: function() { + var left = this.relational(); + var token; + if ((token = this.expect('==','!=','===','!=='))) { + left = this.binaryFn(left, token.fn, this.equality()); + } + return left; + }, + + relational: function() { + var left = this.additive(); + var token; + if ((token = this.expect('<', '>', '<=', '>='))) { + left = this.binaryFn(left, token.fn, this.relational()); + } + return left; + }, + + additive: function() { + var left = this.multiplicative(); + var token; + while ((token = this.expect('+','-'))) { + left = this.binaryFn(left, token.fn, this.multiplicative()); + } + return left; + }, + + multiplicative: function() { + var left = this.unary(); + var token; + while ((token = this.expect('*','/','%'))) { + left = this.binaryFn(left, token.fn, this.unary()); + } + return left; + }, + + unary: function() { + var token; + if (this.expect('+')) { + return this.primary(); + } else if ((token = this.expect('-'))) { + return this.binaryFn(Parser.ZERO, token.fn, this.unary()); + } else if ((token = this.expect('!'))) { + return this.unaryFn(token.fn, this.unary()); + } else { + return this.primary(); + } + }, + + fieldAccess: function(object) { + var parser = this; + var field = this.expect().text; + var getter = getterFn(field, this.options, this.text); + + return extend(function(scope, locals, self) { + return getter(self || object(scope, locals), locals); + }, { + assign: function(scope, value, locals) { + return setter(object(scope, locals), field, value, parser.text, parser.options); + } + }); + }, + + objectIndex: function(obj) { + var parser = this; + + var indexFn = this.expression(); + this.consume(']'); + + return extend(function(self, locals) { + var o = obj(self, locals), + i = indexFn(self, locals), + v, p; + + if (!o) return undefined; + v = ensureSafeObject(o[i], parser.text); + if (v && v.then && parser.options.unwrapPromises) { + p = v; + if (!('$$v' in v)) { + p.$$v = undefined; + p.then(function(val) { p.$$v = val; }); + } + v = v.$$v; + } + return v; + }, { + assign: function(self, value, locals) { + var key = indexFn(self, locals); + // prevent overwriting of Function.constructor which would break ensureSafeObject check + var safe = ensureSafeObject(obj(self, locals), parser.text); + return safe[key] = value; + } + }); + }, + + functionCall: function(fn, contextGetter) { + var argsFn = []; + if (this.peekToken().text !== ')') { + do { + argsFn.push(this.expression()); + } while (this.expect(',')); + } + this.consume(')'); + + var parser = this; + + return function(scope, locals) { + var args = []; + var context = contextGetter ? contextGetter(scope, locals) : scope; + + for (var i = 0; i < argsFn.length; i++) { + args.push(argsFn[i](scope, locals)); + } + var fnPtr = fn(scope, locals, context) || noop; + + ensureSafeObject(context, parser.text); + ensureSafeObject(fnPtr, parser.text); + + // IE stupidity! (IE doesn't have apply for some native functions) + var v = fnPtr.apply + ? fnPtr.apply(context, args) + : fnPtr(args[0], args[1], args[2], args[3], args[4]); + + return ensureSafeObject(v, parser.text); + }; + }, + + // This is used with json array declaration + arrayDeclaration: function () { + var elementFns = []; + var allConstant = true; + if (this.peekToken().text !== ']') { + do { + var elementFn = this.expression(); + elementFns.push(elementFn); + if (!elementFn.constant) { + allConstant = false; + } + } while (this.expect(',')); + } + this.consume(']'); + + return extend(function(self, locals) { + var array = []; + for (var i = 0; i < elementFns.length; i++) { + array.push(elementFns[i](self, locals)); + } + return array; + }, { + literal: true, + constant: allConstant + }); + }, + + object: function () { + var keyValues = []; + var allConstant = true; + if (this.peekToken().text !== '}') { + do { + var token = this.expect(), + key = token.string || token.text; + this.consume(':'); + var value = this.expression(); + keyValues.push({key: key, value: value}); + if (!value.constant) { + allConstant = false; + } + } while (this.expect(',')); + } + this.consume('}'); + + return extend(function(self, locals) { + var object = {}; + for (var i = 0; i < keyValues.length; i++) { + var keyValue = keyValues[i]; + object[keyValue.key] = keyValue.value(self, locals); + } + return object; + }, { + literal: true, + constant: allConstant + }); + } +}; + + +////////////////////////////////////////////////// +// Parser helper functions +////////////////////////////////////////////////// + +function setter(obj, path, setValue, fullExp, options) { + //needed? + options = options || {}; + + var element = path.split('.'), key; + for (var i = 0; element.length > 1; i++) { + key = ensureSafeMemberName(element.shift(), fullExp); + var propertyObj = obj[key]; + if (!propertyObj) { + propertyObj = {}; + obj[key] = propertyObj; + } + obj = propertyObj; + if (obj.then && options.unwrapPromises) { + promiseWarning(fullExp); + if (!("$$v" in obj)) { + (function(promise) { + promise.then(function(val) { promise.$$v = val; }); } + )(obj); + } + if (obj.$$v === undefined) { + obj.$$v = {}; + } + obj = obj.$$v; + } + } + key = ensureSafeMemberName(element.shift(), fullExp); + obj[key] = setValue; + return setValue; +} + +var getterFnCache = {}; + +/** + * Implementation of the "Black Hole" variant from: + * - http://jsperf.com/angularjs-parse-getter/4 + * - http://jsperf.com/path-evaluation-simplified/7 + */ +function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) { + ensureSafeMemberName(key0, fullExp); + ensureSafeMemberName(key1, fullExp); + ensureSafeMemberName(key2, fullExp); + ensureSafeMemberName(key3, fullExp); + ensureSafeMemberName(key4, fullExp); + + return !options.unwrapPromises + ? function cspSafeGetter(scope, locals) { + var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope; + + if (pathVal === null || pathVal === undefined) return pathVal; + pathVal = pathVal[key0]; + + if (!key1 || pathVal === null || pathVal === undefined) return pathVal; + pathVal = pathVal[key1]; + + if (!key2 || pathVal === null || pathVal === undefined) return pathVal; + pathVal = pathVal[key2]; + + if (!key3 || pathVal === null || pathVal === undefined) return pathVal; + pathVal = pathVal[key3]; + + if (!key4 || pathVal === null || pathVal === undefined) return pathVal; + pathVal = pathVal[key4]; + + return pathVal; + } + : function cspSafePromiseEnabledGetter(scope, locals) { + var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope, + promise; + + if (pathVal === null || pathVal === undefined) return pathVal; + + pathVal = pathVal[key0]; + if (pathVal && pathVal.then) { + promiseWarning(fullExp); + if (!("$$v" in pathVal)) { + promise = pathVal; + promise.$$v = undefined; + promise.then(function(val) { promise.$$v = val; }); + } + pathVal = pathVal.$$v; + } + if (!key1 || pathVal === null || pathVal === undefined) return pathVal; + + pathVal = pathVal[key1]; + if (pathVal && pathVal.then) { + promiseWarning(fullExp); + if (!("$$v" in pathVal)) { + promise = pathVal; + promise.$$v = undefined; + promise.then(function(val) { promise.$$v = val; }); + } + pathVal = pathVal.$$v; + } + if (!key2 || pathVal === null || pathVal === undefined) return pathVal; + + pathVal = pathVal[key2]; + if (pathVal && pathVal.then) { + promiseWarning(fullExp); + if (!("$$v" in pathVal)) { + promise = pathVal; + promise.$$v = undefined; + promise.then(function(val) { promise.$$v = val; }); + } + pathVal = pathVal.$$v; + } + if (!key3 || pathVal === null || pathVal === undefined) return pathVal; + + pathVal = pathVal[key3]; + if (pathVal && pathVal.then) { + promiseWarning(fullExp); + if (!("$$v" in pathVal)) { + promise = pathVal; + promise.$$v = undefined; + promise.then(function(val) { promise.$$v = val; }); + } + pathVal = pathVal.$$v; + } + if (!key4 || pathVal === null || pathVal === undefined) return pathVal; + + pathVal = pathVal[key4]; + if (pathVal && pathVal.then) { + promiseWarning(fullExp); + if (!("$$v" in pathVal)) { + promise = pathVal; + promise.$$v = undefined; + promise.then(function(val) { promise.$$v = val; }); + } + pathVal = pathVal.$$v; + } + return pathVal; + }; +} + +function getterFn(path, options, fullExp) { + // Check whether the cache has this getter already. + // We can use hasOwnProperty directly on the cache because we ensure, + // see below, that the cache never stores a path called 'hasOwnProperty' + if (getterFnCache.hasOwnProperty(path)) { + return getterFnCache[path]; + } + + var pathKeys = path.split('.'), + pathKeysLength = pathKeys.length, + fn; + + if (options.csp) { + if (pathKeysLength < 6) { + fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, + options); + } else { + fn = function(scope, locals) { + var i = 0, val; + do { + val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], + pathKeys[i++], fullExp, options)(scope, locals); + + locals = undefined; // clear after first iteration + scope = val; + } while (i < pathKeysLength); + return val; + }; + } + } else { + var code = 'var l, fn, p;\n'; + forEach(pathKeys, function(key, index) { + ensureSafeMemberName(key, fullExp); + code += 'if(s === null || s === undefined) return s;\n' + + 'l=s;\n' + + 's='+ (index + // we simply dereference 's' on any .dot notation + ? 's' + // but if we are first then we check locals first, and if so read it first + : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' + + (options.unwrapPromises + ? 'if (s && s.then) {\n' + + ' pw("' + fullExp.replace(/(["\r\n])/g, '\\$1') + '");\n' + + ' if (!("$$v" in s)) {\n' + + ' p=s;\n' + + ' p.$$v = undefined;\n' + + ' p.then(function(v) {p.$$v=v;});\n' + + '}\n' + + ' s=s.$$v\n' + + '}\n' + : ''); + }); + code += 'return s;'; + + /* jshint -W054 */ + var evaledFnGetter = new Function('s', 'k', 'pw', code); // s=scope, k=locals, pw=promiseWarning + /* jshint +W054 */ + evaledFnGetter.toString = function() { return code; }; + fn = function(scope, locals) { + return evaledFnGetter(scope, locals, promiseWarning); + }; + } + + // Only cache the value if it's not going to mess up the cache object + // This is more performant that using Object.prototype.hasOwnProperty.call + if (path !== 'hasOwnProperty') { + getterFnCache[path] = fn; + } + return fn; +} + +/////////////////////////////////// + +/** + * @ngdoc function + * @name ng.$parse + * @function + * + * @description + * + * Converts Angular {@link guide/expression expression} into a function. + * + *
+ *   var getter = $parse('user.name');
+ *   var setter = getter.assign;
+ *   var context = {user:{name:'angular'}};
+ *   var locals = {user:{name:'local'}};
+ *
+ *   expect(getter(context)).toEqual('angular');
+ *   setter(context, 'newValue');
+ *   expect(context.user.name).toEqual('newValue');
+ *   expect(getter(context, locals)).toEqual('local');
+ * 
+ * + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + * + * The returned function also has the following properties: + * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript + * literal. + * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript + * constant literals. + * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be + * set to a function to change its value on the given context. + * + */ + + +/** + * @ngdoc object + * @name ng.$parseProvider + * @function + * + * @description + * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} + * service. + */ +function $ParseProvider() { + var cache = {}; + + var $parseOptions = { + csp: false, + unwrapPromises: false, + logPromiseWarnings: true + }; + + + /** + * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future. + * + * @ngdoc method + * @name ng.$parseProvider#unwrapPromises + * @methodOf ng.$parseProvider + * @description + * + * **This feature is deprecated, see deprecation notes below for more info** + * + * If set to true (default is false), $parse will unwrap promises automatically when a promise is + * found at any part of the expression. In other words, if set to true, the expression will always + * result in a non-promise value. + * + * While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled, + * the fulfillment value is used in place of the promise while evaluating the expression. + * + * **Deprecation notice** + * + * This is a feature that didn't prove to be wildly useful or popular, primarily because of the + * dichotomy between data access in templates (accessed as raw values) and controller code + * (accessed as promises). + * + * In most code we ended up resolving promises manually in controllers anyway and thus unifying + * the model access there. + * + * Other downsides of automatic promise unwrapping: + * + * - when building components it's often desirable to receive the raw promises + * - adds complexity and slows down expression evaluation + * - makes expression code pre-generation unattractive due to the amount of code that needs to be + * generated + * - makes IDE auto-completion and tool support hard + * + * **Warning Logs** + * + * If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a + * promise (to reduce the noise, each expression is logged only once). To disable this logging use + * `$parseProvider.logPromiseWarnings(false)` api. + * + * + * @param {boolean=} value New value. + * @returns {boolean|self} Returns the current setting when used as getter and self if used as + * setter. + */ + this.unwrapPromises = function(value) { + if (isDefined(value)) { + $parseOptions.unwrapPromises = !!value; + return this; + } else { + return $parseOptions.unwrapPromises; + } + }; + + + /** + * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future. + * + * @ngdoc method + * @name ng.$parseProvider#logPromiseWarnings + * @methodOf ng.$parseProvider + * @description + * + * Controls whether Angular should log a warning on any encounter of a promise in an expression. + * + * The default is set to `true`. + * + * This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well. + * + * @param {boolean=} value New value. + * @returns {boolean|self} Returns the current setting when used as getter and self if used as + * setter. + */ + this.logPromiseWarnings = function(value) { + if (isDefined(value)) { + $parseOptions.logPromiseWarnings = value; + return this; + } else { + return $parseOptions.logPromiseWarnings; + } + }; + + + this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) { + $parseOptions.csp = $sniffer.csp; + + promiseWarning = function promiseWarningFn(fullExp) { + if (!$parseOptions.logPromiseWarnings || promiseWarningCache.hasOwnProperty(fullExp)) return; + promiseWarningCache[fullExp] = true; + $log.warn('[$parse] Promise found in the expression `' + fullExp + '`. ' + + 'Automatic unwrapping of promises in Angular expressions is deprecated.'); + }; + + return function(exp) { + var parsedExpression; + + switch (typeof exp) { + case 'string': + + if (cache.hasOwnProperty(exp)) { + return cache[exp]; + } + + var lexer = new Lexer($parseOptions); + var parser = new Parser(lexer, $filter, $parseOptions); + parsedExpression = parser.parse(exp, false); + + if (exp !== 'hasOwnProperty') { + // Only cache the value if it's not going to mess up the cache object + // This is more performant that using Object.prototype.hasOwnProperty.call + cache[exp] = parsedExpression; + } + + return parsedExpression; + + case 'function': + return exp; + + default: + return noop; + } + }; + }]; +} + +/** + * @ngdoc service + * @name ng.$q + * @requires $rootScope + * + * @description + * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q). + * + * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an + * interface for interacting with an object that represents the result of an action that is + * performed asynchronously, and may or may not be finished at any given point in time. + * + * From the perspective of dealing with error handling, deferred and promise APIs are to + * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. + * + *
+ *   // for the purpose of this example let's assume that variables `$q` and `scope` are
+ *   // available in the current lexical scope (they could have been injected or passed in).
+ *
+ *   function asyncGreet(name) {
+ *     var deferred = $q.defer();
+ *
+ *     setTimeout(function() {
+ *       // since this fn executes async in a future turn of the event loop, we need to wrap
+ *       // our code into an $apply call so that the model changes are properly observed.
+ *       scope.$apply(function() {
+ *         deferred.notify('About to greet ' + name + '.');
+ *
+ *         if (okToGreet(name)) {
+ *           deferred.resolve('Hello, ' + name + '!');
+ *         } else {
+ *           deferred.reject('Greeting ' + name + ' is not allowed.');
+ *         }
+ *       });
+ *     }, 1000);
+ *
+ *     return deferred.promise;
+ *   }
+ *
+ *   var promise = asyncGreet('Robin Hood');
+ *   promise.then(function(greeting) {
+ *     alert('Success: ' + greeting);
+ *   }, function(reason) {
+ *     alert('Failed: ' + reason);
+ *   }, function(update) {
+ *     alert('Got notification: ' + update);
+ *   });
+ * 
+ * + * At first it might not be obvious why this extra complexity is worth the trouble. The payoff + * comes in the way of guarantees that promise and deferred APIs make, see + * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. + * + * Additionally the promise api allows for composition that is very hard to do with the + * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. + * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the + * section on serial or parallel joining of promises. + * + * + * # The Deferred API + * + * A new instance of deferred is constructed by calling `$q.defer()`. + * + * The purpose of the deferred object is to expose the associated Promise instance as well as APIs + * that can be used for signaling the successful or unsuccessful completion, as well as the status + * of the task. + * + * **Methods** + * + * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection + * constructed via `$q.reject`, the promise will be rejected instead. + * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to + * resolving it with a rejection constructed via `$q.reject`. + * - `notify(value)` - provides updates on the status of the promises execution. This may be called + * multiple times before the promise is either resolved or rejected. + * + * **Properties** + * + * - promise – `{Promise}` – promise object associated with this deferred. + * + * + * # The Promise API + * + * A new promise instance is created when a deferred instance is created and can be retrieved by + * calling `deferred.promise`. + * + * The purpose of the promise object is to allow for interested parties to get access to the result + * of the deferred task when it completes. + * + * **Methods** + * + * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or + * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously + * as soon as the result is available. The callbacks are called with a single argument: the result + * or rejection reason. Additionally, the notify callback may be called zero or more times to + * provide a progress indication, before the promise is resolved or rejected. + * + * This method *returns a new promise* which is resolved or rejected via the return value of the + * `successCallback`, `errorCallback`. It also notifies via the return value of the + * `notifyCallback` method. The promise can not be resolved or rejected from the notifyCallback + * method. + * + * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` + * + * - `finally(callback)` – allows you to observe either the fulfillment or rejection of a promise, + * but to do so without modifying the final value. This is useful to release resources or do some + * clean-up that needs to be done whether the promise was rejected or resolved. See the [full + * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for + * more information. + * + * Because `finally` is a reserved word in JavaScript and reserved keywords are not supported as + * property names by ES3, you'll need to invoke the method like `promise['finally'](callback)` to + * make your code IE8 compatible. + * + * # Chaining promises + * + * Because calling the `then` method of a promise returns a new derived promise, it is easily + * possible to create a chain of promises: + * + *
+ *   promiseB = promiseA.then(function(result) {
+ *     return result + 1;
+ *   });
+ *
+ *   // promiseB will be resolved immediately after promiseA is resolved and its value
+ *   // will be the result of promiseA incremented by 1
+ * 
+ * + * It is possible to create chains of any length and since a promise can be resolved with another + * promise (which will defer its resolution further), it is possible to pause/defer resolution of + * the promises at any point in the chain. This makes it possible to implement powerful APIs like + * $http's response interceptors. + * + * + * # Differences between Kris Kowal's Q and $q + * + * There are three main differences: + * + * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation + * mechanism in angular, which means faster propagation of resolution or rejection into your + * models and avoiding unnecessary browser repaints, which would result in flickering UI. + * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains + * all the important functionality needed for common async tasks. + * + * # Testing + * + *
+ *    it('should simulate promise', inject(function($q, $rootScope) {
+ *      var deferred = $q.defer();
+ *      var promise = deferred.promise;
+ *      var resolvedValue;
+ *
+ *      promise.then(function(value) { resolvedValue = value; });
+ *      expect(resolvedValue).toBeUndefined();
+ *
+ *      // Simulate resolving of promise
+ *      deferred.resolve(123);
+ *      // Note that the 'then' function does not get called synchronously.
+ *      // This is because we want the promise API to always be async, whether or not
+ *      // it got called synchronously or asynchronously.
+ *      expect(resolvedValue).toBeUndefined();
+ *
+ *      // Propagate promise resolution to 'then' functions using $apply().
+ *      $rootScope.$apply();
+ *      expect(resolvedValue).toEqual(123);
+ *    }));
+ *  
+ */ +function $QProvider() { + + this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { + return qFactory(function(callback) { + $rootScope.$evalAsync(callback); + }, $exceptionHandler); + }]; +} + + +/** + * Constructs a promise manager. + * + * @param {function(function)} nextTick Function for executing functions in the next turn. + * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for + * debugging purposes. + * @returns {object} Promise manager. + */ +function qFactory(nextTick, exceptionHandler) { + + /** + * @ngdoc + * @name ng.$q#defer + * @methodOf ng.$q + * @description + * Creates a `Deferred` object which represents a task which will finish in the future. + * + * @returns {Deferred} Returns a new instance of deferred. + */ + var defer = function() { + var pending = [], + value, deferred; + + deferred = { + + resolve: function(val) { + if (pending) { + var callbacks = pending; + pending = undefined; + value = ref(val); + + if (callbacks.length) { + nextTick(function() { + var callback; + for (var i = 0, ii = callbacks.length; i < ii; i++) { + callback = callbacks[i]; + value.then(callback[0], callback[1], callback[2]); + } + }); + } + } + }, + + + reject: function(reason) { + deferred.resolve(reject(reason)); + }, + + + notify: function(progress) { + if (pending) { + var callbacks = pending; + + if (pending.length) { + nextTick(function() { + var callback; + for (var i = 0, ii = callbacks.length; i < ii; i++) { + callback = callbacks[i]; + callback[2](progress); + } + }); + } + } + }, + + + promise: { + then: function(callback, errback, progressback) { + var result = defer(); + + var wrappedCallback = function(value) { + try { + result.resolve((isFunction(callback) ? callback : defaultCallback)(value)); + } catch(e) { + result.reject(e); + exceptionHandler(e); + } + }; + + var wrappedErrback = function(reason) { + try { + result.resolve((isFunction(errback) ? errback : defaultErrback)(reason)); + } catch(e) { + result.reject(e); + exceptionHandler(e); + } + }; + + var wrappedProgressback = function(progress) { + try { + result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress)); + } catch(e) { + exceptionHandler(e); + } + }; + + if (pending) { + pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]); + } else { + value.then(wrappedCallback, wrappedErrback, wrappedProgressback); + } + + return result.promise; + }, + + "catch": function(callback) { + return this.then(null, callback); + }, + + "finally": function(callback) { + + function makePromise(value, resolved) { + var result = defer(); + if (resolved) { + result.resolve(value); + } else { + result.reject(value); + } + return result.promise; + } + + function handleCallback(value, isResolved) { + var callbackOutput = null; + try { + callbackOutput = (callback ||defaultCallback)(); + } catch(e) { + return makePromise(e, false); + } + if (callbackOutput && isFunction(callbackOutput.then)) { + return callbackOutput.then(function() { + return makePromise(value, isResolved); + }, function(error) { + return makePromise(error, false); + }); + } else { + return makePromise(value, isResolved); + } + } + + return this.then(function(value) { + return handleCallback(value, true); + }, function(error) { + return handleCallback(error, false); + }); + } + } + }; + + return deferred; + }; + + + var ref = function(value) { + if (value && isFunction(value.then)) return value; + return { + then: function(callback) { + var result = defer(); + nextTick(function() { + result.resolve(callback(value)); + }); + return result.promise; + } + }; + }; + + + /** + * @ngdoc + * @name ng.$q#reject + * @methodOf ng.$q + * @description + * Creates a promise that is resolved as rejected with the specified `reason`. This api should be + * used to forward rejection in a chain of promises. If you are dealing with the last promise in + * a promise chain, you don't need to worry about it. + * + * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of + * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via + * a promise error callback and you want to forward the error to the promise derived from the + * current promise, you have to "rethrow" the error by returning a rejection constructed via + * `reject`. + * + *
+   *   promiseB = promiseA.then(function(result) {
+   *     // success: do something and resolve promiseB
+   *     //          with the old or a new result
+   *     return result;
+   *   }, function(reason) {
+   *     // error: handle the error if possible and
+   *     //        resolve promiseB with newPromiseOrValue,
+   *     //        otherwise forward the rejection to promiseB
+   *     if (canHandle(reason)) {
+   *      // handle the error and recover
+   *      return newPromiseOrValue;
+   *     }
+   *     return $q.reject(reason);
+   *   });
+   * 
+ * + * @param {*} reason Constant, message, exception or an object representing the rejection reason. + * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. + */ + var reject = function(reason) { + return { + then: function(callback, errback) { + var result = defer(); + nextTick(function() { + try { + result.resolve((isFunction(errback) ? errback : defaultErrback)(reason)); + } catch(e) { + result.reject(e); + exceptionHandler(e); + } + }); + return result.promise; + } + }; + }; + + + /** + * @ngdoc + * @name ng.$q#when + * @methodOf ng.$q + * @description + * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. + * This is useful when you are dealing with an object that might or might not be a promise, or if + * the promise comes from a source that can't be trusted. + * + * @param {*} value Value or a promise + * @returns {Promise} Returns a promise of the passed value or promise + */ + var when = function(value, callback, errback, progressback) { + var result = defer(), + done; + + var wrappedCallback = function(value) { + try { + return (isFunction(callback) ? callback : defaultCallback)(value); + } catch (e) { + exceptionHandler(e); + return reject(e); + } + }; + + var wrappedErrback = function(reason) { + try { + return (isFunction(errback) ? errback : defaultErrback)(reason); + } catch (e) { + exceptionHandler(e); + return reject(e); + } + }; + + var wrappedProgressback = function(progress) { + try { + return (isFunction(progressback) ? progressback : defaultCallback)(progress); + } catch (e) { + exceptionHandler(e); + } + }; + + nextTick(function() { + ref(value).then(function(value) { + if (done) return; + done = true; + result.resolve(ref(value).then(wrappedCallback, wrappedErrback, wrappedProgressback)); + }, function(reason) { + if (done) return; + done = true; + result.resolve(wrappedErrback(reason)); + }, function(progress) { + if (done) return; + result.notify(wrappedProgressback(progress)); + }); + }); + + return result.promise; + }; + + + function defaultCallback(value) { + return value; + } + + + function defaultErrback(reason) { + return reject(reason); + } + + + /** + * @ngdoc + * @name ng.$q#all + * @methodOf ng.$q + * @description + * Combines multiple promises into a single promise that is resolved when all of the input + * promises are resolved. + * + * @param {Array.|Object.} promises An array or hash of promises. + * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, + * each value corresponding to the promise at the same index/key in the `promises` array/hash. + * If any of the promises is resolved with a rejection, this resulting promise will be rejected + * with the same rejection value. + */ + function all(promises) { + var deferred = defer(), + counter = 0, + results = isArray(promises) ? [] : {}; + + forEach(promises, function(promise, key) { + counter++; + ref(promise).then(function(value) { + if (results.hasOwnProperty(key)) return; + results[key] = value; + if (!(--counter)) deferred.resolve(results); + }, function(reason) { + if (results.hasOwnProperty(key)) return; + deferred.reject(reason); + }); + }); + + if (counter === 0) { + deferred.resolve(results); + } + + return deferred.promise; + } + + return { + defer: defer, + reject: reject, + when: when, + all: all + }; +} + +/** + * DESIGN NOTES + * + * The design decisions behind the scope are heavily favored for speed and memory consumption. + * + * The typical use of scope is to watch the expressions, which most of the time return the same + * value as last time so we optimize the operation. + * + * Closures construction is expensive in terms of speed as well as memory: + * - No closures, instead use prototypical inheritance for API + * - Internal state needs to be stored on scope directly, which means that private state is + * exposed as $$____ properties + * + * Loop operations are optimized by using while(count--) { ... } + * - this means that in order to keep the same order of execution as addition we have to add + * items to the array at the beginning (shift) instead of at the end (push) + * + * Child scopes are created and removed often + * - Using an array would be slow since inserts in middle are expensive so we use linked list + * + * There are few watches then a lot of observers. This is why you don't want the observer to be + * implemented in the same way as watch. Watch requires return of initialization function which + * are expensive to construct. + */ + + +/** + * @ngdoc object + * @name ng.$rootScopeProvider + * @description + * + * Provider for the $rootScope service. + */ + +/** + * @ngdoc function + * @name ng.$rootScopeProvider#digestTtl + * @methodOf ng.$rootScopeProvider + * @description + * + * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and + * assuming that the model is unstable. + * + * The current default is 10 iterations. + * + * In complex applications it's possible that the dependencies between `$watch`s will result in + * several digest iterations. However if an application needs more than the default 10 digest + * iterations for its model to stabilize then you should investigate what is causing the model to + * continuously change during the digest. + * + * Increasing the TTL could have performance implications, so you should not change it without + * proper justification. + * + * @param {number} limit The number of digest iterations. + */ + + +/** + * @ngdoc object + * @name ng.$rootScope + * @description + * + * Every application has a single root {@link ng.$rootScope.Scope scope}. + * All other scopes are descendant scopes of the root scope. Scopes provide separation + * between the model and the view, via a mechanism for watching the model for changes. + * They also provide an event emission/broadcast and subscription facility. See the + * {@link guide/scope developer guide on scopes}. + */ +function $RootScopeProvider(){ + var TTL = 10; + var $rootScopeMinErr = minErr('$rootScope'); + + this.digestTtl = function(value) { + if (arguments.length) { + TTL = value; + } + return TTL; + }; + + this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', + function( $injector, $exceptionHandler, $parse, $browser) { + + /** + * @ngdoc function + * @name ng.$rootScope.Scope + * + * @description + * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the + * {@link AUTO.$injector $injector}. Child scopes are created using the + * {@link ng.$rootScope.Scope#methods_$new $new()} method. (Most scopes are created automatically when + * compiled HTML template is executed.) + * + * Here is a simple scope snippet to show how you can interact with the scope. + *
+     * 
+     * 
+ * + * # Inheritance + * A scope can inherit from a parent scope, as in this example: + *
+         var parent = $rootScope;
+         var child = parent.$new();
+
+         parent.salutation = "Hello";
+         child.name = "World";
+         expect(child.salutation).toEqual('Hello');
+
+         child.salutation = "Welcome";
+         expect(child.salutation).toEqual('Welcome');
+         expect(parent.salutation).toEqual('Hello');
+     * 
+ * + * + * @param {Object.=} providers Map of service factory which need to be + * provided for the current scope. Defaults to {@link ng}. + * @param {Object.=} instanceCache Provides pre-instantiated services which should + * append/override services provided by `providers`. This is handy + * when unit-testing and having the need to override a default + * service. + * @returns {Object} Newly created scope. + * + */ + function Scope() { + this.$id = nextUid(); + this.$$phase = this.$parent = this.$$watchers = + this.$$nextSibling = this.$$prevSibling = + this.$$childHead = this.$$childTail = null; + this['this'] = this.$root = this; + this.$$destroyed = false; + this.$$asyncQueue = []; + this.$$postDigestQueue = []; + this.$$listeners = {}; + this.$$isolateBindings = {}; + } + + /** + * @ngdoc property + * @name ng.$rootScope.Scope#$id + * @propertyOf ng.$rootScope.Scope + * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for + * debugging. + */ + + + Scope.prototype = { + constructor: Scope, + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$new + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Creates a new child {@link ng.$rootScope.Scope scope}. + * + * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and + * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the + * scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. + * + * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is + * desired for the scope and its child scopes to be permanently detached from the parent and + * thus stop participating in model change detection and listener notification by invoking. + * + * @param {boolean} isolate If true, then the scope does not prototypically inherit from the + * parent scope. The scope is isolated, as it can not see parent scope properties. + * When creating widgets, it is useful for the widget to not accidentally read parent + * state. + * + * @returns {Object} The newly created child scope. + * + */ + $new: function(isolate) { + var Child, + child; + + if (isolate) { + child = new Scope(); + child.$root = this.$root; + // ensure that there is just one async queue per $rootScope and its children + child.$$asyncQueue = this.$$asyncQueue; + child.$$postDigestQueue = this.$$postDigestQueue; + } else { + Child = function() {}; // should be anonymous; This is so that when the minifier munges + // the name it does not become random set of chars. This will then show up as class + // name in the debugger. + Child.prototype = this; + child = new Child(); + child.$id = nextUid(); + } + child['this'] = child; + child.$$listeners = {}; + child.$parent = this; + child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null; + child.$$prevSibling = this.$$childTail; + if (this.$$childHead) { + this.$$childTail.$$nextSibling = child; + this.$$childTail = child; + } else { + this.$$childHead = this.$$childTail = child; + } + return child; + }, + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$watch + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Registers a `listener` callback to be executed whenever the `watchExpression` changes. + * + * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest + * $digest()} and should return the value that will be watched. (Since + * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the + * `watchExpression` can execute multiple times per + * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) + * - The `listener` is called only when the value from the current `watchExpression` and the + * previous call to `watchExpression` are not equal (with the exception of the initial run, + * see below). The inequality is determined according to + * {@link angular.equals} function. To save the value of the object for later comparison, + * the {@link angular.copy} function is used. It also means that watching complex options + * will have adverse memory and performance implications. + * - The watch `listener` may change the model, which may trigger other `listener`s to fire. + * This is achieved by rerunning the watchers until no changes are detected. The rerun + * iteration limit is 10 to prevent an infinite loop deadlock. + * + * + * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, + * you can register a `watchExpression` function with no `listener`. (Since `watchExpression` + * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a + * change is detected, be prepared for multiple calls to your listener.) + * + * After a watcher is registered with the scope, the `listener` fn is called asynchronously + * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the + * watcher. In rare cases, this is undesirable because the listener is called when the result + * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you + * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the + * listener was called due to initialization. + * + * The example below contains an illustration of using a function as your $watch listener + * + * + * # Example + *
+           // let's assume that scope was dependency injected as the $rootScope
+           var scope = $rootScope;
+           scope.name = 'misko';
+           scope.counter = 0;
+
+           expect(scope.counter).toEqual(0);
+           scope.$watch('name', function(newValue, oldValue) {
+             scope.counter = scope.counter + 1;
+           });
+           expect(scope.counter).toEqual(0);
+
+           scope.$digest();
+           // no variable change
+           expect(scope.counter).toEqual(0);
+
+           scope.name = 'adam';
+           scope.$digest();
+           expect(scope.counter).toEqual(1);
+
+
+
+           // Using a listener function
+           var food;
+           scope.foodCounter = 0;
+           expect(scope.foodCounter).toEqual(0);
+           scope.$watch(
+             // This is the listener function
+             function() { return food; },
+             // This is the change handler
+             function(newValue, oldValue) {
+               if ( newValue !== oldValue ) {
+                 // Only increment the counter if the value changed
+                 scope.foodCounter = scope.foodCounter + 1;
+               }
+             }
+           );
+           // No digest has been run so the counter will be zero
+           expect(scope.foodCounter).toEqual(0);
+
+           // Run the digest but since food has not changed cout will still be zero
+           scope.$digest();
+           expect(scope.foodCounter).toEqual(0);
+
+           // Update food and run digest.  Now the counter will increment
+           food = 'cheeseburger';
+           scope.$digest();
+           expect(scope.foodCounter).toEqual(1);
+
+       * 
+ * + * + * + * @param {(function()|string)} watchExpression Expression that is evaluated on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers + * a call to the `listener`. + * + * - `string`: Evaluated as {@link guide/expression expression} + * - `function(scope)`: called with current `scope` as a parameter. + * @param {(function()|string)=} listener Callback called whenever the return value of + * the `watchExpression` changes. + * + * - `string`: Evaluated as {@link guide/expression expression} + * - `function(newValue, oldValue, scope)`: called with current and previous values as + * parameters. + * + * @param {boolean=} objectEquality Compare object for equality rather than for reference. + * @returns {function()} Returns a deregistration function for this listener. + */ + $watch: function(watchExp, listener, objectEquality) { + var scope = this, + get = compileToFn(watchExp, 'watch'), + array = scope.$$watchers, + watcher = { + fn: listener, + last: initWatchVal, + get: get, + exp: watchExp, + eq: !!objectEquality + }; + + // in the case user pass string, we need to compile it, do we really need this ? + if (!isFunction(listener)) { + var listenFn = compileToFn(listener || noop, 'listener'); + watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);}; + } + + if (typeof watchExp == 'string' && get.constant) { + var originalFn = watcher.fn; + watcher.fn = function(newVal, oldVal, scope) { + originalFn.call(this, newVal, oldVal, scope); + arrayRemove(array, watcher); + }; + } + + if (!array) { + array = scope.$$watchers = []; + } + // we use unshift since we use a while loop in $digest for speed. + // the while loop reads in reverse order. + array.unshift(watcher); + + return function() { + arrayRemove(array, watcher); + }; + }, + + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$watchCollection + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Shallow watches the properties of an object and fires whenever any of the properties change + * (for arrays, this implies watching the array items; for object maps, this implies watching + * the properties). If a change is detected, the `listener` callback is fired. + * + * - The `obj` collection is observed via standard $watch operation and is examined on every + * call to $digest() to see if any items have been added, removed, or moved. + * - The `listener` is called whenever anything within the `obj` has changed. Examples include + * adding, removing, and moving items belonging to an object or array. + * + * + * # Example + *
+          $scope.names = ['igor', 'matias', 'misko', 'james'];
+          $scope.dataCount = 4;
+
+          $scope.$watchCollection('names', function(newNames, oldNames) {
+            $scope.dataCount = newNames.length;
+          });
+
+          expect($scope.dataCount).toEqual(4);
+          $scope.$digest();
+
+          //still at 4 ... no changes
+          expect($scope.dataCount).toEqual(4);
+
+          $scope.names.pop();
+          $scope.$digest();
+
+          //now there's been a change
+          expect($scope.dataCount).toEqual(3);
+       * 
+ * + * + * @param {string|Function(scope)} obj Evaluated as {@link guide/expression expression}. The + * expression value should evaluate to an object or an array which is observed on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the + * collection will trigger a call to the `listener`. + * + * @param {function(newCollection, oldCollection, scope)} listener a callback function that is + * fired with both the `newCollection` and `oldCollection` as parameters. + * The `newCollection` object is the newly modified data obtained from the `obj` expression + * and the `oldCollection` object is a copy of the former collection data. + * The `scope` refers to the current scope. + * + * @returns {function()} Returns a de-registration function for this listener. When the + * de-registration function is executed, the internal watch operation is terminated. + */ + $watchCollection: function(obj, listener) { + var self = this; + var oldValue; + var newValue; + var changeDetected = 0; + var objGetter = $parse(obj); + var internalArray = []; + var internalObject = {}; + var oldLength = 0; + + function $watchCollectionWatch() { + newValue = objGetter(self); + var newLength, key; + + if (!isObject(newValue)) { + if (oldValue !== newValue) { + oldValue = newValue; + changeDetected++; + } + } else if (isArrayLike(newValue)) { + if (oldValue !== internalArray) { + // we are transitioning from something which was not an array into array. + oldValue = internalArray; + oldLength = oldValue.length = 0; + changeDetected++; + } + + newLength = newValue.length; + + if (oldLength !== newLength) { + // if lengths do not match we need to trigger change notification + changeDetected++; + oldValue.length = oldLength = newLength; + } + // copy the items to oldValue and look for changes. + for (var i = 0; i < newLength; i++) { + if (oldValue[i] !== newValue[i]) { + changeDetected++; + oldValue[i] = newValue[i]; + } + } + } else { + if (oldValue !== internalObject) { + // we are transitioning from something which was not an object into object. + oldValue = internalObject = {}; + oldLength = 0; + changeDetected++; + } + // copy the items to oldValue and look for changes. + newLength = 0; + for (key in newValue) { + if (newValue.hasOwnProperty(key)) { + newLength++; + if (oldValue.hasOwnProperty(key)) { + if (oldValue[key] !== newValue[key]) { + changeDetected++; + oldValue[key] = newValue[key]; + } + } else { + oldLength++; + oldValue[key] = newValue[key]; + changeDetected++; + } + } + } + if (oldLength > newLength) { + // we used to have more keys, need to find them and destroy them. + changeDetected++; + for(key in oldValue) { + if (oldValue.hasOwnProperty(key) && !newValue.hasOwnProperty(key)) { + oldLength--; + delete oldValue[key]; + } + } + } + } + return changeDetected; + } + + function $watchCollectionAction() { + listener(newValue, oldValue, self); + } + + return this.$watch($watchCollectionWatch, $watchCollectionAction); + }, + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$digest + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and + * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change + * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} + * until no more listeners are firing. This means that it is possible to get into an infinite + * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of + * iterations exceeds 10. + * + * Usually, you don't call `$digest()` directly in + * {@link ng.directive:ngController controllers} or in + * {@link ng.$compileProvider#methods_directive directives}. + * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within + * a {@link ng.$compileProvider#methods_directive directives}), which will force a `$digest()`. + * + * If you want to be notified whenever `$digest()` is called, + * you can register a `watchExpression` function with + * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`. + * + * In unit tests, you may need to call `$digest()` to simulate the scope life cycle. + * + * # Example + *
+           var scope = ...;
+           scope.name = 'misko';
+           scope.counter = 0;
+
+           expect(scope.counter).toEqual(0);
+           scope.$watch('name', function(newValue, oldValue) {
+             scope.counter = scope.counter + 1;
+           });
+           expect(scope.counter).toEqual(0);
+
+           scope.$digest();
+           // no variable change
+           expect(scope.counter).toEqual(0);
+
+           scope.name = 'adam';
+           scope.$digest();
+           expect(scope.counter).toEqual(1);
+       * 
+ * + */ + $digest: function() { + var watch, value, last, + watchers, + asyncQueue = this.$$asyncQueue, + postDigestQueue = this.$$postDigestQueue, + length, + dirty, ttl = TTL, + next, current, target = this, + watchLog = [], + logIdx, logMsg, asyncTask; + + beginPhase('$digest'); + + do { // "while dirty" loop + dirty = false; + current = target; + + while(asyncQueue.length) { + try { + asyncTask = asyncQueue.shift(); + asyncTask.scope.$eval(asyncTask.expression); + } catch (e) { + $exceptionHandler(e); + } + } + + do { // "traverse the scopes" loop + if ((watchers = current.$$watchers)) { + // process our watches + length = watchers.length; + while (length--) { + try { + watch = watchers[length]; + // Most common watches are on primitives, in which case we can short + // circuit it with === operator, only when === fails do we use .equals + if (watch && (value = watch.get(current)) !== (last = watch.last) && + !(watch.eq + ? equals(value, last) + : (typeof value == 'number' && typeof last == 'number' + && isNaN(value) && isNaN(last)))) { + dirty = true; + watch.last = watch.eq ? copy(value) : value; + watch.fn(value, ((last === initWatchVal) ? value : last), current); + if (ttl < 5) { + logIdx = 4 - ttl; + if (!watchLog[logIdx]) watchLog[logIdx] = []; + logMsg = (isFunction(watch.exp)) + ? 'fn: ' + (watch.exp.name || watch.exp.toString()) + : watch.exp; + logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last); + watchLog[logIdx].push(logMsg); + } + } + } catch (e) { + $exceptionHandler(e); + } + } + } + + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $broadcast + if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) { + while(current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } while ((current = next)); + + if(dirty && !(ttl--)) { + clearPhase(); + throw $rootScopeMinErr('infdig', + '{0} $digest() iterations reached. Aborting!\n' + + 'Watchers fired in the last 5 iterations: {1}', + TTL, toJson(watchLog)); + } + } while (dirty || asyncQueue.length); + + clearPhase(); + + while(postDigestQueue.length) { + try { + postDigestQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } + } + }, + + + /** + * @ngdoc event + * @name ng.$rootScope.Scope#$destroy + * @eventOf ng.$rootScope.Scope + * @eventType broadcast on scope being destroyed + * + * @description + * Broadcasted when a scope and its children are being destroyed. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$destroy + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Removes the current scope (and all of its children) from the parent scope. Removal implies + * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer + * propagate to the current scope and its children. Removal also implies that the current + * scope is eligible for garbage collection. + * + * The `$destroy()` is usually used by directives such as + * {@link ng.directive:ngRepeat ngRepeat} for managing the + * unrolling of the loop. + * + * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. + * Application code can register a `$destroy` event handler that will give it a chance to + * perform any necessary cleanup. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + $destroy: function() { + // we can't destroy the root scope or a scope that has been already destroyed + if ($rootScope == this || this.$$destroyed) return; + var parent = this.$parent; + + this.$broadcast('$destroy'); + this.$$destroyed = true; + + if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; + if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; + + // This is bogus code that works around Chrome's GC leak + // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 + this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = + this.$$childTail = null; + }, + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$eval + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Executes the `expression` on the current scope and returns the result. Any exceptions in + * the expression are propagated (uncaught). This is useful when evaluating Angular + * expressions. + * + * # Example + *
+           var scope = ng.$rootScope.Scope();
+           scope.a = 1;
+           scope.b = 2;
+
+           expect(scope.$eval('a+b')).toEqual(3);
+           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
+       * 
+ * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + * @returns {*} The result of evaluating the expression. + */ + $eval: function(expr, locals) { + return $parse(expr)(this, locals); + }, + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$evalAsync + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Executes the expression on the current scope at a later point in time. + * + * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only + * that: + * + * - it will execute after the function that scheduled the evaluation (preferably before DOM + * rendering). + * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after + * `expression` execution. + * + * Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle + * will be scheduled. However, it is encouraged to always call code that changes the model + * from within an `$apply` call. That includes code evaluated via `$evalAsync`. + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + */ + $evalAsync: function(expr) { + // if we are outside of an $digest loop and this is the first time we are scheduling async + // task also schedule async auto-flush + if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) { + $browser.defer(function() { + if ($rootScope.$$asyncQueue.length) { + $rootScope.$digest(); + } + }); + } + + this.$$asyncQueue.push({scope: this, expression: expr}); + }, + + $$postDigest : function(fn) { + this.$$postDigestQueue.push(fn); + }, + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$apply + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * `$apply()` is used to execute an expression in angular from outside of the angular + * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). + * Because we are calling into the angular framework we need to perform proper scope life + * cycle of {@link ng.$exceptionHandler exception handling}, + * {@link ng.$rootScope.Scope#$digest executing watches}. + * + * ## Life cycle + * + * # Pseudo-Code of `$apply()` + *
+           function $apply(expr) {
+             try {
+               return $eval(expr);
+             } catch (e) {
+               $exceptionHandler(e);
+             } finally {
+               $root.$digest();
+             }
+           }
+       * 
+ * + * + * Scope's `$apply()` method transitions through the following stages: + * + * 1. The {@link guide/expression expression} is executed using the + * {@link ng.$rootScope.Scope#$eval $eval()} method. + * 2. Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the + * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. + * + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + * + * @returns {*} The result of evaluating the expression. + */ + $apply: function(expr) { + try { + beginPhase('$apply'); + return this.$eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + clearPhase(); + try { + $rootScope.$digest(); + } catch (e) { + $exceptionHandler(e); + throw e; + } + } + }, + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$on + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for + * discussion of event life cycle. + * + * The event listener function format is: `function(event, args...)`. The `event` object + * passed into the listener has the following attributes: + * + * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or + * `$broadcast`-ed. + * - `currentScope` - `{Scope}`: the current scope which is handling the event. + * - `name` - `{string}`: name of the event. + * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel + * further event propagation (available only for events that were `$emit`-ed). + * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag + * to true. + * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. + * + * @param {string} name Event name to listen on. + * @param {function(event, args...)} listener Function to call when the event is emitted. + * @returns {function()} Returns a deregistration function for this listener. + */ + $on: function(name, listener) { + var namedListeners = this.$$listeners[name]; + if (!namedListeners) { + this.$$listeners[name] = namedListeners = []; + } + namedListeners.push(listener); + + return function() { + namedListeners[indexOf(namedListeners, listener)] = null; + }; + }, + + + /** + * @ngdoc function + * @name ng.$rootScope.Scope#$emit + * @methodOf ng.$rootScope.Scope + * @function + * + * @description + * Dispatches an event `name` upwards through the scope hierarchy notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. + * + * The event life cycle starts at the scope on which `$emit` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event traverses upwards toward the root scope and calls all + * registered listeners along the way. The event will stop propagating if one of the listeners + * cancels it. + * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to emit. + * @param {...*} args Optional set of arguments which will be passed onto the event listeners. + * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}). + */ + $emit: function(name, args) { + var empty = [], + namedListeners, + scope = this, + stopPropagation = false, + event = { + name: name, + targetScope: scope, + stopPropagation: function() {stopPropagation = true;}, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }, + listenerArgs = concat([event], arguments, 1), + i, length; + + do { + namedListeners = scope.$$listeners[name] || empty; + event.currentScope = scope; + for (i=0, length=namedListeners.length; i= 8 ) { + normalizedVal = urlResolve(uri).href; + if (normalizedVal !== '' && !normalizedVal.match(regex)) { + return 'unsafe:'+normalizedVal; + } + } + return uri; + }; + }; +} + +var $sceMinErr = minErr('$sce'); + +var SCE_CONTEXTS = { + HTML: 'html', + CSS: 'css', + URL: 'url', + // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a + // url. (e.g. ng-include, script src, templateUrl) + RESOURCE_URL: 'resourceUrl', + JS: 'js' +}; + +// Helper functions follow. + +// Copied from: +// http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962 +// Prereq: s is a string. +function escapeForRegexp(s) { + return s.replace(/([-()\[\]{}+?*.$\^|,:# -1) { + throw $sceMinErr('iwcard', + 'Illegal sequence *** in string matcher. String: {0}', matcher); + } + matcher = escapeForRegexp(matcher). + replace('\\*\\*', '.*'). + replace('\\*', '[^:/.?&;]*'); + return new RegExp('^' + matcher + '$'); + } else if (isRegExp(matcher)) { + // The only other type of matcher allowed is a Regexp. + // Match entire URL / disallow partial matches. + // Flags are reset (i.e. no global, ignoreCase or multiline) + return new RegExp('^' + matcher.source + '$'); + } else { + throw $sceMinErr('imatcher', + 'Matchers may only be "self", string patterns or RegExp objects'); + } +} + + +function adjustMatchers(matchers) { + var adjustedMatchers = []; + if (isDefined(matchers)) { + forEach(matchers, function(matcher) { + adjustedMatchers.push(adjustMatcher(matcher)); + }); + } + return adjustedMatchers; +} + + +/** + * @ngdoc service + * @name ng.$sceDelegate + * @function + * + * @description + * + * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict + * Contextual Escaping (SCE)} services to AngularJS. + * + * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of + * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is + * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to + * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things + * work because `$sce` delegates to `$sceDelegate` for these operations. + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service. + * + * The default instance of `$sceDelegate` should work out of the box with little pain. While you + * can override it completely to change the behavior of `$sce`, the common case would + * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting + * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as + * templates. Refer {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist + * $sceDelegateProvider.resourceUrlWhitelist} and {@link + * ng.$sceDelegateProvider#methods_resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + */ + +/** + * @ngdoc object + * @name ng.$sceDelegateProvider + * @description + * + * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate + * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure + * that the URLs used for sourcing Angular templates are safe. Refer {@link + * ng.$sceDelegateProvider#methods_resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and + * {@link ng.$sceDelegateProvider#methods_resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + * + * For the general details about this service in Angular, read the main page for {@link ng.$sce + * Strict Contextual Escaping (SCE)}. + * + * **Example**: Consider the following case. + * + * - your app is hosted at url `http://myapp.example.com/` + * - but some of your templates are hosted on other domains you control such as + * `http://srv01.assets.example.com/`, `http://srv02.assets.example.com/`, etc. + * - and you have an open redirect at `http://myapp.example.com/clickThru?...`. + * + * Here is what a secure configuration for this scenario might look like: + * + *
+ *    angular.module('myApp', []).config(function($sceDelegateProvider) {
+ *      $sceDelegateProvider.resourceUrlWhitelist([
+ *        // Allow same origin resource loads.
+ *        'self',
+ *        // Allow loading from our assets domain.  Notice the difference between * and **.
+ *        'http://srv*.assets.example.com/**']);
+ *
+ *      // The blacklist overrides the whitelist so the open redirect here is blocked.
+ *      $sceDelegateProvider.resourceUrlBlacklist([
+ *        'http://myapp.example.com/clickThru**']);
+ *      });
+ * 
+ */ + +function $SceDelegateProvider() { + this.SCE_CONTEXTS = SCE_CONTEXTS; + + // Resource URLs can also be trusted by policy. + var resourceUrlWhitelist = ['self'], + resourceUrlBlacklist = []; + + /** + * @ngdoc function + * @name ng.sceDelegateProvider#resourceUrlWhitelist + * @methodOf ng.$sceDelegateProvider + * @function + * + * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * Note: **an empty whitelist array will block all URLs**! + * + * @return {Array} the currently set whitelist array. + * + * The **default value** when no whitelist has been explicitly set is `['self']` allowing only + * same origin resource requests. + * + * @description + * Sets/Gets the whitelist of trusted resource URLs. + */ + this.resourceUrlWhitelist = function (value) { + if (arguments.length) { + resourceUrlWhitelist = adjustMatchers(value); + } + return resourceUrlWhitelist; + }; + + /** + * @ngdoc function + * @name ng.sceDelegateProvider#resourceUrlBlacklist + * @methodOf ng.$sceDelegateProvider + * @function + * + * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * The typical usage for the blacklist is to **block + * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as + * these would otherwise be trusted but actually return content from the redirected domain. + * + * Finally, **the blacklist overrides the whitelist** and has the final say. + * + * @return {Array} the currently set blacklist array. + * + * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there + * is no blacklist.) + * + * @description + * Sets/Gets the blacklist of trusted resource URLs. + */ + + this.resourceUrlBlacklist = function (value) { + if (arguments.length) { + resourceUrlBlacklist = adjustMatchers(value); + } + return resourceUrlBlacklist; + }; + + this.$get = ['$injector', function($injector) { + + var htmlSanitizer = function htmlSanitizer(html) { + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + }; + + if ($injector.has('$sanitize')) { + htmlSanitizer = $injector.get('$sanitize'); + } + + + function matchUrl(matcher, parsedUrl) { + if (matcher === 'self') { + return urlIsSameOrigin(parsedUrl); + } else { + // definitely a regex. See adjustMatchers() + return !!matcher.exec(parsedUrl.href); + } + } + + function isResourceUrlAllowedByPolicy(url) { + var parsedUrl = urlResolve(url.toString()); + var i, n, allowed = false; + // Ensure that at least one item from the whitelist allows this url. + for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { + if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { + allowed = true; + break; + } + } + if (allowed) { + // Ensure that no item from the blacklist blocked this url. + for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { + if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { + allowed = false; + break; + } + } + } + return allowed; + } + + function generateHolderType(Base) { + var holderType = function TrustedValueHolderType(trustedValue) { + this.$$unwrapTrustedValue = function() { + return trustedValue; + }; + }; + if (Base) { + holderType.prototype = new Base(); + } + holderType.prototype.valueOf = function sceValueOf() { + return this.$$unwrapTrustedValue(); + }; + holderType.prototype.toString = function sceToString() { + return this.$$unwrapTrustedValue().toString(); + }; + return holderType; + } + + var trustedValueHolderBase = generateHolderType(), + byType = {}; + + byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); + + /** + * @ngdoc method + * @name ng.$sceDelegate#trustAs + * @methodOf ng.$sceDelegate + * + * @description + * Returns an object that is trusted by angular for use in specified strict + * contextual escaping contexts (such as ng-html-bind-unsafe, ng-include, any src + * attribute interpolation, any dom event binding attribute interpolation + * such as for onclick, etc.) that uses the provided value. + * See {@link ng.$sce $sce} for enabling strict contextual escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resourceUrl, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + function trustAs(type, trustedValue) { + var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (!Constructor) { + throw $sceMinErr('icontext', + 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', + type, trustedValue); + } + if (trustedValue === null || trustedValue === undefined || trustedValue === '') { + return trustedValue; + } + // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting + // mutable objects, we ensure here that the value passed in is actually a string. + if (typeof trustedValue !== 'string') { + throw $sceMinErr('itype', + 'Attempted to trust a non-string value in a content requiring a string: Context: {0}', + type); + } + return new Constructor(trustedValue); + } + + /** + * @ngdoc method + * @name ng.$sceDelegate#valueOf + * @methodOf ng.$sceDelegate + * + * @description + * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#methods_trustAs + * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link + * ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}. + * + * If the passed parameter is not a value that had been returned by {@link + * ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}, returns it as-is. + * + * @param {*} value The result of a prior {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`} + * call or anything else. + * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs + * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns + * `value` unchanged. + */ + function valueOf(maybeTrusted) { + if (maybeTrusted instanceof trustedValueHolderBase) { + return maybeTrusted.$$unwrapTrustedValue(); + } else { + return maybeTrusted; + } + } + + /** + * @ngdoc method + * @name ng.$sceDelegate#getTrusted + * @methodOf ng.$sceDelegate + * + * @description + * Takes the result of a {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`} call and + * returns the originally supplied value if the queried context type is a supertype of the + * created type. If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#methods_trustAs + * `$sceDelegate.trustAs`} call. + * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs + * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception. + */ + function getTrusted(type, maybeTrusted) { + if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') { + return maybeTrusted; + } + var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (constructor && maybeTrusted instanceof constructor) { + return maybeTrusted.$$unwrapTrustedValue(); + } + // If we get here, then we may only take one of two actions. + // 1. sanitize the value for the requested type, or + // 2. throw an exception. + if (type === SCE_CONTEXTS.RESOURCE_URL) { + if (isResourceUrlAllowedByPolicy(maybeTrusted)) { + return maybeTrusted; + } else { + throw $sceMinErr('insecurl', + 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', + maybeTrusted.toString()); + } + } else if (type === SCE_CONTEXTS.HTML) { + return htmlSanitizer(maybeTrusted); + } + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + } + + return { trustAs: trustAs, + getTrusted: getTrusted, + valueOf: valueOf }; + }]; +} + + +/** + * @ngdoc object + * @name ng.$sceProvider + * @description + * + * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service. + * - enable/disable Strict Contextual Escaping (SCE) in a module + * - override the default implementation with a custom delegate + * + * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}. + */ + +/* jshint maxlen: false*/ + +/** + * @ngdoc service + * @name ng.$sce + * @function + * + * @description + * + * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS. + * + * # Strict Contextual Escaping + * + * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain + * contexts to result in a value that is marked as safe to use for that context. One example of + * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer + * to these contexts as privileged or SCE contexts. + * + * As of version 1.2, Angular ships with SCE enabled by default. + * + * Note: When enabled (the default), IE8 in quirks mode is not supported. In this mode, IE8 allows + * one to execute arbitrary javascript by the use of the expression() syntax. Refer + * to learn more about them. + * You can ensure your document is in standards mode and not quirks mode by adding `` + * to the top of your HTML document. + * + * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for + * security vulnerabilities such as XSS, clickjacking, etc. a lot easier. + * + * Here's an example of a binding in a privileged context: + * + *
+ *     
+ *     
+ *
+ * + * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE + * disabled, this application allows the user to render arbitrary HTML into the DIV. + * In a more realistic example, one may be rendering user comments, blog articles, etc. via + * bindings. (HTML is just one example of a context where rendering user controlled input creates + * security vulnerabilities.) + * + * For the case of HTML, you might use a library, either on the client side, or on the server side, + * to sanitize unsafe HTML before binding to the value and rendering it in the document. + * + * How would you ensure that every place that used these types of bindings was bound to a value that + * was sanitized by your library (or returned as safe for rendering by your server?) How can you + * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some + * properties/fields and forgot to update the binding to the sanitized value? + * + * To be secure by default, you want to ensure that any such bindings are disallowed unless you can + * determine that something explicitly says it's safe to use a value for binding in that + * context. You can then audit your code (a simple grep would do) to ensure that this is only done + * for those values that you can easily tell are safe - because they were received from your server, + * sanitized by your library, etc. You can organize your codebase to help with this - perhaps + * allowing only the files in a specific directory to do this. Ensuring that the internal API + * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task. + * + * In the case of AngularJS' SCE service, one uses {@link ng.$sce#methods_trustAs $sce.trustAs} + * (and shorthand methods such as {@link ng.$sce#methods_trustAsHtml $sce.trustAsHtml}, etc.) to + * obtain values that will be accepted by SCE / privileged contexts. + * + * + * ## How does it work? + * + * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#methods_getTrusted + * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link + * ng.$sce#methods_parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the + * {@link ng.$sce#methods_getTrusted $sce.getTrusted} behind the scenes on non-constant literals. + * + * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link + * ng.$sce#methods_parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly + * simplified): + * + *
+ *   var ngBindHtmlDirective = ['$sce', function($sce) {
+ *     return function(scope, element, attr) {
+ *       scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
+ *         element.html(value || '');
+ *       });
+ *     };
+ *   }];
+ * 
+ * + * ## Impact on loading templates + * + * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as + * `templateUrl`'s specified by {@link guide/directive directives}. + * + * By default, Angular only loads templates from the same domain and protocol as the application + * document. This is done by calling {@link ng.$sce#methods_getTrustedResourceUrl + * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or + * protocols, you may either either {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelist + * them} or {@link ng.$sce#methods_trustAsResourceUrl wrap it} into a trusted value. + * + * *Please note*: + * The browser's + * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest + * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing (CORS)} + * policy apply in addition to this and may further restrict whether the template is successfully + * loaded. This means that without the right CORS policy, loading templates from a different domain + * won't work on all browsers. Also, loading templates from `file://` URL does not work on some + * browsers. + * + * ## This feels like too much overhead for the developer? + * + * It's important to remember that SCE only applies to interpolation expressions. + * + * If your expressions are constant literals, they're automatically trusted and you don't need to + * call `$sce.trustAs` on them. (e.g. + * `
`) just works. + * + * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them + * through {@link ng.$sce#methods_getTrusted $sce.getTrusted}. SCE doesn't play a role here. + * + * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load + * templates in `ng-include` from your application's domain without having to even know about SCE. + * It blocks loading templates from other domains or loading templates over http from an https + * served document. You can change these by setting your own custom {@link + * ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelists} and {@link + * ng.$sceDelegateProvider#methods_resourceUrlBlacklist blacklists} for matching such URLs. + * + * This significantly reduces the overhead. It is far easier to pay the small overhead and have an + * application that's secure and can be audited to verify that with much more ease than bolting + * security onto an application later. + * + * + * ## What trusted context types are supported? + * + * | Context | Notes | + * |---------------------|----------------| + * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. | + * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. | + * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`
Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. | + * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. | + * + * ## Format of items in {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#methods_resourceUrlBlacklist Blacklist}
+ * + * Each element in these arrays must be one of the following: + * + * - **'self'** + * - The special **string**, `'self'`, can be used to match against all URLs of the **same + * domain** as the application document using the **same protocol**. + * - **String** (except the special value `'self'`) + * - The string is matched against the full *normalized / absolute URL* of the resource + * being tested (substring matches are not good enough.) + * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters + * match themselves. + * - `*`: matches zero or more occurances of any character other than one of the following 6 + * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use + * in a whitelist. + * - `**`: matches zero or more occurances of *any* character. As such, it's not + * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g. + * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might + * not have been the intention.) It's usage at the very end of the path is ok. (e.g. + * http://foo.example.com/templates/**). + * - **RegExp** (*see caveat below*) + * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax + * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to + * accidentally introduce a bug when one updates a complex expression (imho, all regexes should + * have good test coverage.). For instance, the use of `.` in the regex is correct only in a + * small number of cases. A `.` character in the regex used when matching the scheme or a + * subdomain could be matched against a `:` or literal `.` that was likely not intended. It + * is highly recommended to use the string patterns and only fall back to regular expressions + * if they as a last resort. + * - The regular expression must be an instance of RegExp (i.e. not a string.) It is + * matched against the **entire** *normalized / absolute URL* of the resource being tested + * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags + * present on the RegExp (such as multiline, global, ignoreCase) are ignored. + * - If you are generating your Javascript from some other templating engine (not + * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)), + * remember to escape your regular expression (and be aware that you might need more than + * one level of escaping depending on your templating engine and the way you interpolated + * the value.) Do make use of your platform's escaping mechanism as it might be good + * enough before coding your own. e.g. Ruby has + * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape) + * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape). + * Javascript lacks a similar built in function for escaping. Take a look at Google + * Closure library's [goog.string.regExpEscape(s)]( + * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962). + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example. + * + * ## Show me an example using SCE. + * + * @example + + +
+

+ User comments
+ By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when + $sanitize is available. If $sanitize isn't available, this results in an error instead of an + exploit. +
+
+ {{userComment.name}}: + +
+
+
+
+
+ + + var mySceApp = angular.module('mySceApp', ['ngSanitize']); + + mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) { + var self = this; + $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) { + self.userComments = userComments; + }); + self.explicitlyTrustedHtml = $sce.trustAsHtml( + 'Hover over this text.'); + }); + + + +[ + { "name": "Alice", + "htmlComment": + "Is anyone reading this?" + }, + { "name": "Bob", + "htmlComment": "Yes! Am I the only other one?" + } +] + + + + describe('SCE doc demo', function() { + it('should sanitize untrusted values', function() { + expect(element('.htmlComment').html()).toBe('Is anyone reading this?'); + }); + it('should NOT sanitize explicitly trusted values', function() { + expect(element('#explicitlyTrustedHtml').html()).toBe( + 'Hover over this text.'); + }); + }); + +
+ * + * + * + * ## Can I disable SCE completely? + * + * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits + * for little coding overhead. It will be much harder to take an SCE disabled application and + * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE + * for cases where you have a lot of existing code that was written before SCE was introduced and + * you're migrating them a module at a time. + * + * That said, here's how you can completely disable SCE: + * + *
+ *   angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
+ *     // Completely disable SCE.  For demonstration purposes only!
+ *     // Do not use in new projects.
+ *     $sceProvider.enabled(false);
+ *   });
+ * 
+ * + */ +/* jshint maxlen: 100 */ + +function $SceProvider() { + var enabled = true; + + /** + * @ngdoc function + * @name ng.sceProvider#enabled + * @methodOf ng.$sceProvider + * @function + * + * @param {boolean=} value If provided, then enables/disables SCE. + * @return {boolean} true if SCE is enabled, false otherwise. + * + * @description + * Enables/disables SCE and returns the current value. + */ + this.enabled = function (value) { + if (arguments.length) { + enabled = !!value; + } + return enabled; + }; + + + /* Design notes on the default implementation for SCE. + * + * The API contract for the SCE delegate + * ------------------------------------- + * The SCE delegate object must provide the following 3 methods: + * + * - trustAs(contextEnum, value) + * This method is used to tell the SCE service that the provided value is OK to use in the + * contexts specified by contextEnum. It must return an object that will be accepted by + * getTrusted() for a compatible contextEnum and return this value. + * + * - valueOf(value) + * For values that were not produced by trustAs(), return them as is. For values that were + * produced by trustAs(), return the corresponding input value to trustAs. Basically, if + * trustAs is wrapping the given values into some type, this operation unwraps it when given + * such a value. + * + * - getTrusted(contextEnum, value) + * This function should return the a value that is safe to use in the context specified by + * contextEnum or throw and exception otherwise. + * + * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be + * opaque or wrapped in some holder object. That happens to be an implementation detail. For + * instance, an implementation could maintain a registry of all trusted objects by context. In + * such a case, trustAs() would return the same object that was passed in. getTrusted() would + * return the same object passed in if it was found in the registry under a compatible context or + * throw an exception otherwise. An implementation might only wrap values some of the time based + * on some criteria. getTrusted() might return a value and not throw an exception for special + * constants or objects even if not wrapped. All such implementations fulfill this contract. + * + * + * A note on the inheritance model for SCE contexts + * ------------------------------------------------ + * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This + * is purely an implementation details. + * + * The contract is simply this: + * + * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value) + * will also succeed. + * + * Inheritance happens to capture this in a natural way. In some future, we + * may not use inheritance anymore. That is OK because no code outside of + * sce.js and sceSpecs.js would need to be aware of this detail. + */ + + this.$get = ['$parse', '$sniffer', '$sceDelegate', function( + $parse, $sniffer, $sceDelegate) { + // Prereq: Ensure that we're not running in IE8 quirks mode. In that mode, IE allows + // the "expression(javascript expression)" syntax which is insecure. + if (enabled && $sniffer.msie && $sniffer.msieDocumentMode < 8) { + throw $sceMinErr('iequirks', + 'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' + + 'mode. You can fix this by adding the text to the top of your HTML ' + + 'document. See http://docs.angularjs.org/api/ng.$sce for more information.'); + } + + var sce = copy(SCE_CONTEXTS); + + /** + * @ngdoc function + * @name ng.sce#isEnabled + * @methodOf ng.$sce + * @function + * + * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you + * have to do it at module config time on {@link ng.$sceProvider $sceProvider}. + * + * @description + * Returns a boolean indicating if SCE is enabled. + */ + sce.isEnabled = function () { + return enabled; + }; + sce.trustAs = $sceDelegate.trustAs; + sce.getTrusted = $sceDelegate.getTrusted; + sce.valueOf = $sceDelegate.valueOf; + + if (!enabled) { + sce.trustAs = sce.getTrusted = function(type, value) { return value; }; + sce.valueOf = identity; + } + + /** + * @ngdoc method + * @name ng.$sce#parse + * @methodOf ng.$sce + * + * @description + * Converts Angular {@link guide/expression expression} into a function. This is like {@link + * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it + * wraps the expression in a call to {@link ng.$sce#methods_getTrusted $sce.getTrusted(*type*, + * *result*)} + * + * @param {string} type The kind of SCE context in which this result will be used. + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + sce.parseAs = function sceParseAs(type, expr) { + var parsed = $parse(expr); + if (parsed.literal && parsed.constant) { + return parsed; + } else { + return function sceParseAsTrusted(self, locals) { + return sce.getTrusted(type, parsed(self, locals)); + }; + } + }; + + /** + * @ngdoc method + * @name ng.$sce#trustAs + * @methodOf ng.$sce + * + * @description + * Delegates to {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}. As such, + * returns an objectthat is trusted by angular for use in specified strict contextual + * escaping contexts (such as ng-html-bind-unsafe, ng-include, any src attribute + * interpolation, any dom event binding attribute interpolation such as for onclick, etc.) + * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual + * escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resource_url, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + + /** + * @ngdoc method + * @name ng.$sce#trustAsHtml + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.trustAsHtml(value)` → + * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.HTML, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedHtml + * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name ng.$sce#trustAsUrl + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.trustAsUrl(value)` → + * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedUrl + * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name ng.$sce#trustAsResourceUrl + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.trustAsResourceUrl(value)` → + * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedResourceUrl + * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the return + * value of {@link ng.$sce#methods_trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name ng.$sce#trustAsJs + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.trustAsJs(value)` → + * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.JS, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedJs + * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name ng.$sce#getTrusted + * @methodOf ng.$sce + * + * @description + * Delegates to {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted`}. As such, + * takes the result of a {@link ng.$sce#methods_trustAs `$sce.trustAs`}() call and returns the + * originally supplied value if the queried context type is a supertype of the created type. + * If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sce#methods_trustAs `$sce.trustAs`} + * call. + * @returns {*} The value the was originally provided to + * {@link ng.$sce#methods_trustAs `$sce.trustAs`} if valid in this context. + * Otherwise, throws an exception. + */ + + /** + * @ngdoc method + * @name ng.$sce#getTrustedHtml + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.getTrustedHtml(value)` → + * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)` + */ + + /** + * @ngdoc method + * @name ng.$sce#getTrustedCss + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.getTrustedCss(value)` → + * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)` + */ + + /** + * @ngdoc method + * @name ng.$sce#getTrustedUrl + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.getTrustedUrl(value)` → + * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.URL, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)` + */ + + /** + * @ngdoc method + * @name ng.$sce#getTrustedResourceUrl + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.getTrustedResourceUrl(value)` → + * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to pass to `$sceDelegate.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)` + */ + + /** + * @ngdoc method + * @name ng.$sce#getTrustedJs + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.getTrustedJs(value)` → + * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.JS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)` + */ + + /** + * @ngdoc method + * @name ng.$sce#parseAsHtml + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.parseAsHtml(expression string)` → + * {@link ng.$sce#methods_parse `$sce.parseAs($sce.HTML, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name ng.$sce#parseAsCss + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.parseAsCss(value)` → + * {@link ng.$sce#methods_parse `$sce.parseAs($sce.CSS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name ng.$sce#parseAsUrl + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.parseAsUrl(value)` → + * {@link ng.$sce#methods_parse `$sce.parseAs($sce.URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name ng.$sce#parseAsResourceUrl + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.parseAsResourceUrl(value)` → + * {@link ng.$sce#methods_parse `$sce.parseAs($sce.RESOURCE_URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name ng.$sce#parseAsJs + * @methodOf ng.$sce + * + * @description + * Shorthand method. `$sce.parseAsJs(value)` → + * {@link ng.$sce#methods_parse `$sce.parseAs($sce.JS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + // Shorthand delegations. + var parse = sce.parseAs, + getTrusted = sce.getTrusted, + trustAs = sce.trustAs; + + forEach(SCE_CONTEXTS, function (enumValue, name) { + var lName = lowercase(name); + sce[camelCase("parse_as_" + lName)] = function (expr) { + return parse(enumValue, expr); + }; + sce[camelCase("get_trusted_" + lName)] = function (value) { + return getTrusted(enumValue, value); + }; + sce[camelCase("trust_as_" + lName)] = function (value) { + return trustAs(enumValue, value); + }; + }); + + return sce; + }]; +} + +/** + * !!! This is an undocumented "private" service !!! + * + * @name ng.$sniffer + * @requires $window + * @requires $document + * + * @property {boolean} history Does the browser support html5 history api ? + * @property {boolean} hashchange Does the browser support hashchange event ? + * @property {boolean} transitions Does the browser support CSS transition events ? + * @property {boolean} animations Does the browser support CSS animation events ? + * + * @description + * This is very simple implementation of testing browser's features. + */ +function $SnifferProvider() { + this.$get = ['$window', '$document', function($window, $document) { + var eventSupport = {}, + android = + int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), + boxee = /Boxee/i.test(($window.navigator || {}).userAgent), + document = $document[0] || {}, + documentMode = document.documentMode, + vendorPrefix, + vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/, + bodyStyle = document.body && document.body.style, + transitions = false, + animations = false, + match; + + if (bodyStyle) { + for(var prop in bodyStyle) { + if(match = vendorRegex.exec(prop)) { + vendorPrefix = match[0]; + vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); + break; + } + } + + if(!vendorPrefix) { + vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit'; + } + + transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle)); + animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle)); + + if (android && (!transitions||!animations)) { + transitions = isString(document.body.style.webkitTransition); + animations = isString(document.body.style.webkitAnimation); + } + } + + + return { + // Android has history.pushState, but it does not update location correctly + // so let's not use the history API at all. + // http://code.google.com/p/android/issues/detail?id=17471 + // https://github.com/angular/angular.js/issues/904 + + // older webit browser (533.9) on Boxee box has exactly the same problem as Android has + // so let's not use the history API also + // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined + // jshint -W018 + history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), + // jshint +W018 + hashchange: 'onhashchange' in $window && + // IE8 compatible mode lies + (!documentMode || documentMode > 7), + hasEvent: function(event) { + // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have + // it. In particular the event is not fired when backspace or delete key are pressed or + // when cut operation is performed. + if (event == 'input' && msie == 9) return false; + + if (isUndefined(eventSupport[event])) { + var divElm = document.createElement('div'); + eventSupport[event] = 'on' + event in divElm; + } + + return eventSupport[event]; + }, + csp: csp(), + vendorPrefix: vendorPrefix, + transitions : transitions, + animations : animations, + msie : msie, + msieDocumentMode: documentMode + }; + }]; +} + +function $TimeoutProvider() { + this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler', + function($rootScope, $browser, $q, $exceptionHandler) { + var deferreds = {}; + + + /** + * @ngdoc function + * @name ng.$timeout + * @requires $browser + * + * @description + * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch + * block and delegates any exceptions to + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * The return value of registering a timeout function is a promise, which will be resolved when + * the timeout is reached and the timeout function is executed. + * + * To cancel a timeout request, call `$timeout.cancel(promise)`. + * + * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to + * synchronously flush the queue of deferred functions. + * + * @param {function()} fn A function, whose execution should be delayed. + * @param {number=} [delay=0] Delay in milliseconds. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block. + * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this + * promise will be resolved with is the return value of the `fn` function. + * + * @example + + + + +
+
+ Date format:
+ Current time is: +
+ Blood 1 : {{blood_1}} + Blood 2 : {{blood_2}} + + + +
+
+ +
+
+ */ + function timeout(fn, delay, invokeApply) { + var deferred = $q.defer(), + promise = deferred.promise, + skipApply = (isDefined(invokeApply) && !invokeApply), + timeoutId; + + timeoutId = $browser.defer(function() { + try { + deferred.resolve(fn()); + } catch(e) { + deferred.reject(e); + $exceptionHandler(e); + } + finally { + delete deferreds[promise.$$timeoutId]; + } + + if (!skipApply) $rootScope.$apply(); + }, delay); + + promise.$$timeoutId = timeoutId; + deferreds[timeoutId] = deferred; + + return promise; + } + + + /** + * @ngdoc function + * @name ng.$timeout#cancel + * @methodOf ng.$timeout + * + * @description + * Cancels a task associated with the `promise`. As a result of this, the promise will be + * resolved with a rejection. + * + * @param {Promise=} promise Promise returned by the `$timeout` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + timeout.cancel = function(promise) { + if (promise && promise.$$timeoutId in deferreds) { + deferreds[promise.$$timeoutId].reject('canceled'); + delete deferreds[promise.$$timeoutId]; + return $browser.defer.cancel(promise.$$timeoutId); + } + return false; + }; + + return timeout; + }]; +} + +// NOTE: The usage of window and document instead of $window and $document here is +// deliberate. This service depends on the specific behavior of anchor nodes created by the +// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and +// cause us to break tests. In addition, when the browser resolves a URL for XHR, it +// doesn't know about mocked locations and resolves URLs to the real document - which is +// exactly the behavior needed here. There is little value is mocking these out for this +// service. +var urlParsingNode = document.createElement("a"); +var originUrl = urlResolve(window.location.href, true); + + +/** + * + * Implementation Notes for non-IE browsers + * ---------------------------------------- + * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, + * results both in the normalizing and parsing of the URL. Normalizing means that a relative + * URL will be resolved into an absolute URL in the context of the application document. + * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related + * properties are all populated to reflect the normalized URL. This approach has wide + * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * + * Implementation Notes for IE + * --------------------------- + * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other + * browsers. However, the parsed components will not be set if the URL assigned did not specify + * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We + * work around that by performing the parsing in a 2nd step by taking a previously normalized + * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the + * properties such as protocol, hostname, port, etc. + * + * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one + * uses the inner HTML approach to assign the URL as part of an HTML snippet - + * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL. + * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. + * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that + * method and IE < 8 is unsupported. + * + * References: + * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * http://url.spec.whatwg.org/#urlutils + * https://github.com/angular/angular.js/pull/2902 + * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ + * + * @function + * @param {string} url The URL to be parsed. + * @description Normalizes and parses a URL. + * @returns {object} Returns the normalized URL as a dictionary. + * + * | member name | Description | + * |---------------|----------------| + * | href | A normalized version of the provided URL if it was not an absolute URL | + * | protocol | The protocol including the trailing colon | + * | host | The host and port (if the port is non-default) of the normalizedUrl | + * | search | The search params, minus the question mark | + * | hash | The hash string, minus the hash symbol + * | hostname | The hostname + * | port | The port, without ":" + * | pathname | The pathname, beginning with "/" + * + */ +function urlResolve(url, base) { + var href = url; + + if (msie) { + // Normalize before parse. Refer Implementation Notes on why this is + // done in two steps on IE. + urlParsingNode.setAttribute("href", href); + href = urlParsingNode.href; + } + + urlParsingNode.setAttribute('href', href); + + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: (urlParsingNode.pathname.charAt(0) === '/') + ? urlParsingNode.pathname + : '/' + urlParsingNode.pathname + }; +} + +/** + * Parse a request URL and determine whether this is a same-origin request as the application document. + * + * @param {string|object} requestUrl The url of the request as a string that will be resolved + * or a parsed URL object. + * @returns {boolean} Whether the request is for the same origin as the application document. + */ +function urlIsSameOrigin(requestUrl) { + var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl; + return (parsed.protocol === originUrl.protocol && + parsed.host === originUrl.host); +} + +/** + * @ngdoc object + * @name ng.$window + * + * @description + * A reference to the browser's `window` object. While `window` + * is globally available in JavaScript, it causes testability problems, because + * it is a global variable. In angular we always refer to it through the + * `$window` service, so it may be overridden, removed or mocked for testing. + * + * Expressions, like the one defined for the `ngClick` directive in the example + * below, are evaluated with respect to the current scope. Therefore, there is + * no risk of inadvertently coding in a dependency on a global value in such an + * expression. + * + * @example + + + +
+ + +
+
+ + it('should display the greeting in the input box', function() { + input('greeting').enter('Hello, E2E Tests'); + // If we click the button it will block the test runner + // element(':button').click(); + }); + +
+ */ +function $WindowProvider(){ + this.$get = valueFn(window); +} + +/** + * @ngdoc object + * @name ng.$filterProvider + * @description + * + * Filters are just functions which transform input to an output. However filters need to be + * Dependency Injected. To achieve this a filter definition consists of a factory function which is + * annotated with dependencies and is responsible for creating a filter function. + * + *
+ *   // Filter registration
+ *   function MyModule($provide, $filterProvider) {
+ *     // create a service to demonstrate injection (not always needed)
+ *     $provide.value('greet', function(name){
+ *       return 'Hello ' + name + '!';
+ *     });
+ *
+ *     // register a filter factory which uses the
+ *     // greet service to demonstrate DI.
+ *     $filterProvider.register('greet', function(greet){
+ *       // return the filter function which uses the greet service
+ *       // to generate salutation
+ *       return function(text) {
+ *         // filters need to be forgiving so check input validity
+ *         return text && greet(text) || text;
+ *       };
+ *     });
+ *   }
+ * 
+ * + * The filter function is registered with the `$injector` under the filter name suffix with + * `Filter`. + * + *
+ *   it('should be the same instance', inject(
+ *     function($filterProvider) {
+ *       $filterProvider.register('reverse', function(){
+ *         return ...;
+ *       });
+ *     },
+ *     function($filter, reverseFilter) {
+ *       expect($filter('reverse')).toBe(reverseFilter);
+ *     });
+ * 
+ * + * + * For more information about how angular filters work, and how to create your own filters, see + * {@link guide/filter Filters} in the Angular Developer Guide. + */ +/** + * @ngdoc method + * @name ng.$filterProvider#register + * @methodOf ng.$filterProvider + * @description + * Register filter factory function. + * + * @param {String} name Name of the filter. + * @param {function} fn The filter factory function which is injectable. + */ + + +/** + * @ngdoc function + * @name ng.$filter + * @function + * @description + * Filters are used for formatting data displayed to the user. + * + * The general syntax in templates is as follows: + * + * {{ expression [| filter_name[:parameter_value] ... ] }} + * + * @param {String} name Name of the filter function to retrieve + * @return {Function} the filter function + */ +$FilterProvider.$inject = ['$provide']; +function $FilterProvider($provide) { + var suffix = 'Filter'; + + /** + * @ngdoc function + * @name ng.$controllerProvider#register + * @methodOf ng.$controllerProvider + * @param {string|Object} name Name of the filter function, or an object map of filters where + * the keys are the filter names and the values are the filter factories. + * @returns {Object} Registered filter instance, or if a map of filters was provided then a map + * of the registered filter instances. + */ + function register(name, factory) { + if(isObject(name)) { + var filters = {}; + forEach(name, function(filter, key) { + filters[key] = register(key, filter); + }); + return filters; + } else { + return $provide.factory(name + suffix, factory); + } + } + this.register = register; + + this.$get = ['$injector', function($injector) { + return function(name) { + return $injector.get(name + suffix); + }; + }]; + + //////////////////////////////////////// + + /* global + currencyFilter: false, + dateFilter: false, + filterFilter: false, + jsonFilter: false, + limitToFilter: false, + lowercaseFilter: false, + numberFilter: false, + orderByFilter: false, + uppercaseFilter: false, + */ + + register('currency', currencyFilter); + register('date', dateFilter); + register('filter', filterFilter); + register('json', jsonFilter); + register('limitTo', limitToFilter); + register('lowercase', lowercaseFilter); + register('number', numberFilter); + register('orderBy', orderByFilter); + register('uppercase', uppercaseFilter); +} + +/** + * @ngdoc filter + * @name ng.filter:filter + * @function + * + * @description + * Selects a subset of items from `array` and returns it as a new array. + * + * @param {Array} array The source array. + * @param {string|Object|function()} expression The predicate to be used for selecting items from + * `array`. + * + * Can be one of: + * + * - `string`: Predicate that results in a substring match using the value of `expression` + * string. All strings or objects with string properties in `array` that contain this string + * will be returned. The predicate can be negated by prefixing the string with `!`. + * + * - `Object`: A pattern object can be used to filter specific properties on objects contained + * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items + * which have property `name` containing "M" and property `phone` containing "1". A special + * property name `$` can be used (as in `{$:"text"}`) to accept a match against any + * property of the object. That's equivalent to the simple substring match with a `string` + * as described above. + * + * - `function`: A predicate function can be used to write arbitrary filters. The function is + * called for each element of `array`. The final result is an array of those elements that + * the predicate returned true for. + * + * @param {function(expected, actual)|true|undefined} comparator Comparator which is used in + * determining if the expected value (from the filter expression) and actual value (from + * the object in the array) should be considered a match. + * + * Can be one of: + * + * - `function(expected, actual)`: + * The function will be given the object value and the predicate value to compare and + * should return true if the item should be included in filtered result. + * + * - `true`: A shorthand for `function(expected, actual) { return angular.equals(expected, actual)}`. + * this is essentially strict comparison of expected and actual. + * + * - `false|undefined`: A short hand for a function which will look for a substring match in case + * insensitive way. + * + * @example + + +
+ + Search: + + + + + + +
NamePhone
{{friend.name}}{{friend.phone}}
+
+ Any:
+ Name only
+ Phone only
+ Equality
+ + + + + + +
NamePhone
{{friend.name}}{{friend.phone}}
+
+ + it('should search across all fields when filtering with a string', function() { + input('searchText').enter('m'); + expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). + toEqual(['Mary', 'Mike', 'Adam']); + + input('searchText').enter('76'); + expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). + toEqual(['John', 'Julie']); + }); + + it('should search in specific fields when filtering with a predicate object', function() { + input('search.$').enter('i'); + expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). + toEqual(['Mary', 'Mike', 'Julie', 'Juliette']); + }); + it('should use a equal comparison when comparator is true', function() { + input('search.name').enter('Julie'); + input('strict').check(); + expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). + toEqual(['Julie']); + }); + +
+ */ +function filterFilter() { + return function(array, expression, comparator) { + if (!isArray(array)) return array; + + var comparatorType = typeof(comparator), + predicates = []; + + predicates.check = function(value) { + for (var j = 0; j < predicates.length; j++) { + if(!predicates[j](value)) { + return false; + } + } + return true; + }; + + if (comparatorType !== 'function') { + if (comparatorType === 'boolean' && comparator) { + comparator = function(obj, text) { + return angular.equals(obj, text); + }; + } else { + comparator = function(obj, text) { + text = (''+text).toLowerCase(); + return (''+obj).toLowerCase().indexOf(text) > -1; + }; + } + } + + var search = function(obj, text){ + if (typeof text == 'string' && text.charAt(0) === '!') { + return !search(obj, text.substr(1)); + } + switch (typeof obj) { + case "boolean": + case "number": + case "string": + return comparator(obj, text); + case "object": + switch (typeof text) { + case "object": + return comparator(obj, text); + default: + for ( var objKey in obj) { + if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { + return true; + } + } + break; + } + return false; + case "array": + for ( var i = 0; i < obj.length; i++) { + if (search(obj[i], text)) { + return true; + } + } + return false; + default: + return false; + } + }; + switch (typeof expression) { + case "boolean": + case "number": + case "string": + // Set up expression object and fall through + expression = {$:expression}; + // jshint -W086 + case "object": + // jshint +W086 + for (var key in expression) { + if (key == '$') { + (function() { + if (!expression[key]) return; + var path = key; + predicates.push(function(value) { + return search(value, expression[path]); + }); + })(); + } else { + (function() { + if (typeof(expression[key]) == 'undefined') { return; } + var path = key; + predicates.push(function(value) { + return search(getter(value,path), expression[path]); + }); + })(); + } + } + break; + case 'function': + predicates.push(expression); + break; + default: + return array; + } + var filtered = []; + for ( var j = 0; j < array.length; j++) { + var value = array[j]; + if (predicates.check(value)) { + filtered.push(value); + } + } + return filtered; + }; +} + +/** + * @ngdoc filter + * @name ng.filter:currency + * @function + * + * @description + * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default + * symbol for current locale is used. + * + * @param {number} amount Input to filter. + * @param {string=} symbol Currency symbol or identifier to be displayed. + * @returns {string} Formatted number. + * + * + * @example + + + +
+
+ default currency symbol ($): {{amount | currency}}
+ custom currency identifier (USD$): {{amount | currency:"USD$"}} +
+
+ + it('should init with 1234.56', function() { + expect(binding('amount | currency')).toBe('$1,234.56'); + expect(binding('amount | currency:"USD$"')).toBe('USD$1,234.56'); + }); + it('should update', function() { + input('amount').enter('-1234'); + expect(binding('amount | currency')).toBe('($1,234.00)'); + expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)'); + }); + +
+ */ +currencyFilter.$inject = ['$locale']; +function currencyFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(amount, currencySymbol){ + if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM; + return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2). + replace(/\u00A4/g, currencySymbol); + }; +} + +/** + * @ngdoc filter + * @name ng.filter:number + * @function + * + * @description + * Formats a number as text. + * + * If the input is not a number an empty string is returned. + * + * @param {number|string} number Number to format. + * @param {(number|string)=} fractionSize Number of decimal places to round the number to. + * If this is not provided then the fraction size is computed from the current locale's number + * formatting pattern. In the case of the default locale, it will be 3. + * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. + * + * @example + + + +
+ Enter number:
+ Default formatting: {{val | number}}
+ No fractions: {{val | number:0}}
+ Negative number: {{-val | number:4}} +
+
+ + it('should format numbers', function() { + expect(binding('val | number')).toBe('1,234.568'); + expect(binding('val | number:0')).toBe('1,235'); + expect(binding('-val | number:4')).toBe('-1,234.5679'); + }); + + it('should update', function() { + input('val').enter('3374.333'); + expect(binding('val | number')).toBe('3,374.333'); + expect(binding('val | number:0')).toBe('3,374'); + expect(binding('-val | number:4')).toBe('-3,374.3330'); + }); + +
+ */ + + +numberFilter.$inject = ['$locale']; +function numberFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(number, fractionSize) { + return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, + fractionSize); + }; +} + +var DECIMAL_SEP = '.'; +function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { + if (isNaN(number) || !isFinite(number)) return ''; + + var isNegative = number < 0; + number = Math.abs(number); + var numStr = number + '', + formatedText = '', + parts = []; + + var hasExponent = false; + if (numStr.indexOf('e') !== -1) { + var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); + if (match && match[2] == '-' && match[3] > fractionSize + 1) { + numStr = '0'; + } else { + formatedText = numStr; + hasExponent = true; + } + } + + if (!hasExponent) { + var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; + + // determine fractionSize if it is not specified + if (isUndefined(fractionSize)) { + fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); + } + + var pow = Math.pow(10, fractionSize); + number = Math.round(number * pow) / pow; + var fraction = ('' + number).split(DECIMAL_SEP); + var whole = fraction[0]; + fraction = fraction[1] || ''; + + var i, pos = 0, + lgroup = pattern.lgSize, + group = pattern.gSize; + + if (whole.length >= (lgroup + group)) { + pos = whole.length - lgroup; + for (i = 0; i < pos; i++) { + if ((pos - i)%group === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + } + + for (i = pos; i < whole.length; i++) { + if ((whole.length - i)%lgroup === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + + // format fraction part. + while(fraction.length < fractionSize) { + fraction += '0'; + } + + if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); + } else { + + if (fractionSize > 0 && number > -1 && number < 1) { + formatedText = number.toFixed(fractionSize); + } + } + + parts.push(isNegative ? pattern.negPre : pattern.posPre); + parts.push(formatedText); + parts.push(isNegative ? pattern.negSuf : pattern.posSuf); + return parts.join(''); +} + +function padNumber(num, digits, trim) { + var neg = ''; + if (num < 0) { + neg = '-'; + num = -num; + } + num = '' + num; + while(num.length < digits) num = '0' + num; + if (trim) + num = num.substr(num.length - digits); + return neg + num; +} + + +function dateGetter(name, size, offset, trim) { + offset = offset || 0; + return function(date) { + var value = date['get' + name](); + if (offset > 0 || value > -offset) + value += offset; + if (value === 0 && offset == -12 ) value = 12; + return padNumber(value, size, trim); + }; +} + +function dateStrGetter(name, shortForm) { + return function(date, formats) { + var value = date['get' + name](); + var get = uppercase(shortForm ? ('SHORT' + name) : name); + + return formats[get][value]; + }; +} + +function timeZoneGetter(date) { + var zone = -1 * date.getTimezoneOffset(); + var paddedZone = (zone >= 0) ? "+" : ""; + + paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + + padNumber(Math.abs(zone % 60), 2); + + return paddedZone; +} + +function ampmGetter(date, formats) { + return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; +} + +var DATE_FORMATS = { + yyyy: dateGetter('FullYear', 4), + yy: dateGetter('FullYear', 2, 0, true), + y: dateGetter('FullYear', 1), + MMMM: dateStrGetter('Month'), + MMM: dateStrGetter('Month', true), + MM: dateGetter('Month', 2, 1), + M: dateGetter('Month', 1, 1), + dd: dateGetter('Date', 2), + d: dateGetter('Date', 1), + HH: dateGetter('Hours', 2), + H: dateGetter('Hours', 1), + hh: dateGetter('Hours', 2, -12), + h: dateGetter('Hours', 1, -12), + mm: dateGetter('Minutes', 2), + m: dateGetter('Minutes', 1), + ss: dateGetter('Seconds', 2), + s: dateGetter('Seconds', 1), + // while ISO 8601 requires fractions to be prefixed with `.` or `,` + // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions + sss: dateGetter('Milliseconds', 3), + EEEE: dateStrGetter('Day'), + EEE: dateStrGetter('Day', true), + a: ampmGetter, + Z: timeZoneGetter +}; + +var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/, + NUMBER_STRING = /^\-?\d+$/; + +/** + * @ngdoc filter + * @name ng.filter:date + * @function + * + * @description + * Formats `date` to a string based on the requested `format`. + * + * `format` string can be composed of the following elements: + * + * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) + * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) + * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) + * * `'MMMM'`: Month in year (January-December) + * * `'MMM'`: Month in year (Jan-Dec) + * * `'MM'`: Month in year, padded (01-12) + * * `'M'`: Month in year (1-12) + * * `'dd'`: Day in month, padded (01-31) + * * `'d'`: Day in month (1-31) + * * `'EEEE'`: Day in Week,(Sunday-Saturday) + * * `'EEE'`: Day in Week, (Sun-Sat) + * * `'HH'`: Hour in day, padded (00-23) + * * `'H'`: Hour in day (0-23) + * * `'hh'`: Hour in am/pm, padded (01-12) + * * `'h'`: Hour in am/pm, (1-12) + * * `'mm'`: Minute in hour, padded (00-59) + * * `'m'`: Minute in hour (0-59) + * * `'ss'`: Second in minute, padded (00-59) + * * `'s'`: Second in minute (0-59) + * * `'.sss' or ',sss'`: Millisecond in second, padded (000-999) + * * `'a'`: am/pm marker + * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) + * + * `format` string can also be one of the following predefined + * {@link guide/i18n localizable formats}: + * + * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale + * (e.g. Sep 3, 2010 12:05:08 pm) + * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 pm) + * * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US locale + * (e.g. Friday, September 3, 2010) + * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010) + * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) + * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) + * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm) + * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm) + * + * `format` string can contain literal values. These need to be quoted with single quotes (e.g. + * `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence + * (e.g. `"h 'o''clock'"`). + * + * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or + * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its + * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is + * specified in the string input, the time is considered to be in the local timezone. + * @param {string=} format Formatting rules (see Description). If not specified, + * `mediumDate` is used. + * @returns {string} Formatted string or the input if input is not recognized as date/millis. + * + * @example + + + {{1288323623006 | date:'medium'}}: + {{1288323623006 | date:'medium'}}
+ {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
+ {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: + {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
+
+ + it('should format date', function() { + expect(binding("1288323623006 | date:'medium'")). + toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); + expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). + toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); + expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). + toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); + }); + +
+ */ +dateFilter.$inject = ['$locale']; +function dateFilter($locale) { + + + var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; + // 1 2 3 4 5 6 7 8 9 10 11 + function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8601_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0, + dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, + timeSetter = match[8] ? date.setUTCHours : date.setHours; + + if (match[9]) { + tzHour = int(match[9] + match[10]); + tzMin = int(match[9] + match[11]); + } + dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3])); + var h = int(match[4]||0) - tzHour; + var m = int(match[5]||0) - tzMin; + var s = int(match[6]||0); + var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000); + timeSetter.call(date, h, m, s, ms); + return date; + } + return string; + } + + + return function(date, format) { + var text = '', + parts = [], + fn, match; + + format = format || 'mediumDate'; + format = $locale.DATETIME_FORMATS[format] || format; + if (isString(date)) { + if (NUMBER_STRING.test(date)) { + date = int(date); + } else { + date = jsonStringToDate(date); + } + } + + if (isNumber(date)) { + date = new Date(date); + } + + if (!isDate(date)) { + return date; + } + + while(format) { + match = DATE_FORMATS_SPLIT.exec(format); + if (match) { + parts = concat(parts, match, 1); + format = parts.pop(); + } else { + parts.push(format); + format = null; + } + } + + forEach(parts, function(value){ + fn = DATE_FORMATS[value]; + text += fn ? fn(date, $locale.DATETIME_FORMATS) + : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); + }); + + return text; + }; +} + + +/** + * @ngdoc filter + * @name ng.filter:json + * @function + * + * @description + * Allows you to convert a JavaScript object into JSON string. + * + * This filter is mostly useful for debugging. When using the double curly {{value}} notation + * the binding is automatically converted to JSON. + * + * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. + * @returns {string} JSON string. + * + * + * @example: + + +
{{ {'name':'value'} | json }}
+
+ + it('should jsonify filtered objects', function() { + expect(binding("{'name':'value'}")).toMatch(/\{\n "name": ?"value"\n}/); + }); + +
+ * + */ +function jsonFilter() { + return function(object) { + return toJson(object, true); + }; +} + + +/** + * @ngdoc filter + * @name ng.filter:lowercase + * @function + * @description + * Converts string to lowercase. + * @see angular.lowercase + */ +var lowercaseFilter = valueFn(lowercase); + + +/** + * @ngdoc filter + * @name ng.filter:uppercase + * @function + * @description + * Converts string to uppercase. + * @see angular.uppercase + */ +var uppercaseFilter = valueFn(uppercase); + +/** + * @ngdoc function + * @name ng.filter:limitTo + * @function + * + * @description + * Creates a new array or string containing only a specified number of elements. The elements + * are taken from either the beginning or the end of the source array or string, as specified by + * the value and sign (positive or negative) of `limit`. + * + * @param {Array|string} input Source array or string to be limited. + * @param {string|number} limit The length of the returned array or string. If the `limit` number + * is positive, `limit` number of items from the beginning of the source array/string are copied. + * If the number is negative, `limit` number of items from the end of the source array/string + * are copied. The `limit` will be trimmed if it exceeds `array.length` + * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array + * had less than `limit` elements. + * + * @example + + + +
+ Limit {{numbers}} to: +

Output numbers: {{ numbers | limitTo:numLimit }}

+ Limit {{letters}} to: +

Output letters: {{ letters | limitTo:letterLimit }}

+
+
+ + it('should limit the number array to first three items', function() { + expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3'); + expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3'); + expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]'); + expect(binding('letters | limitTo:letterLimit')).toEqual('abc'); + }); + + it('should update the output when -3 is entered', function() { + input('numLimit').enter(-3); + input('letterLimit').enter(-3); + expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]'); + expect(binding('letters | limitTo:letterLimit')).toEqual('ghi'); + }); + + it('should not exceed the maximum size of input array', function() { + input('numLimit').enter(100); + input('letterLimit').enter(100); + expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]'); + expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi'); + }); + +
+ */ +function limitToFilter(){ + return function(input, limit) { + if (!isArray(input) && !isString(input)) return input; + + limit = int(limit); + + if (isString(input)) { + //NaN check on limit + if (limit) { + return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length); + } else { + return ""; + } + } + + var out = [], + i, n; + + // if abs(limit) exceeds maximum length, trim it + if (limit > input.length) + limit = input.length; + else if (limit < -input.length) + limit = -input.length; + + if (limit > 0) { + i = 0; + n = limit; + } else { + i = input.length + limit; + n = input.length; + } + + for (; i} expression A predicate to be + * used by the comparator to determine the order of elements. + * + * Can be one of: + * + * - `function`: Getter function. The result of this function will be sorted using the + * `<`, `=`, `>` operator. + * - `string`: An Angular expression which evaluates to an object to order by, such as 'name' + * to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control + * ascending or descending sort order (for example, +name or -name). + * - `Array`: An array of function or string predicates. The first predicate in the array + * is used for sorting, but when two items are equivalent, the next predicate is used. + * + * @param {boolean=} reverse Reverse the order the array. + * @returns {Array} Sorted copy of the source array. + * + * @example + + + +
+
Sorting predicate = {{predicate}}; reverse = {{reverse}}
+
+ [ unsorted ] + + + + + + + + + + + +
Name + (^)Phone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
+
+
+ + it('should be reverse ordered by aged', function() { + expect(binding('predicate')).toBe('-age'); + expect(repeater('table.friend', 'friend in friends').column('friend.age')). + toEqual(['35', '29', '21', '19', '10']); + expect(repeater('table.friend', 'friend in friends').column('friend.name')). + toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); + }); + + it('should reorder the table when user selects different predicate', function() { + element('.doc-example-live a:contains("Name")').click(); + expect(repeater('table.friend', 'friend in friends').column('friend.name')). + toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); + expect(repeater('table.friend', 'friend in friends').column('friend.age')). + toEqual(['35', '10', '29', '19', '21']); + + element('.doc-example-live a:contains("Phone")').click(); + expect(repeater('table.friend', 'friend in friends').column('friend.phone')). + toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); + expect(repeater('table.friend', 'friend in friends').column('friend.name')). + toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); + }); + +
+ */ +orderByFilter.$inject = ['$parse']; +function orderByFilter($parse){ + return function(array, sortPredicate, reverseOrder) { + if (!isArray(array)) return array; + if (!sortPredicate) return array; + sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate]; + sortPredicate = map(sortPredicate, function(predicate){ + var descending = false, get = predicate || identity; + if (isString(predicate)) { + if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { + descending = predicate.charAt(0) == '-'; + predicate = predicate.substring(1); + } + get = $parse(predicate); + } + return reverseComparator(function(a,b){ + return compare(get(a),get(b)); + }, descending); + }); + var arrayCopy = []; + for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); } + return arrayCopy.sort(reverseComparator(comparator, reverseOrder)); + + function comparator(o1, o2){ + for ( var i = 0; i < sortPredicate.length; i++) { + var comp = sortPredicate[i](o1, o2); + if (comp !== 0) return comp; + } + return 0; + } + function reverseComparator(comp, descending) { + return toBoolean(descending) + ? function(a,b){return comp(b,a);} + : comp; + } + function compare(v1, v2){ + var t1 = typeof v1; + var t2 = typeof v2; + if (t1 == t2) { + if (t1 == "string") { + v1 = v1.toLowerCase(); + v2 = v2.toLowerCase(); + } + if (v1 === v2) return 0; + return v1 < v2 ? -1 : 1; + } else { + return t1 < t2 ? -1 : 1; + } + } + }; +} + +function ngDirective(directive) { + if (isFunction(directive)) { + directive = { + link: directive + }; + } + directive.restrict = directive.restrict || 'AC'; + return valueFn(directive); +} + +/** + * @ngdoc directive + * @name ng.directive:a + * @restrict E + * + * @description + * Modifies the default behavior of the html A tag so that the default action is prevented when + * the href attribute is empty. + * + * This change permits the easy creation of action links with the `ngClick` directive + * without changing the location or causing page reloads, e.g.: + * `Add Item` + */ +var htmlAnchorDirective = valueFn({ + restrict: 'E', + compile: function(element, attr) { + + if (msie <= 8) { + + // turn link into a stylable link in IE + // but only if it doesn't have name attribute, in which case it's an anchor + if (!attr.href && !attr.name) { + attr.$set('href', ''); + } + + // add a comment node to anchors to workaround IE bug that causes element content to be reset + // to new attribute content if attribute is updated with value containing @ and element also + // contains value with @ + // see issue #1949 + element.append(document.createComment('IE fix')); + } + + return function(scope, element) { + element.on('click', function(event){ + // if we have no href url, then don't navigate anywhere. + if (!element.attr('href')) { + event.preventDefault(); + } + }); + }; + } +}); + +/** + * @ngdoc directive + * @name ng.directive:ngHref + * @restrict A + * + * @description + * Using Angular markup like `{{hash}}` in an href attribute will + * make the link go to the wrong URL if the user clicks it before + * Angular has a chance to replace the `{{hash}}` markup with its + * value. Until Angular replaces the markup the link will be broken + * and will most likely return a 404 error. + * + * The `ngHref` directive solves this problem. + * + * The wrong way to write it: + *
+ * 
+ * 
+ * + * The correct way to write it: + *
+ * 
+ * 
+ * + * @element A + * @param {template} ngHref any string which can contain `{{}}` markup. + * + * @example + * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes + * in links and their different behaviors: + + +
+
link 1 (link, don't reload)
+ link 2 (link, don't reload)
+ link 3 (link, reload!)
+ anchor (link, don't reload)
+ anchor (no link)
+ link (link, change location) + + + it('should execute ng-click but not reload when href without value', function() { + element('#link-1').click(); + expect(input('value').val()).toEqual('1'); + expect(element('#link-1').attr('href')).toBe(""); + }); + + it('should execute ng-click but not reload when href empty string', function() { + element('#link-2').click(); + expect(input('value').val()).toEqual('2'); + expect(element('#link-2').attr('href')).toBe(""); + }); + + it('should execute ng-click and change url when ng-href specified', function() { + expect(element('#link-3').attr('href')).toBe("/123"); + + element('#link-3').click(); + expect(browser().window().path()).toEqual('/123'); + }); + + it('should execute ng-click but not reload when href empty string and name specified', function() { + element('#link-4').click(); + expect(input('value').val()).toEqual('4'); + expect(element('#link-4').attr('href')).toBe(''); + }); + + it('should execute ng-click but not reload when no href but name specified', function() { + element('#link-5').click(); + expect(input('value').val()).toEqual('5'); + expect(element('#link-5').attr('href')).toBe(undefined); + }); + + it('should only change url when only ng-href', function() { + input('value').enter('6'); + expect(element('#link-6').attr('href')).toBe('6'); + + element('#link-6').click(); + expect(browser().location().url()).toEqual('/6'); + }); + + + */ + +/** + * @ngdoc directive + * @name ng.directive:ngSrc + * @restrict A + * + * @description + * Using Angular markup like `{{hash}}` in a `src` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrc` directive solves this problem. + * + * The buggy way to write it: + *
+ * 
+ * 
+ * + * The correct way to write it: + *
+ * 
+ * 
+ * + * @element IMG + * @param {template} ngSrc any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ng.directive:ngSrcset + * @restrict A + * + * @description + * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrcset` directive solves this problem. + * + * The buggy way to write it: + *
+ * 
+ * 
+ * + * The correct way to write it: + *
+ * 
+ * 
+ * + * @element IMG + * @param {template} ngSrcset any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ng.directive:ngDisabled + * @restrict A + * + * @description + * + * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs: + *
+ * 
+ * + *
+ *
+ * + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as disabled. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngDisabled` directive solves this problem for the `disabled` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * + * @example + + + Click me to toggle:
+ +
+ + it('should toggle button', function() { + expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy(); + input('checked').check(); + expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy(); + }); + +
+ * + * @element INPUT + * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, + * then special attribute "disabled" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngChecked + * @restrict A + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as checked. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngChecked` directive solves this problem for the `checked` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + + + Check me to check both:
+ +
+ + it('should check both checkBoxes', function() { + expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy(); + input('master').check(); + expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy(); + }); + +
+ * + * @element INPUT + * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, + * then special attribute "checked" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngReadonly + * @restrict A + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as readonly. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngReadonly` directive solves this problem for the `readonly` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + + * @example + + + Check me to make text readonly:
+ +
+ + it('should toggle readonly attr', function() { + expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy(); + input('checked').check(); + expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy(); + }); + +
+ * + * @element INPUT + * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, + * then special attribute "readonly" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngSelected + * @restrict A + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as selected. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngSelected` directive solves this problem for the `selected` atttribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + + + Check me to select:
+ +
+ + it('should select Greetings!', function() { + expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy(); + input('selected').check(); + expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy(); + }); + +
+ * + * @element OPTION + * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, + * then special attribute "selected" will be set on the element + */ + +/** + * @ngdoc directive + * @name ng.directive:ngOpen + * @restrict A + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as open. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngOpen` directive solves this problem for the `open` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + + * + * @example + + + Check me check multiple:
+
+ Show/Hide me +
+
+ + it('should toggle open', function() { + expect(element('#details').prop('open')).toBeFalsy(); + input('open').check(); + expect(element('#details').prop('open')).toBeTruthy(); + }); + +
+ * + * @element DETAILS + * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, + * then special attribute "open" will be set on the element + */ + +var ngAttributeAliasDirectives = {}; + + +// boolean attrs are evaluated +forEach(BOOLEAN_ATTR, function(propName, attrName) { + // binding to multiple is not supported + if (propName == "multiple") return; + + var normalized = directiveNormalize('ng-' + attrName); + ngAttributeAliasDirectives[normalized] = function() { + return { + priority: 100, + compile: function() { + return function(scope, element, attr) { + scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { + attr.$set(attrName, !!value); + }); + }; + } + }; + }; +}); + + +// ng-src, ng-srcset, ng-href are interpolated +forEach(['src', 'srcset', 'href'], function(attrName) { + var normalized = directiveNormalize('ng-' + attrName); + ngAttributeAliasDirectives[normalized] = function() { + return { + priority: 99, // it needs to run after the attributes are interpolated + link: function(scope, element, attr) { + attr.$observe(normalized, function(value) { + if (!value) + return; + + attr.$set(attrName, value); + + // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist + // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need + // to set the property as well to achieve the desired effect. + // we use attr[attrName] value since $set can sanitize the url. + if (msie) element.prop(attrName, attr[attrName]); + }); + } + }; + }; +}); + +/* global -nullFormCtrl */ +var nullFormCtrl = { + $addControl: noop, + $removeControl: noop, + $setValidity: noop, + $setDirty: noop, + $setPristine: noop +}; + +/** + * @ngdoc object + * @name ng.directive:form.FormController + * + * @property {boolean} $pristine True if user has not interacted with the form yet. + * @property {boolean} $dirty True if user has already interacted with the form. + * @property {boolean} $valid True if all of the containing forms and controls are valid. + * @property {boolean} $invalid True if at least one containing control or form is invalid. + * + * @property {Object} $error Is an object hash, containing references to all invalid controls or + * forms, where: + * + * - keys are validation tokens (error names) — such as `required`, `url` or `email`, + * - values are arrays of controls or forms that are invalid with given error. + * + * @description + * `FormController` keeps track of all its controls and nested forms as well as state of them, + * such as being valid/invalid or dirty/pristine. + * + * Each {@link ng.directive:form form} directive creates an instance + * of `FormController`. + * + */ +//asks for $scope to fool the BC controller module +FormController.$inject = ['$element', '$attrs', '$scope']; +function FormController(element, attrs) { + var form = this, + parentForm = element.parent().controller('form') || nullFormCtrl, + invalidCount = 0, // used to easily determine if we are valid + errors = form.$error = {}, + controls = []; + + // init state + form.$name = attrs.name || attrs.ngForm; + form.$dirty = false; + form.$pristine = true; + form.$valid = true; + form.$invalid = false; + + parentForm.$addControl(form); + + // Setup initial state of the control + element.addClass(PRISTINE_CLASS); + toggleValidCss(true); + + // convenience method for easy toggling of classes + function toggleValidCss(isValid, validationErrorKey) { + validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; + element. + removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey). + addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey); + } + + /** + * @ngdoc function + * @name ng.directive:form.FormController#$addControl + * @methodOf ng.directive:form.FormController + * + * @description + * Register a control with the form. + * + * Input elements using ngModelController do this automatically when they are linked. + */ + form.$addControl = function(control) { + // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored + // and not added to the scope. Now we throw an error. + assertNotHasOwnProperty(control.$name, 'input'); + controls.push(control); + + if (control.$name) { + form[control.$name] = control; + } + }; + + /** + * @ngdoc function + * @name ng.directive:form.FormController#$removeControl + * @methodOf ng.directive:form.FormController + * + * @description + * Deregister a control from the form. + * + * Input elements using ngModelController do this automatically when they are destroyed. + */ + form.$removeControl = function(control) { + if (control.$name && form[control.$name] === control) { + delete form[control.$name]; + } + forEach(errors, function(queue, validationToken) { + form.$setValidity(validationToken, true, control); + }); + + arrayRemove(controls, control); + }; + + /** + * @ngdoc function + * @name ng.directive:form.FormController#$setValidity + * @methodOf ng.directive:form.FormController + * + * @description + * Sets the validity of a form control. + * + * This method will also propagate to parent forms. + */ + form.$setValidity = function(validationToken, isValid, control) { + var queue = errors[validationToken]; + + if (isValid) { + if (queue) { + arrayRemove(queue, control); + if (!queue.length) { + invalidCount--; + if (!invalidCount) { + toggleValidCss(isValid); + form.$valid = true; + form.$invalid = false; + } + errors[validationToken] = false; + toggleValidCss(true, validationToken); + parentForm.$setValidity(validationToken, true, form); + } + } + + } else { + if (!invalidCount) { + toggleValidCss(isValid); + } + if (queue) { + if (includes(queue, control)) return; + } else { + errors[validationToken] = queue = []; + invalidCount++; + toggleValidCss(false, validationToken); + parentForm.$setValidity(validationToken, false, form); + } + queue.push(control); + + form.$valid = false; + form.$invalid = true; + } + }; + + /** + * @ngdoc function + * @name ng.directive:form.FormController#$setDirty + * @methodOf ng.directive:form.FormController + * + * @description + * Sets the form to a dirty state. + * + * This method can be called to add the 'ng-dirty' class and set the form to a dirty + * state (ng-dirty class). This method will also propagate to parent forms. + */ + form.$setDirty = function() { + element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS); + form.$dirty = true; + form.$pristine = false; + parentForm.$setDirty(); + }; + + /** + * @ngdoc function + * @name ng.directive:form.FormController#$setPristine + * @methodOf ng.directive:form.FormController + * + * @description + * Sets the form to its pristine state. + * + * This method can be called to remove the 'ng-dirty' class and set the form to its pristine + * state (ng-pristine class). This method will also propagate to all the controls contained + * in this form. + * + * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after + * saving or resetting it. + */ + form.$setPristine = function () { + element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS); + form.$dirty = false; + form.$pristine = true; + forEach(controls, function(control) { + control.$setPristine(); + }); + }; +} + + +/** + * @ngdoc directive + * @name ng.directive:ngForm + * @restrict EAC + * + * @description + * Nestable alias of {@link ng.directive:form `form`} directive. HTML + * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a + * sub-group of controls needs to be determined. + * + * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + * + */ + + /** + * @ngdoc directive + * @name ng.directive:form + * @restrict E + * + * @description + * Directive that instantiates + * {@link ng.directive:form.FormController FormController}. + * + * If the `name` attribute is specified, the form controller is published onto the current scope under + * this name. + * + * # Alias: {@link ng.directive:ngForm `ngForm`} + * + * In Angular forms can be nested. This means that the outer form is valid when all of the child + * forms are valid as well. However, browsers do not allow nesting of `
` elements, so + * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to + * `` but can be nested. This allows you to have nested forms, which is very useful when + * using Angular validation directives in forms that are dynamically generated using the + * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name` + * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an + * `ngForm` directive and nest these in an outer `form` element. + * + * + * # CSS classes + * - `ng-valid` Is set if the form is valid. + * - `ng-invalid` Is set if the form is invalid. + * - `ng-pristine` Is set if the form is pristine. + * - `ng-dirty` Is set if the form is dirty. + * + * + * # Submitting a form and preventing the default action + * + * Since the role of forms in client-side Angular applications is different than in classical + * roundtrip apps, it is desirable for the browser not to translate the form submission into a full + * page reload that sends the data to the server. Instead some javascript logic should be triggered + * to handle the form submission in an application-specific way. + * + * For this reason, Angular prevents the default action (form submission to the server) unless the + * `` element has an `action` attribute specified. + * + * You can use one of the following two ways to specify what javascript method should be called when + * a form is submitted: + * + * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element + * - {@link ng.directive:ngClick ngClick} directive on the first + * button or input field of type submit (input[type=submit]) + * + * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit} + * or {@link ng.directive:ngClick ngClick} directives. + * This is because of the following form submission rules in the HTML specification: + * + * - If a form has only one input field then hitting enter in this field triggers form submit + * (`ngSubmit`) + * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter + * doesn't trigger submit + * - if a form has one or more input fields and one or more buttons or input[type=submit] then + * hitting enter in any of the input fields will trigger the click handler on the *first* button or + * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) + * + * @param {string=} name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + * + * @example + + + + + userType: + Required!
+ userType = {{userType}}
+ myForm.input.$valid = {{myForm.input.$valid}}
+ myForm.input.$error = {{myForm.input.$error}}
+ myForm.$valid = {{myForm.$valid}}
+ myForm.$error.required = {{!!myForm.$error.required}}
+ +
+ + it('should initialize to model', function() { + expect(binding('userType')).toEqual('guest'); + expect(binding('myForm.input.$valid')).toEqual('true'); + }); + + it('should be invalid if empty', function() { + input('userType').enter(''); + expect(binding('userType')).toEqual(''); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + +
+ */ +var formDirectiveFactory = function(isNgForm) { + return ['$timeout', function($timeout) { + var formDirective = { + name: 'form', + restrict: isNgForm ? 'EAC' : 'E', + controller: FormController, + compile: function() { + return { + pre: function(scope, formElement, attr, controller) { + if (!attr.action) { + // we can't use jq events because if a form is destroyed during submission the default + // action is not prevented. see #1238 + // + // IE 9 is not affected because it doesn't fire a submit event and try to do a full + // page reload if the form was destroyed by submission of the form via a click handler + // on a button in the form. Looks like an IE9 specific bug. + var preventDefaultListener = function(event) { + event.preventDefault + ? event.preventDefault() + : event.returnValue = false; // IE + }; + + addEventListenerFn(formElement[0], 'submit', preventDefaultListener); + + // unregister the preventDefault listener so that we don't not leak memory but in a + // way that will achieve the prevention of the default action. + formElement.on('$destroy', function() { + $timeout(function() { + removeEventListenerFn(formElement[0], 'submit', preventDefaultListener); + }, 0, false); + }); + } + + var parentFormCtrl = formElement.parent().controller('form'), + alias = attr.name || attr.ngForm; + + if (alias) { + setter(scope, alias, controller, alias); + } + if (parentFormCtrl) { + formElement.on('$destroy', function() { + parentFormCtrl.$removeControl(controller); + if (alias) { + setter(scope, alias, undefined, alias); + } + extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards + }); + } + } + }; + } + }; + + return formDirective; + }]; +}; + +var formDirective = formDirectiveFactory(); +var ngFormDirective = formDirectiveFactory(true); + +/* global + + -VALID_CLASS, + -INVALID_CLASS, + -PRISTINE_CLASS, + -DIRTY_CLASS +*/ + +var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; +var EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$/; +var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; + +var inputType = { + + /** + * @ngdoc inputType + * @name ng.directive:input.text + * + * @description + * Standard HTML text input with angular data binding. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Adds `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. + * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the + * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for + * patterns defined as scope expressions. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * + * @example + + + +
+ Single word: + + Required! + + Single word only! + + text = {{text}}
+ myForm.input.$valid = {{myForm.input.$valid}}
+ myForm.input.$error = {{myForm.input.$error}}
+ myForm.$valid = {{myForm.$valid}}
+ myForm.$error.required = {{!!myForm.$error.required}}
+
+
+ + it('should initialize to model', function() { + expect(binding('text')).toEqual('guest'); + expect(binding('myForm.input.$valid')).toEqual('true'); + }); + + it('should be invalid if empty', function() { + input('text').enter(''); + expect(binding('text')).toEqual(''); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + + it('should be invalid if multi word', function() { + input('text').enter('hello world'); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + + it('should not be trimmed', function() { + input('text').enter('untrimmed '); + expect(binding('text')).toEqual('untrimmed '); + expect(binding('myForm.input.$valid')).toEqual('true'); + }); + +
+ */ + 'text': textInputType, + + + /** + * @ngdoc inputType + * @name ng.directive:input.number + * + * @description + * Text input with number validation and transformation. Sets the `number` validation + * error if not a valid number. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. + * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the + * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for + * patterns defined as scope expressions. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
+ Number: + + Required! + + Not valid number! + value = {{value}}
+ myForm.input.$valid = {{myForm.input.$valid}}
+ myForm.input.$error = {{myForm.input.$error}}
+ myForm.$valid = {{myForm.$valid}}
+ myForm.$error.required = {{!!myForm.$error.required}}
+
+
+ + it('should initialize to model', function() { + expect(binding('value')).toEqual('12'); + expect(binding('myForm.input.$valid')).toEqual('true'); + }); + + it('should be invalid if empty', function() { + input('value').enter(''); + expect(binding('value')).toEqual(''); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + + it('should be invalid if over max', function() { + input('value').enter('123'); + expect(binding('value')).toEqual(''); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + +
+ */ + 'number': numberInputType, + + + /** + * @ngdoc inputType + * @name ng.directive:input.url + * + * @description + * Text input with URL validation. Sets the `url` validation error key if the content is not a + * valid URL. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. + * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the + * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for + * patterns defined as scope expressions. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
+ URL: + + Required! + + Not valid url! + text = {{text}}
+ myForm.input.$valid = {{myForm.input.$valid}}
+ myForm.input.$error = {{myForm.input.$error}}
+ myForm.$valid = {{myForm.$valid}}
+ myForm.$error.required = {{!!myForm.$error.required}}
+ myForm.$error.url = {{!!myForm.$error.url}}
+
+
+ + it('should initialize to model', function() { + expect(binding('text')).toEqual('http://google.com'); + expect(binding('myForm.input.$valid')).toEqual('true'); + }); + + it('should be invalid if empty', function() { + input('text').enter(''); + expect(binding('text')).toEqual(''); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + + it('should be invalid if not url', function() { + input('text').enter('xxx'); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + +
+ */ + 'url': urlInputType, + + + /** + * @ngdoc inputType + * @name ng.directive:input.email + * + * @description + * Text input with email validation. Sets the `email` validation error key if not a valid email + * address. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. + * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the + * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for + * patterns defined as scope expressions. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
+ Email: + + Required! + + Not valid email! + text = {{text}}
+ myForm.input.$valid = {{myForm.input.$valid}}
+ myForm.input.$error = {{myForm.input.$error}}
+ myForm.$valid = {{myForm.$valid}}
+ myForm.$error.required = {{!!myForm.$error.required}}
+ myForm.$error.email = {{!!myForm.$error.email}}
+
+
+ + it('should initialize to model', function() { + expect(binding('text')).toEqual('me@example.com'); + expect(binding('myForm.input.$valid')).toEqual('true'); + }); + + it('should be invalid if empty', function() { + input('text').enter(''); + expect(binding('text')).toEqual(''); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + + it('should be invalid if not email', function() { + input('text').enter('xxx'); + expect(binding('myForm.input.$valid')).toEqual('false'); + }); + +
+ */ + 'email': emailInputType, + + + /** + * @ngdoc inputType + * @name ng.directive:input.radio + * + * @description + * HTML radio button. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string} value The value to which the expression should be set when selected. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
+ Red
+ Green
+ Blue
+ color = {{color}}
+
+
+ + it('should change state', function() { + expect(binding('color')).toEqual('blue'); + + input('color').select('red'); + expect(binding('color')).toEqual('red'); + }); + +
+ */ + 'radio': radioInputType, + + + /** + * @ngdoc inputType + * @name ng.directive:input.checkbox + * + * @description + * HTML checkbox. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} ngTrueValue The value to which the expression should be set when selected. + * @param {string=} ngFalseValue The value to which the expression should be set when not selected. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
+ Value1:
+ Value2:
+ value1 = {{value1}}
+ value2 = {{value2}}
+
+
+ + it('should change state', function() { + expect(binding('value1')).toEqual('true'); + expect(binding('value2')).toEqual('YES'); + + input('value1').check(); + input('value2').check(); + expect(binding('value1')).toEqual('false'); + expect(binding('value2')).toEqual('NO'); + }); + +
+ */ + 'checkbox': checkboxInputType, + + 'hidden': noop, + 'button': noop, + 'submit': noop, + 'reset': noop +}; + + +function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // In composition mode, users are still inputing intermediate text buffer, + // hold the listener until composition is done. + // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent + var composing = false; + + element.on('compositionstart', function() { + composing = true; + }); + + element.on('compositionend', function() { + composing = false; + }); + + var listener = function() { + if (composing) return; + var value = element.val(); + + // By default we will trim the value + // If the attribute ng-trim exists we will avoid trimming + // e.g. + if (toBoolean(attr.ngTrim || 'T')) { + value = trim(value); + } + + if (ctrl.$viewValue !== value) { + scope.$apply(function() { + ctrl.$setViewValue(value); + }); + } + }; + + // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the + // input event on backspace, delete or cut + if ($sniffer.hasEvent('input')) { + element.on('input', listener); + } else { + var timeout; + + var deferListener = function() { + if (!timeout) { + timeout = $browser.defer(function() { + listener(); + timeout = null; + }); + } + }; + + element.on('keydown', function(event) { + var key = event.keyCode; + + // ignore + // command modifiers arrows + if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; + + deferListener(); + }); + + // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it + if ($sniffer.hasEvent('paste')) { + element.on('paste cut', deferListener); + } + } + + // if user paste into input using mouse on older browser + // or form autocomplete on newer browser, we need "change" event to catch it + element.on('change', listener); + + ctrl.$render = function() { + element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); + }; + + // pattern validator + var pattern = attr.ngPattern, + patternValidator, + match; + + var validate = function(regexp, value) { + if (ctrl.$isEmpty(value) || regexp.test(value)) { + ctrl.$setValidity('pattern', true); + return value; + } else { + ctrl.$setValidity('pattern', false); + return undefined; + } + }; + + if (pattern) { + match = pattern.match(/^\/(.*)\/([gim]*)$/); + if (match) { + pattern = new RegExp(match[1], match[2]); + patternValidator = function(value) { + return validate(pattern, value); + }; + } else { + patternValidator = function(value) { + var patternObj = scope.$eval(pattern); + + if (!patternObj || !patternObj.test) { + throw minErr('ngPattern')('noregexp', + 'Expected {0} to be a RegExp but was {1}. Element: {2}', pattern, + patternObj, startingTag(element)); + } + return validate(patternObj, value); + }; + } + + ctrl.$formatters.push(patternValidator); + ctrl.$parsers.push(patternValidator); + } + + // min length validator + if (attr.ngMinlength) { + var minlength = int(attr.ngMinlength); + var minLengthValidator = function(value) { + if (!ctrl.$isEmpty(value) && value.length < minlength) { + ctrl.$setValidity('minlength', false); + return undefined; + } else { + ctrl.$setValidity('minlength', true); + return value; + } + }; + + ctrl.$parsers.push(minLengthValidator); + ctrl.$formatters.push(minLengthValidator); + } + + // max length validator + if (attr.ngMaxlength) { + var maxlength = int(attr.ngMaxlength); + var maxLengthValidator = function(value) { + if (!ctrl.$isEmpty(value) && value.length > maxlength) { + ctrl.$setValidity('maxlength', false); + return undefined; + } else { + ctrl.$setValidity('maxlength', true); + return value; + } + }; + + ctrl.$parsers.push(maxLengthValidator); + ctrl.$formatters.push(maxLengthValidator); + } +} + +function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { + textInputType(scope, element, attr, ctrl, $sniffer, $browser); + + ctrl.$parsers.push(function(value) { + var empty = ctrl.$isEmpty(value); + if (empty || NUMBER_REGEXP.test(value)) { + ctrl.$setValidity('number', true); + return value === '' ? null : (empty ? value : parseFloat(value)); + } else { + ctrl.$setValidity('number', false); + return undefined; + } + }); + + ctrl.$formatters.push(function(value) { + return ctrl.$isEmpty(value) ? '' : '' + value; + }); + + if (attr.min) { + var minValidator = function(value) { + var min = parseFloat(attr.min); + if (!ctrl.$isEmpty(value) && value < min) { + ctrl.$setValidity('min', false); + return undefined; + } else { + ctrl.$setValidity('min', true); + return value; + } + }; + + ctrl.$parsers.push(minValidator); + ctrl.$formatters.push(minValidator); + } + + if (attr.max) { + var maxValidator = function(value) { + var max = parseFloat(attr.max); + if (!ctrl.$isEmpty(value) && value > max) { + ctrl.$setValidity('max', false); + return undefined; + } else { + ctrl.$setValidity('max', true); + return value; + } + }; + + ctrl.$parsers.push(maxValidator); + ctrl.$formatters.push(maxValidator); + } + + ctrl.$formatters.push(function(value) { + + if (ctrl.$isEmpty(value) || isNumber(value)) { + ctrl.$setValidity('number', true); + return value; + } else { + ctrl.$setValidity('number', false); + return undefined; + } + }); +} + +function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { + textInputType(scope, element, attr, ctrl, $sniffer, $browser); + + var urlValidator = function(value) { + if (ctrl.$isEmpty(value) || URL_REGEXP.test(value)) { + ctrl.$setValidity('url', true); + return value; + } else { + ctrl.$setValidity('url', false); + return undefined; + } + }; + + ctrl.$formatters.push(urlValidator); + ctrl.$parsers.push(urlValidator); +} + +function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { + textInputType(scope, element, attr, ctrl, $sniffer, $browser); + + var emailValidator = function(value) { + if (ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value)) { + ctrl.$setValidity('email', true); + return value; + } else { + ctrl.$setValidity('email', false); + return undefined; + } + }; + + ctrl.$formatters.push(emailValidator); + ctrl.$parsers.push(emailValidator); +} + +function radioInputType(scope, element, attr, ctrl) { + // make the name unique, if not defined + if (isUndefined(attr.name)) { + element.attr('name', nextUid()); + } + + element.on('click', function() { + if (element[0].checked) { + scope.$apply(function() { + ctrl.$setViewValue(attr.value); + }); + } + }); + + ctrl.$render = function() { + var value = attr.value; + element[0].checked = (value == ctrl.$viewValue); + }; + + attr.$observe('value', ctrl.$render); +} + +function checkboxInputType(scope, element, attr, ctrl) { + var trueValue = attr.ngTrueValue, + falseValue = attr.ngFalseValue; + + if (!isString(trueValue)) trueValue = true; + if (!isString(falseValue)) falseValue = false; + + element.on('click', function() { + scope.$apply(function() { + ctrl.$setViewValue(element[0].checked); + }); + }); + + ctrl.$render = function() { + element[0].checked = ctrl.$viewValue; + }; + + // Override the standard `$isEmpty` because a value of `false` means empty in a checkbox. + ctrl.$isEmpty = function(value) { + return value !== trueValue; + }; + + ctrl.$formatters.push(function(value) { + return value === trueValue; + }); + + ctrl.$parsers.push(function(value) { + return value ? trueValue : falseValue; + }); +} + + +/** + * @ngdoc directive + * @name ng.directive:textarea + * @restrict E + * + * @description + * HTML textarea element control with angular data-binding. The data-binding and validation + * properties of this element are exactly the same as those of the + * {@link ng.directive:input input element}. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. + * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the + * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for + * patterns defined as scope expressions. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + */ + + +/** + * @ngdoc directive + * @name ng.directive:input + * @restrict E + * + * @description + * HTML input element control with angular data-binding. Input control follows HTML5 input types + * and polyfills the HTML5 validation behavior for older browsers. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {boolean=} ngRequired Sets `required` attribute if set to true + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. + * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the + * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for + * patterns defined as scope expressions. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
+
+ User name: + + Required!
+ Last name: + + Too short! + + Too long!
+
+
+ user = {{user}}
+ myForm.userName.$valid = {{myForm.userName.$valid}}
+ myForm.userName.$error = {{myForm.userName.$error}}
+ myForm.lastName.$valid = {{myForm.lastName.$valid}}
+ myForm.lastName.$error = {{myForm.lastName.$error}}
+ myForm.$valid = {{myForm.$valid}}
+ myForm.$error.required = {{!!myForm.$error.required}}
+ myForm.$error.minlength = {{!!myForm.$error.minlength}}
+ myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
+
+
+ + it('should initialize to model', function() { + expect(binding('user')).toEqual('{"name":"guest","last":"visitor"}'); + expect(binding('myForm.userName.$valid')).toEqual('true'); + expect(binding('myForm.$valid')).toEqual('true'); + }); + + it('should be invalid if empty when required', function() { + input('user.name').enter(''); + expect(binding('user')).toEqual('{"last":"visitor"}'); + expect(binding('myForm.userName.$valid')).toEqual('false'); + expect(binding('myForm.$valid')).toEqual('false'); + }); + + it('should be valid if empty when min length is set', function() { + input('user.last').enter(''); + expect(binding('user')).toEqual('{"name":"guest","last":""}'); + expect(binding('myForm.lastName.$valid')).toEqual('true'); + expect(binding('myForm.$valid')).toEqual('true'); + }); + + it('should be invalid if less than required min length', function() { + input('user.last').enter('xx'); + expect(binding('user')).toEqual('{"name":"guest"}'); + expect(binding('myForm.lastName.$valid')).toEqual('false'); + expect(binding('myForm.lastName.$error')).toMatch(/minlength/); + expect(binding('myForm.$valid')).toEqual('false'); + }); + + it('should be invalid if longer than max length', function() { + input('user.last').enter('some ridiculously long name'); + expect(binding('user')) + .toEqual('{"name":"guest"}'); + expect(binding('myForm.lastName.$valid')).toEqual('false'); + expect(binding('myForm.lastName.$error')).toMatch(/maxlength/); + expect(binding('myForm.$valid')).toEqual('false'); + }); + +
+ */ +var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { + return { + restrict: 'E', + require: '?ngModel', + link: function(scope, element, attr, ctrl) { + if (ctrl) { + (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer, + $browser); + } + } + }; +}]; + +var VALID_CLASS = 'ng-valid', + INVALID_CLASS = 'ng-invalid', + PRISTINE_CLASS = 'ng-pristine', + DIRTY_CLASS = 'ng-dirty'; + +/** + * @ngdoc object + * @name ng.directive:ngModel.NgModelController + * + * @property {string} $viewValue Actual string value in the view. + * @property {*} $modelValue The value in the model, that the control is bound to. + * @property {Array.} $parsers Array of functions to execute, as a pipeline, whenever + the control reads value from the DOM. Each function is called, in turn, passing the value + through to the next. Used to sanitize / convert the value as well as validation. + For validation, the parsers should update the validity state using + {@link ng.directive:ngModel.NgModelController#methods_$setValidity $setValidity()}, + and return `undefined` for invalid values. + + * + * @property {Array.} $formatters Array of functions to execute, as a pipeline, whenever + the model value changes. Each function is called, in turn, passing the value through to the + next. Used to format / convert values for display in the control and validation. + *
+ *      function formatter(value) {
+ *        if (value) {
+ *          return value.toUpperCase();
+ *        }
+ *      }
+ *      ngModel.$formatters.push(formatter);
+ *      
+ * + * @property {Array.} $viewChangeListeners Array of functions to execute whenever the + * view value has changed. It is called with no arguments, and its return value is ignored. + * This can be used in place of additional $watches against the model value. + * + * @property {Object} $error An object hash with all errors as keys. + * + * @property {boolean} $pristine True if user has not interacted with the control yet. + * @property {boolean} $dirty True if user has already interacted with the control. + * @property {boolean} $valid True if there is no error. + * @property {boolean} $invalid True if at least one error on the control. + * + * @description + * + * `NgModelController` provides API for the `ng-model` directive. The controller contains + * services for data-binding, validation, CSS updates, and value formatting and parsing. It + * purposefully does not contain any logic which deals with DOM rendering or listening to + * DOM events. Such DOM related logic should be provided by other directives which make use of + * `NgModelController` for data-binding. + * + * ## Custom Control Example + * This example shows how to use `NgModelController` with a custom control to achieve + * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) + * collaborate together to achieve the desired result. + * + * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element + * contents be edited in place by the user. This will not work on older browsers. + * + * + + [contenteditable] { + border: 1px solid black; + background-color: white; + min-height: 20px; + } + + .ng-invalid { + border: 1px solid red; + } + + + + angular.module('customControl', []). + directive('contenteditable', function() { + return { + restrict: 'A', // only activate on element attribute + require: '?ngModel', // get a hold of NgModelController + link: function(scope, element, attrs, ngModel) { + if(!ngModel) return; // do nothing if no ng-model + + // Specify how UI should be updated + ngModel.$render = function() { + element.html(ngModel.$viewValue || ''); + }; + + // Listen for change events to enable binding + element.on('blur keyup change', function() { + scope.$apply(read); + }); + read(); // initialize + + // Write data to the model + function read() { + var html = element.html(); + // When we clear the content editable the browser leaves a
behind + // If strip-br attribute is provided then we strip this out + if( attrs.stripBr && html == '
' ) { + html = ''; + } + ngModel.$setViewValue(html); + } + } + }; + }); +
+ +
+
Change me!
+ Required! +
+ +
+
+ + it('should data-bind and become invalid', function() { + var contentEditable = element('[contenteditable]'); + + expect(contentEditable.text()).toEqual('Change me!'); + input('userContent').enter(''); + expect(contentEditable.text()).toEqual(''); + expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/); + }); + + *
+ * + * ## Isolated Scope Pitfall + * + * Note that if you have a directive with an isolated scope, you cannot require `ngModel` + * since the model value will be looked up on the isolated scope rather than the outer scope. + * When the directive updates the model value, calling `ngModel.$setViewValue()` the property + * on the outer scope will not be updated. However you can get around this by using $parent. + * + * Here is an example of this situation. You'll notice that the first div is not updating the input. + * However the second div can update the input properly. + * + * + + angular.module('badIsolatedDirective', []).directive('isolate', function() { + return { + require: 'ngModel', + scope: { }, + template: '', + link: function(scope, element, attrs, ngModel) { + scope.$watch('innerModel', function(value) { + console.log(value); + ngModel.$setViewValue(value); + }); + } + }; + }); + + + +
+
+
+ *
+ * + * + */ +var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', + function($scope, $exceptionHandler, $attr, $element, $parse) { + this.$viewValue = Number.NaN; + this.$modelValue = Number.NaN; + this.$parsers = []; + this.$formatters = []; + this.$viewChangeListeners = []; + this.$pristine = true; + this.$dirty = false; + this.$valid = true; + this.$invalid = false; + this.$name = $attr.name; + + var ngModelGet = $parse($attr.ngModel), + ngModelSet = ngModelGet.assign; + + if (!ngModelSet) { + throw minErr('ngModel')('nonassign', "Expression '{0}' is non-assignable. Element: {1}", + $attr.ngModel, startingTag($element)); + } + + /** + * @ngdoc function + * @name ng.directive:ngModel.NgModelController#$render + * @methodOf ng.directive:ngModel.NgModelController + * + * @description + * Called when the view needs to be updated. It is expected that the user of the ng-model + * directive will implement this method. + */ + this.$render = noop; + + /** + * @ngdoc function + * @name { ng.directive:ngModel.NgModelController#$isEmpty + * @methodOf ng.directive:ngModel.NgModelController + * + * @description + * This is called when we need to determine if the value of the input is empty. + * + * For instance, the required directive does this to work out if the input has data or not. + * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`. + * + * You can override this for input directives whose concept of being empty is different to the + * default. The `checkboxInputType` directive does this because in its case a value of `false` + * implies empty. + */ + this.$isEmpty = function(value) { + return isUndefined(value) || value === '' || value === null || value !== value; + }; + + var parentForm = $element.inheritedData('$formController') || nullFormCtrl, + invalidCount = 0, // used to easily determine if we are valid + $error = this.$error = {}; // keep invalid keys here + + + // Setup initial state of the control + $element.addClass(PRISTINE_CLASS); + toggleValidCss(true); + + // convenience method for easy toggling of classes + function toggleValidCss(isValid, validationErrorKey) { + validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; + $element. + removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey). + addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey); + } + + /** + * @ngdoc function + * @name ng.directive:ngModel.NgModelController#$setValidity + * @methodOf ng.directive:ngModel.NgModelController + * + * @description + * Change the validity state, and notifies the form when the control changes validity. (i.e. it + * does not notify form if given validator is already marked as invalid). + * + * This method should be called by validators - i.e. the parser or formatter functions. + * + * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign + * to `$error[validationErrorKey]=isValid` so that it is available for data-binding. + * The `validationErrorKey` should be in camelCase and will get converted into dash-case + * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` + * class and can be bound to as `{{someForm.someControl.$error.myError}}` . + * @param {boolean} isValid Whether the current state is valid (true) or invalid (false). + */ + this.$setValidity = function(validationErrorKey, isValid) { + // Purposeful use of ! here to cast isValid to boolean in case it is undefined + // jshint -W018 + if ($error[validationErrorKey] === !isValid) return; + // jshint +W018 + + if (isValid) { + if ($error[validationErrorKey]) invalidCount--; + if (!invalidCount) { + toggleValidCss(true); + this.$valid = true; + this.$invalid = false; + } + } else { + toggleValidCss(false); + this.$invalid = true; + this.$valid = false; + invalidCount++; + } + + $error[validationErrorKey] = !isValid; + toggleValidCss(isValid, validationErrorKey); + + parentForm.$setValidity(validationErrorKey, isValid, this); + }; + + /** + * @ngdoc function + * @name ng.directive:ngModel.NgModelController#$setPristine + * @methodOf ng.directive:ngModel.NgModelController + * + * @description + * Sets the control to its pristine state. + * + * This method can be called to remove the 'ng-dirty' class and set the control to its pristine + * state (ng-pristine class). + */ + this.$setPristine = function () { + this.$dirty = false; + this.$pristine = true; + $element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS); + }; + + /** + * @ngdoc function + * @name ng.directive:ngModel.NgModelController#$setViewValue + * @methodOf ng.directive:ngModel.NgModelController + * + * @description + * Update the view value. + * + * This method should be called when the view value changes, typically from within a DOM event handler. + * For example {@link ng.directive:input input} and + * {@link ng.directive:select select} directives call it. + * + * It will update the $viewValue, then pass this value through each of the functions in `$parsers`, + * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to + * `$modelValue` and the **expression** specified in the `ng-model` attribute. + * + * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called. + * + * Note that calling this function does not trigger a `$digest`. + * + * @param {string} value Value from the view. + */ + this.$setViewValue = function(value) { + this.$viewValue = value; + + // change to dirty + if (this.$pristine) { + this.$dirty = true; + this.$pristine = false; + $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS); + parentForm.$setDirty(); + } + + forEach(this.$parsers, function(fn) { + value = fn(value); + }); + + if (this.$modelValue !== value) { + this.$modelValue = value; + ngModelSet($scope, value); + forEach(this.$viewChangeListeners, function(listener) { + try { + listener(); + } catch(e) { + $exceptionHandler(e); + } + }); + } + }; + + // model -> value + var ctrl = this; + + $scope.$watch(function ngModelWatch() { + var value = ngModelGet($scope); + + // if scope model value and ngModel value are out of sync + if (ctrl.$modelValue !== value) { + + var formatters = ctrl.$formatters, + idx = formatters.length; + + ctrl.$modelValue = value; + while(idx--) { + value = formatters[idx](value); + } + + if (ctrl.$viewValue !== value) { + ctrl.$viewValue = value; + ctrl.$render(); + } + } + }); +}]; + + +/** + * @ngdoc directive + * @name ng.directive:ngModel + * + * @element input + * + * @description + * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a + * property on the scope using {@link ng.directive:ngModel.NgModelController NgModelController}, + * which is created and exposed by this directive. + * + * `ngModel` is responsible for: + * + * - Binding the view into the model, which other directives such as `input`, `textarea` or `select` + * require. + * - Providing validation behavior (i.e. required, number, email, url). + * - Keeping the state of the control (valid/invalid, dirty/pristine, validation errors). + * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`). + * - Registering the control with its parent {@link ng.directive:form form}. + * + * Note: `ngModel` will try to bind to the property given by evaluating the expression on the + * current scope. If the property doesn't already exist on this scope, it will be created + * implicitly and added to the scope. + * + * For best practices on using `ngModel`, see: + * + * - {@link https://github.com/angular/angular.js/wiki/Understanding-Scopes} + * + * For basic examples, how to use `ngModel`, see: + * + * - {@link ng.directive:input input} + * - {@link ng.directive:input.text text} + * - {@link ng.directive:input.checkbox checkbox} + * - {@link ng.directive:input.radio radio} + * - {@link ng.directive:input.number number} + * - {@link ng.directive:input.email email} + * - {@link ng.directive:input.url url} + * - {@link ng.directive:select select} + * - {@link ng.directive:textarea textarea} + * + */ +var ngModelDirective = function() { + return { + require: ['ngModel', '^?form'], + controller: NgModelController, + link: function(scope, element, attr, ctrls) { + // notify others, especially parent forms + + var modelCtrl = ctrls[0], + formCtrl = ctrls[1] || nullFormCtrl; + + formCtrl.$addControl(modelCtrl); + + scope.$on('$destroy', function() { + formCtrl.$removeControl(modelCtrl); + }); + } + }; +}; + + +/** + * @ngdoc directive + * @name ng.directive:ngChange + * + * @description + * Evaluate given expression when user changes the input. + * The expression is not evaluated when the value change is coming from the model. + * + * Note, this directive requires `ngModel` to be present. + * + * @element input + * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change + * in input value. + * + * @example + * + * + * + *
+ * + * + *
+ * debug = {{confirmed}}
+ * counter = {{counter}} + *
+ *
+ * + * it('should evaluate the expression if changing from view', function() { + * expect(binding('counter')).toEqual('0'); + * element('#ng-change-example1').click(); + * expect(binding('counter')).toEqual('1'); + * expect(binding('confirmed')).toEqual('true'); + * }); + * + * it('should not evaluate the expression if changing from model', function() { + * element('#ng-change-example2').click(); + * expect(binding('counter')).toEqual('0'); + * expect(binding('confirmed')).toEqual('true'); + * }); + * + *
+ */ +var ngChangeDirective = valueFn({ + require: 'ngModel', + link: function(scope, element, attr, ctrl) { + ctrl.$viewChangeListeners.push(function() { + scope.$eval(attr.ngChange); + }); + } +}); + + +var requiredDirective = function() { + return { + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + attr.required = true; // force truthy in case we are on non input element + + var validator = function(value) { + if (attr.required && ctrl.$isEmpty(value)) { + ctrl.$setValidity('required', false); + return; + } else { + ctrl.$setValidity('required', true); + return value; + } + }; + + ctrl.$formatters.push(validator); + ctrl.$parsers.unshift(validator); + + attr.$observe('required', function() { + validator(ctrl.$viewValue); + }); + } + }; +}; + + +/** + * @ngdoc directive + * @name ng.directive:ngList + * + * @description + * Text input that converts between a delimited string and an array of strings. The delimiter + * can be a fixed string (by default a comma) or a regular expression. + * + * @element input + * @param {string=} ngList optional delimiter that should be used to split the value. If + * specified in form `/something/` then the value will be converted into a regular expression. + * + * @example + + + +
+ List: + + Required! +
+ names = {{names}}
+ myForm.namesInput.$valid = {{myForm.namesInput.$valid}}
+ myForm.namesInput.$error = {{myForm.namesInput.$error}}
+ myForm.$valid = {{myForm.$valid}}
+ myForm.$error.required = {{!!myForm.$error.required}}
+
+
+ + it('should initialize to model', function() { + expect(binding('names')).toEqual('["igor","misko","vojta"]'); + expect(binding('myForm.namesInput.$valid')).toEqual('true'); + expect(element('span.error').css('display')).toBe('none'); + }); + + it('should be invalid if empty', function() { + input('names').enter(''); + expect(binding('names')).toEqual(''); + expect(binding('myForm.namesInput.$valid')).toEqual('false'); + expect(element('span.error').css('display')).not().toBe('none'); + }); + +
+ */ +var ngListDirective = function() { + return { + require: 'ngModel', + link: function(scope, element, attr, ctrl) { + var match = /\/(.*)\//.exec(attr.ngList), + separator = match && new RegExp(match[1]) || attr.ngList || ','; + + var parse = function(viewValue) { + // If the viewValue is invalid (say required but empty) it will be `undefined` + if (isUndefined(viewValue)) return; + + var list = []; + + if (viewValue) { + forEach(viewValue.split(separator), function(value) { + if (value) list.push(trim(value)); + }); + } + + return list; + }; + + ctrl.$parsers.push(parse); + ctrl.$formatters.push(function(value) { + if (isArray(value)) { + return value.join(', '); + } + + return undefined; + }); + + // Override the standard $isEmpty because an empty array means the input is empty. + ctrl.$isEmpty = function(value) { + return !value || !value.length; + }; + } + }; +}; + + +var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; +/** + * @ngdoc directive + * @name ng.directive:ngValue + * + * @description + * Binds the given expression to the value of `input[select]` or `input[radio]`, so + * that when the element is selected, the `ngModel` of that element is set to the + * bound value. + * + * `ngValue` is useful when dynamically generating lists of radio buttons using `ng-repeat`, as + * shown below. + * + * @element input + * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute + * of the `input` element + * + * @example + + + +
+

Which is your favorite?

+ + +
You chose {{my.favorite}}
+
+
+ + it('should initialize to model', function() { + expect(binding('my.favorite')).toEqual('unicorns'); + }); + it('should bind the values to the inputs', function() { + input('my.favorite').select('pizza'); + expect(binding('my.favorite')).toEqual('pizza'); + }); + +
+ */ +var ngValueDirective = function() { + return { + priority: 100, + compile: function(tpl, tplAttr) { + if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) { + return function ngValueConstantLink(scope, elm, attr) { + attr.$set('value', scope.$eval(attr.ngValue)); + }; + } else { + return function ngValueLink(scope, elm, attr) { + scope.$watch(attr.ngValue, function valueWatchAction(value) { + attr.$set('value', value); + }); + }; + } + } + }; +}; + +/** + * @ngdoc directive + * @name ng.directive:ngBind + * @restrict AC + * + * @description + * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element + * with the value of a given expression, and to update the text content when the value of that + * expression changes. + * + * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like + * `{{ expression }}` which is similar but less verbose. + * + * It is preferrable to use `ngBind` instead of `{{ expression }}` when a template is momentarily + * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an + * element attribute, it makes the bindings invisible to the user while the page is loading. + * + * An alternative solution to this problem would be using the + * {@link ng.directive:ngCloak ngCloak} directive. + * + * + * @element ANY + * @param {expression} ngBind {@link guide/expression Expression} to evaluate. + * + * @example + * Enter a name in the Live Preview text box; the greeting below the text box changes instantly. + + + +
+ Enter name:
+ Hello ! +
+
+ + it('should check ng-bind', function() { + expect(using('.doc-example-live').binding('name')).toBe('Whirled'); + using('.doc-example-live').input('name').enter('world'); + expect(using('.doc-example-live').binding('name')).toBe('world'); + }); + +
+ */ +var ngBindDirective = ngDirective(function(scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.ngBind); + scope.$watch(attr.ngBind, function ngBindWatchAction(value) { + // We are purposefully using == here rather than === because we want to + // catch when value is "null or undefined" + // jshint -W041 + element.text(value == undefined ? '' : value); + }); +}); + + +/** + * @ngdoc directive + * @name ng.directive:ngBindTemplate + * + * @description + * The `ngBindTemplate` directive specifies that the element + * text content should be replaced with the interpolation of the template + * in the `ngBindTemplate` attribute. + * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}` + * expressions. This directive is needed since some HTML elements + * (such as TITLE and OPTION) cannot contain SPAN elements. + * + * @element ANY + * @param {string} ngBindTemplate template of form + * {{ expression }} to eval. + * + * @example + * Try it here: enter text in text box and watch the greeting change. + + + +
+ Salutation:
+ Name:
+

+       
+
+ + it('should check ng-bind', function() { + expect(using('.doc-example-live').binding('salutation')). + toBe('Hello'); + expect(using('.doc-example-live').binding('name')). + toBe('World'); + using('.doc-example-live').input('salutation').enter('Greetings'); + using('.doc-example-live').input('name').enter('user'); + expect(using('.doc-example-live').binding('salutation')). + toBe('Greetings'); + expect(using('.doc-example-live').binding('name')). + toBe('user'); + }); + +
+ */ +var ngBindTemplateDirective = ['$interpolate', function($interpolate) { + return function(scope, element, attr) { + // TODO: move this to scenario runner + var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate)); + element.addClass('ng-binding').data('$binding', interpolateFn); + attr.$observe('ngBindTemplate', function(value) { + element.text(value); + }); + }; +}]; + + +/** + * @ngdoc directive + * @name ng.directive:ngBindHtml + * + * @description + * Creates a binding that will innerHTML the result of evaluating the `expression` into the current + * element in a secure way. By default, the innerHTML-ed content will be sanitized using the {@link + * ngSanitize.$sanitize $sanitize} service. To utilize this functionality, ensure that `$sanitize` + * is available, for example, by including {@link ngSanitize} in your module's dependencies (not in + * core Angular.) You may also bypass sanitization for values you know are safe. To do so, bind to + * an explicitly trusted value via {@link ng.$sce#methods_trustAsHtml $sce.trustAsHtml}. See the example + * under {@link ng.$sce#Example Strict Contextual Escaping (SCE)}. + * + * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you + * will have an exception (instead of an exploit.) + * + * @element ANY + * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate. + * + * @example + Try it here: enter text in text box and watch the greeting change. + + + +
+

+
+
+ + + angular.module('ngBindHtmlExample', ['ngSanitize']) + + .controller('ngBindHtmlCtrl', ['$scope', function ngBindHtmlCtrl($scope) { + $scope.myHTML = + 'I am an HTMLstring with links! and other stuff'; + }]); + + + + it('should check ng-bind-html', function() { + expect(using('.doc-example-live').binding('myHTML')). + toBe( + 'I am an HTMLstring with links! and other stuff' + ); + }); + +
+ */ +var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) { + return function(scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.ngBindHtml); + + var parsed = $parse(attr.ngBindHtml); + function getStringValue() { return (parsed(scope) || '').toString(); } + + scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) { + element.html($sce.getTrustedHtml(parsed(scope)) || ''); + }); + }; +}]; + +function classDirective(name, selector) { + name = 'ngClass' + name; + return function() { + return { + restrict: 'AC', + link: function(scope, element, attr) { + var oldVal; + + scope.$watch(attr[name], ngClassWatchAction, true); + + attr.$observe('class', function(value) { + ngClassWatchAction(scope.$eval(attr[name])); + }); + + + if (name !== 'ngClass') { + scope.$watch('$index', function($index, old$index) { + // jshint bitwise: false + var mod = $index & 1; + if (mod !== old$index & 1) { + var classes = flattenClasses(scope.$eval(attr[name])); + mod === selector ? + attr.$addClass(classes) : + attr.$removeClass(classes); + } + }); + } + + + function ngClassWatchAction(newVal) { + if (selector === true || scope.$index % 2 === selector) { + var newClasses = flattenClasses(newVal || ''); + if(!oldVal) { + attr.$addClass(newClasses); + } else if(!equals(newVal,oldVal)) { + attr.$updateClass(newClasses, flattenClasses(oldVal)); + } + } + oldVal = copy(newVal); + } + + + function flattenClasses(classVal) { + if(isArray(classVal)) { + return classVal.join(' '); + } else if (isObject(classVal)) { + var classes = [], i = 0; + forEach(classVal, function(v, k) { + if (v) { + classes.push(k); + } + }); + return classes.join(' '); + } + + return classVal; + } + } + }; + }; +} + +/** + * @ngdoc directive + * @name ng.directive:ngClass + * @restrict AC + * + * @description + * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding + * an expression that represents all classes to be added. + * + * The directive won't add duplicate classes if a particular class was already set. + * + * When the expression changes, the previously added classes are removed and only then the + * new classes are added. + * + * @animations + * add - happens just before the class is applied to the element + * remove - happens just before the class is removed from the element + * + * @element ANY + * @param {expression} ngClass {@link guide/expression Expression} to eval. The result + * of the evaluation can be a string representing space delimited class + * names, an array, or a map of class names to boolean values. In the case of a map, the + * names of the properties whose values are truthy will be added as css classes to the + * element. + * + * @example Example that demonstrates basic bindings via ngClass directive. + + +

Map Syntax Example

+ deleted (apply "strike" class)
+ important (apply "bold" class)
+ error (apply "red" class) +
+

Using String Syntax

+ +
+

Using Array Syntax

+
+
+
+
+ + .strike { + text-decoration: line-through; + } + .bold { + font-weight: bold; + } + .red { + color: red; + } + + + it('should let you toggle the class', function() { + + expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/bold/); + expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/red/); + + input('important').check(); + expect(element('.doc-example-live p:first').prop('className')).toMatch(/bold/); + + input('error').check(); + expect(element('.doc-example-live p:first').prop('className')).toMatch(/red/); + }); + + it('should let you toggle string example', function() { + expect(element('.doc-example-live p:nth-of-type(2)').prop('className')).toBe(''); + input('style').enter('red'); + expect(element('.doc-example-live p:nth-of-type(2)').prop('className')).toBe('red'); + }); + + it('array example should have 3 classes', function() { + expect(element('.doc-example-live p:last').prop('className')).toBe(''); + input('style1').enter('bold'); + input('style2').enter('strike'); + input('style3').enter('red'); + expect(element('.doc-example-live p:last').prop('className')).toBe('bold strike red'); + }); + +
+ + ## Animations + + The example below demonstrates how to perform animations using ngClass. + + + + + +
+ Sample Text +
+ + .base-class { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + } + + .base-class.my-class { + color: red; + font-size:3em; + } + + + it('should check ng-class', function() { + expect(element('.doc-example-live span').prop('className')).not(). + toMatch(/my-class/); + + using('.doc-example-live').element(':button:first').click(); + + expect(element('.doc-example-live span').prop('className')). + toMatch(/my-class/); + + using('.doc-example-live').element(':button:last').click(); + + expect(element('.doc-example-live span').prop('className')).not(). + toMatch(/my-class/); + }); + +
+ + + ## ngClass and pre-existing CSS3 Transitions/Animations + The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure. + Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder + any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure + to view the step by step details of {@link ngAnimate.$animate#methods_addclass $animate.addClass} and + {@link ngAnimate.$animate#methods_removeclass $animate.removeClass}. + */ +var ngClassDirective = classDirective('', true); + +/** + * @ngdoc directive + * @name ng.directive:ngClassOdd + * @restrict AC + * + * @description + * The `ngClassOdd` and `ngClassEven` directives work exactly as + * {@link ng.directive:ngClass ngClass}, except they work in + * conjunction with `ngRepeat` and take effect only on odd (even) rows. + * + * This directive can be applied only within the scope of an + * {@link ng.directive:ngRepeat ngRepeat}. + * + * @element ANY + * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result + * of the evaluation can be a string representing space delimited class names or an array. + * + * @example + + +
    +
  1. + + {{name}} + +
  2. +
+
+ + .odd { + color: red; + } + .even { + color: blue; + } + + + it('should check ng-class-odd and ng-class-even', function() { + expect(element('.doc-example-live li:first span').prop('className')). + toMatch(/odd/); + expect(element('.doc-example-live li:last span').prop('className')). + toMatch(/even/); + }); + +
+ */ +var ngClassOddDirective = classDirective('Odd', 0); + +/** + * @ngdoc directive + * @name ng.directive:ngClassEven + * @restrict AC + * + * @description + * The `ngClassOdd` and `ngClassEven` directives work exactly as + * {@link ng.directive:ngClass ngClass}, except they work in + * conjunction with `ngRepeat` and take effect only on odd (even) rows. + * + * This directive can be applied only within the scope of an + * {@link ng.directive:ngRepeat ngRepeat}. + * + * @element ANY + * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The + * result of the evaluation can be a string representing space delimited class names or an array. + * + * @example + + +
    +
  1. + + {{name}}       + +
  2. +
+
+ + .odd { + color: red; + } + .even { + color: blue; + } + + + it('should check ng-class-odd and ng-class-even', function() { + expect(element('.doc-example-live li:first span').prop('className')). + toMatch(/odd/); + expect(element('.doc-example-live li:last span').prop('className')). + toMatch(/even/); + }); + +
+ */ +var ngClassEvenDirective = classDirective('Even', 1); + +/** + * @ngdoc directive + * @name ng.directive:ngCloak + * @restrict AC + * + * @description + * The `ngCloak` directive is used to prevent the Angular html template from being briefly + * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this + * directive to avoid the undesirable flicker effect caused by the html template display. + * + * The directive can be applied to the `` element, but the preferred usage is to apply + * multiple `ngCloak` directives to small portions of the page to permit progressive rendering + * of the browser view. + * + * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and + * `angular.min.js`. + * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * + *
+ * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
+ *   display: none !important;
+ * }
+ * 
+ * + * When this css rule is loaded by the browser, all html elements (including their children) that + * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive + * during the compilation of the template it deletes the `ngCloak` element attribute, making + * the compiled element visible. + * + * For the best result, the `angular.js` script must be loaded in the head section of the html + * document; alternatively, the css rule above must be included in the external stylesheet of the + * application. + * + * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they + * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css + * class `ngCloak` in addition to the `ngCloak` directive as shown in the example below. + * + * @element ANY + * + * @example + + +
{{ 'hello' }}
+
{{ 'hello IE7' }}
+
+ + it('should remove the template directive and css class', function() { + expect(element('.doc-example-live #template1').attr('ng-cloak')). + not().toBeDefined(); + expect(element('.doc-example-live #template2').attr('ng-cloak')). + not().toBeDefined(); + }); + +
+ * + */ +var ngCloakDirective = ngDirective({ + compile: function(element, attr) { + attr.$set('ngCloak', undefined); + element.removeClass('ng-cloak'); + } +}); + +/** + * @ngdoc directive + * @name ng.directive:ngController + * + * @description + * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular + * supports the principles behind the Model-View-Controller design pattern. + * + * MVC components in angular: + * + * * Model — The Model is scope properties; scopes are attached to the DOM where scope properties + * are accessed through bindings. + * * View — The template (HTML with data bindings) that is rendered into the View. + * * Controller — The `ngController` directive specifies a Controller class; the class contains business + * logic behind the application to decorate the scope with functions and values + * + * Note that you can also attach controllers to the DOM by declaring it in a route definition + * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller + * again using `ng-controller` in the template itself. This will cause the controller to be attached + * and executed twice. + * + * @element ANY + * @scope + * @param {expression} ngController Name of a globally accessible constructor function or an + * {@link guide/expression expression} that on the current scope evaluates to a + * constructor function. The controller instance can be published into a scope property + * by specifying `as propertyName`. + * + * @example + * Here is a simple form for editing user contact information. Adding, removing, clearing, and + * greeting are methods declared on the controller (see source tab). These methods can + * easily be called from the angular markup. Notice that the scope becomes the `this` for the + * controller's instance. This allows for easy access to the view data from the controller. Also + * notice that any changes to the data are automatically reflected in the View without the need + * for a manual update. The example is shown in two different declaration styles you may use + * according to preference. + + + +
+ Name: + [ greet ]
+ Contact: +
    +
  • + + + [ clear + | X ] +
  • +
  • [ add ]
  • +
+
+
+ + it('should check controller as', function() { + expect(element('#ctrl-as-exmpl>:input').val()).toBe('John Smith'); + expect(element('#ctrl-as-exmpl li:nth-child(1) input').val()) + .toBe('408 555 1212'); + expect(element('#ctrl-as-exmpl li:nth-child(2) input').val()) + .toBe('john.smith@example.org'); + + element('#ctrl-as-exmpl li:first a:contains("clear")').click(); + expect(element('#ctrl-as-exmpl li:first input').val()).toBe(''); + + element('#ctrl-as-exmpl li:last a:contains("add")').click(); + expect(element('#ctrl-as-exmpl li:nth-child(3) input').val()) + .toBe('yourname@example.org'); + }); + +
+ + + +
+ Name: + [ greet ]
+ Contact: +
    +
  • + + + [ clear + | X ] +
  • +
  • [ add ]
  • +
+
+
+ + it('should check controller', function() { + expect(element('#ctrl-exmpl>:input').val()).toBe('John Smith'); + expect(element('#ctrl-exmpl li:nth-child(1) input').val()) + .toBe('408 555 1212'); + expect(element('#ctrl-exmpl li:nth-child(2) input').val()) + .toBe('john.smith@example.org'); + + element('#ctrl-exmpl li:first a:contains("clear")').click(); + expect(element('#ctrl-exmpl li:first input').val()).toBe(''); + + element('#ctrl-exmpl li:last a:contains("add")').click(); + expect(element('#ctrl-exmpl li:nth-child(3) input').val()) + .toBe('yourname@example.org'); + }); + +
+ + */ +var ngControllerDirective = [function() { + return { + scope: true, + controller: '@', + priority: 500 + }; +}]; + +/** + * @ngdoc directive + * @name ng.directive:ngCsp + * + * @element html + * @description + * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support. + * + * This is necessary when developing things like Google Chrome Extensions. + * + * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things). + * For us to be compatible, we just need to implement the "getterFn" in $parse without violating + * any of these restrictions. + * + * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp` + * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will + * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will + * be raised. + * + * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically + * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}). + * To make those directives work in CSP mode, include the `angular-csp.css` manually. + * + * In order to use this feature put the `ngCsp` directive on the root element of the application. + * + * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.* + * + * @example + * This example shows how to apply the `ngCsp` directive to the `html` tag. +
+     
+     
+     ...
+     ...
+     
+   
+ */ + +// ngCsp is not implemented as a proper directive any more, because we need it be processed while we bootstrap +// the system (before $parse is instantiated), for this reason we just have a csp() fn that looks for ng-csp attribute +// anywhere in the current doc + +/** + * @ngdoc directive + * @name ng.directive:ngClick + * + * @description + * The ngClick directive allows you to specify custom behavior when + * an element is clicked. + * + * @element ANY + * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon + * click. (Event object is available as `$event`) + * + * @example + + + + count: {{count}} + + + it('should check ng-click', function() { + expect(binding('count')).toBe('0'); + element('.doc-example-live :button').click(); + expect(binding('count')).toBe('1'); + }); + + + */ +/* + * A directive that allows creation of custom onclick handlers that are defined as angular + * expressions and are compiled and executed within the current scope. + * + * Events that are handled via these handler are always configured not to propagate further. + */ +var ngEventDirectives = {}; +forEach( + 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '), + function(name) { + var directiveName = directiveNormalize('ng-' + name); + ngEventDirectives[directiveName] = ['$parse', function($parse) { + return { + compile: function($element, attr) { + var fn = $parse(attr[directiveName]); + return function(scope, element, attr) { + element.on(lowercase(name), function(event) { + scope.$apply(function() { + fn(scope, {$event:event}); + }); + }); + }; + } + }; + }]; + } +); + +/** + * @ngdoc directive + * @name ng.directive:ngDblclick + * + * @description + * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event. + * + * @element ANY + * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon + * a dblclick. (The Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngMousedown + * + * @description + * The ngMousedown directive allows you to specify custom behavior on mousedown event. + * + * @element ANY + * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon + * mousedown. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngMouseup + * + * @description + * Specify custom behavior on mouseup event. + * + * @element ANY + * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon + * mouseup. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + +/** + * @ngdoc directive + * @name ng.directive:ngMouseover + * + * @description + * Specify custom behavior on mouseover event. + * + * @element ANY + * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon + * mouseover. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngMouseenter + * + * @description + * Specify custom behavior on mouseenter event. + * + * @element ANY + * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon + * mouseenter. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngMouseleave + * + * @description + * Specify custom behavior on mouseleave event. + * + * @element ANY + * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon + * mouseleave. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngMousemove + * + * @description + * Specify custom behavior on mousemove event. + * + * @element ANY + * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon + * mousemove. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngKeydown + * + * @description + * Specify custom behavior on keydown event. + * + * @element ANY + * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon + * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngKeyup + * + * @description + * Specify custom behavior on keyup event. + * + * @element ANY + * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon + * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngKeypress + * + * @description + * Specify custom behavior on keypress event. + * + * @element ANY + * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon + * keypress. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + + +/** + * @ngdoc directive + * @name ng.directive:ngSubmit + * + * @description + * Enables binding angular expressions to onsubmit events. + * + * Additionally it prevents the default action (which for form means sending the request to the + * server and reloading the current page) **but only if the form does not contain an `action` + * attribute**. + * + * @element form + * @param {expression} ngSubmit {@link guide/expression Expression} to eval. (Event object is available as `$event`) + * + * @example + + + +
+ Enter text and hit enter: + + +
list={{list}}
+
+
+ + it('should check ng-submit', function() { + expect(binding('list')).toBe('[]'); + element('.doc-example-live #submit').click(); + expect(binding('list')).toBe('["hello"]'); + expect(input('text').val()).toBe(''); + }); + it('should ignore empty strings', function() { + expect(binding('list')).toBe('[]'); + element('.doc-example-live #submit').click(); + element('.doc-example-live #submit').click(); + expect(binding('list')).toBe('["hello"]'); + }); + +
+ */ + +/** + * @ngdoc directive + * @name ng.directive:ngFocus + * + * @description + * Specify custom behavior on focus event. + * + * @element window, input, select, textarea, a + * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon + * focus. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + +/** + * @ngdoc directive + * @name ng.directive:ngBlur + * + * @description + * Specify custom behavior on blur event. + * + * @element window, input, select, textarea, a + * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon + * blur. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + +/** + * @ngdoc directive + * @name ng.directive:ngCopy + * + * @description + * Specify custom behavior on copy event. + * + * @element window, input, select, textarea, a + * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon + * copy. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + +/** + * @ngdoc directive + * @name ng.directive:ngCut + * + * @description + * Specify custom behavior on cut event. + * + * @element window, input, select, textarea, a + * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon + * cut. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + +/** + * @ngdoc directive + * @name ng.directive:ngPaste + * + * @description + * Specify custom behavior on paste event. + * + * @element window, input, select, textarea, a + * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon + * paste. (Event object is available as `$event`) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ + +/** + * @ngdoc directive + * @name ng.directive:ngIf + * @restrict A + * + * @description + * The `ngIf` directive removes or recreates a portion of the DOM tree based on an + * {expression}. If the expression assigned to `ngIf` evaluates to a false + * value then the element is removed from the DOM, otherwise a clone of the + * element is reinserted into the DOM. + * + * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the + * element in the DOM rather than changing its visibility via the `display` css property. A common + * case when this difference is significant is when using css selectors that rely on an element's + * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes. + * + * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope + * is created when the element is restored. The scope created within `ngIf` inherits from + * its parent scope using + * {@link https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance prototypal inheritance}. + * An important implication of this is if `ngModel` is used within `ngIf` to bind to + * a javascript primitive defined in the parent scope. In this case any modifications made to the + * variable within the child scope will override (hide) the value in the parent scope. + * + * Also, `ngIf` recreates elements using their compiled state. An example of this behavior + * is if an element's class attribute is directly modified after it's compiled, using something like + * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element + * the added class will be lost because the original compiled state is used to regenerate the element. + * + * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter` + * and `leave` effects. + * + * @animations + * enter - happens just after the ngIf contents change and a new DOM element is created and injected into the ngIf container + * leave - happens just before the ngIf contents are removed from the DOM + * + * @element ANY + * @scope + * @priority 600 + * @param {expression} ngIf If the {@link guide/expression expression} is falsy then + * the element is removed from the DOM tree. If it is truthy a copy of the compiled + * element is added to the DOM tree. + * + * @example + + + Click me:
+ Show when checked: + + I'm removed when the checkbox is unchecked. + +
+ + .animate-if { + background:white; + border:1px solid black; + padding:10px; + } + + /* + The transition styles can also be placed on the CSS base class above + */ + .animate-if.ng-enter, .animate-if.ng-leave { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + } + + .animate-if.ng-enter, + .animate-if.ng-leave.ng-leave-active { + opacity:0; + } + + .animate-if.ng-leave, + .animate-if.ng-enter.ng-enter-active { + opacity:1; + } + +
+ */ +var ngIfDirective = ['$animate', function($animate) { + return { + transclude: 'element', + priority: 600, + terminal: true, + restrict: 'A', + $$tlb: true, + link: function ($scope, $element, $attr, ctrl, $transclude) { + var block, childScope; + $scope.$watch($attr.ngIf, function ngIfWatchAction(value) { + + if (toBoolean(value)) { + if (!childScope) { + childScope = $scope.$new(); + $transclude(childScope, function (clone) { + block = { + startNode: clone[0], + endNode: clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ') + }; + $animate.enter(clone, $element.parent(), $element); + }); + } + } else { + + if (childScope) { + childScope.$destroy(); + childScope = null; + } + + if (block) { + $animate.leave(getBlockElements(block)); + block = null; + } + } + }); + } + }; +}]; + +/** + * @ngdoc directive + * @name ng.directive:ngInclude + * @restrict ECA + * + * @description + * Fetches, compiles and includes an external HTML fragment. + * + * By default, the template URL is restricted to the same domain and protocol as the + * application document. This is done by calling {@link ng.$sce#methods_getTrustedResourceUrl + * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols + * you may either {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelist them} or + * {@link ng.$sce#methods_trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link + * ng.$sce Strict Contextual Escaping}. + * + * In addition, the browser's + * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest + * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing + * (CORS)} policy may further restrict whether the template is successfully loaded. + * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://` + * access on some browsers. + * + * @animations + * enter - animation is used to bring new content into the browser. + * leave - animation is used to animate existing content away. + * + * The enter and leave animation occur concurrently. + * + * @scope + * @priority 400 + * + * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant, + * make sure you wrap it in quotes, e.g. `src="'myPartialTemplate.html'"`. + * @param {string=} onload Expression to evaluate when a new partial is loaded. + * + * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll + * $anchorScroll} to scroll the viewport after the content is loaded. + * + * - If the attribute is not set, disable scrolling. + * - If the attribute is set without value, enable scrolling. + * - Otherwise enable scrolling only if the expression evaluates to truthy value. + * + * @example + + +
+ + url of the template: {{template.url}} +
+
+
+
+
+
+ + function Ctrl($scope) { + $scope.templates = + [ { name: 'template1.html', url: 'template1.html'} + , { name: 'template2.html', url: 'template2.html'} ]; + $scope.template = $scope.templates[0]; + } + + + Content of template1.html + + + Content of template2.html + + + .slide-animate-container { + position:relative; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .slide-animate { + padding:10px; + } + + .slide-animate.ng-enter, .slide-animate.ng-leave { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + display:block; + padding:10px; + } + + .slide-animate.ng-enter { + top:-50px; + } + .slide-animate.ng-enter.ng-enter-active { + top:0; + } + + .slide-animate.ng-leave { + top:0; + } + .slide-animate.ng-leave.ng-leave-active { + top:50px; + } + + + it('should load template1.html', function() { + expect(element('.doc-example-live [ng-include]').text()). + toMatch(/Content of template1.html/); + }); + it('should load template2.html', function() { + select('template').option('1'); + expect(element('.doc-example-live [ng-include]').text()). + toMatch(/Content of template2.html/); + }); + it('should change to blank', function() { + select('template').option(''); + expect(element('.doc-example-live [ng-include]')).toBe(undefined); + }); + +
+ */ + + +/** + * @ngdoc event + * @name ng.directive:ngInclude#$includeContentRequested + * @eventOf ng.directive:ngInclude + * @eventType emit on the scope ngInclude was declared in + * @description + * Emitted every time the ngInclude content is requested. + */ + + +/** + * @ngdoc event + * @name ng.directive:ngInclude#$includeContentLoaded + * @eventOf ng.directive:ngInclude + * @eventType emit on the current ngInclude scope + * @description + * Emitted every time the ngInclude content is reloaded. + */ +var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', '$animate', '$sce', + function($http, $templateCache, $anchorScroll, $compile, $animate, $sce) { + return { + restrict: 'ECA', + priority: 400, + terminal: true, + transclude: 'element', + compile: function(element, attr) { + var srcExp = attr.ngInclude || attr.src, + onloadExp = attr.onload || '', + autoScrollExp = attr.autoscroll; + + return function(scope, $element, $attr, ctrl, $transclude) { + var changeCounter = 0, + currentScope, + currentElement; + + var cleanupLastIncludeContent = function() { + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if(currentElement) { + $animate.leave(currentElement); + currentElement = null; + } + }; + + scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) { + var afterAnimation = function() { + if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }; + var thisChangeId = ++changeCounter; + + if (src) { + $http.get(src, {cache: $templateCache}).success(function(response) { + if (thisChangeId !== changeCounter) return; + var newScope = scope.$new(); + + // Note: This will also link all children of ng-include that were contained in the original + // html. If that content contains controllers, ... they could pollute/change the scope. + // However, using ng-include on an element with additional content does not make sense... + // Note: We can't remove them in the cloneAttchFn of $transclude as that + // function is called before linking the content, which would apply child + // directives to non existing elements. + var clone = $transclude(newScope, noop); + cleanupLastIncludeContent(); + + currentScope = newScope; + currentElement = clone; + + currentElement.html(response); + $animate.enter(currentElement, null, $element, afterAnimation); + $compile(currentElement.contents())(currentScope); + currentScope.$emit('$includeContentLoaded'); + scope.$eval(onloadExp); + }).error(function() { + if (thisChangeId === changeCounter) cleanupLastIncludeContent(); + }); + scope.$emit('$includeContentRequested'); + } else { + cleanupLastIncludeContent(); + } + }); + }; + } + }; +}]; + +/** + * @ngdoc directive + * @name ng.directive:ngInit + * @restrict AC + * + * @description + * The `ngInit` directive allows you to evaluate an expression in the + * current scope. + * + *
+ * The only appropriate use of `ngInit` for aliasing special properties of + * {@link api/ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you + * should use {@link guide/controller controllers} rather than `ngInit` + * to initialize values on a scope. + *
+ * + * @element ANY + * @param {expression} ngInit {@link guide/expression Expression} to eval. + * + * @example + + + +
+
+
+ list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}}; +
+
+
+
+ + it('should alias index positions', function() { + expect(element('.example-init').text()) + .toBe('list[ 0 ][ 0 ] = a;' + + 'list[ 0 ][ 1 ] = b;' + + 'list[ 1 ][ 0 ] = c;' + + 'list[ 1 ][ 1 ] = d;'); + }); + +
+ */ +var ngInitDirective = ngDirective({ + compile: function() { + return { + pre: function(scope, element, attrs) { + scope.$eval(attrs.ngInit); + } + }; + } +}); + +/** + * @ngdoc directive + * @name ng.directive:ngNonBindable + * @restrict AC + * @priority 1000 + * + * @description + * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current + * DOM element. This is useful if the element contains what appears to be Angular directives and + * bindings but which should be ignored by Angular. This could be the case if you have a site that + * displays snippets of code, for instance. + * + * @element ANY + * + * @example + * In this example there are two locations where a simple interpolation binding (`{{}}`) is present, + * but the one wrapped in `ngNonBindable` is left alone. + * + * @example + + +
Normal: {{1 + 2}}
+
Ignored: {{1 + 2}}
+
+ + it('should check ng-non-bindable', function() { + expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); + expect(using('.doc-example-live').element('div:last').text()). + toMatch(/1 \+ 2/); + }); + +
+ */ +var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); + +/** + * @ngdoc directive + * @name ng.directive:ngPluralize + * @restrict EA + * + * @description + * # Overview + * `ngPluralize` is a directive that displays messages according to en-US localization rules. + * These rules are bundled with angular.js, but can be overridden + * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive + * by specifying the mappings between + * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html + * plural categories} and the strings to be displayed. + * + * # Plural categories and explicit number rules + * There are two + * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html + * plural categories} in Angular's default en-US locale: "one" and "other". + * + * While a plural category may match many numbers (for example, in en-US locale, "other" can match + * any number that is not 1), an explicit number rule can only match one number. For example, the + * explicit number rule for "3" matches the number 3. There are examples of plural categories + * and explicit number rules throughout the rest of this documentation. + * + * # Configuring ngPluralize + * You configure ngPluralize by providing 2 attributes: `count` and `when`. + * You can also provide an optional attribute, `offset`. + * + * The value of the `count` attribute can be either a string or an {@link guide/expression + * Angular expression}; these are evaluated on the current scope for its bound value. + * + * The `when` attribute specifies the mappings between plural categories and the actual + * string to be displayed. The value of the attribute should be a JSON object. + * + * The following example shows how to configure ngPluralize: + * + *
+ * 
+ * 
+ *
+ * + * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not + * specify this rule, 0 would be matched to the "other" category and "0 people are viewing" + * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for + * other numbers, for example 12, so that instead of showing "12 people are viewing", you can + * show "a dozen people are viewing". + * + * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted + * into pluralized strings. In the previous example, Angular will replace `{}` with + * `{{personCount}}`. The closed braces `{}` is a placeholder + * for {{numberExpression}}. + * + * # Configuring ngPluralize with offset + * The `offset` attribute allows further customization of pluralized text, which can result in + * a better user experience. For example, instead of the message "4 people are viewing this document", + * you might display "John, Kate and 2 others are viewing this document". + * The offset attribute allows you to offset a number by any desired value. + * Let's take a look at an example: + * + *
+ * 
+ * 
+ * 
+ * + * Notice that we are still using two plural categories(one, other), but we added + * three explicit number rules 0, 1 and 2. + * When one person, perhaps John, views the document, "John is viewing" will be shown. + * When three people view the document, no explicit number rule is found, so + * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category. + * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing" + * is shown. + * + * Note that when you specify offsets, you must provide explicit number rules for + * numbers from 0 up to and including the offset. If you use an offset of 3, for example, + * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for + * plural categories "one" and "other". + * + * @param {string|expression} count The variable to be bounded to. + * @param {string} when The mapping between plural category to its corresponding strings. + * @param {number=} offset Offset to deduct from the total number. + * + * @example + + + +
+ Person 1:
+ Person 2:
+ Number of People:
+ + + Without Offset: + +
+ + + With Offset(2): + + +
+
+ + it('should show correct pluralized string', function() { + expect(element('.doc-example-live ng-pluralize:first').text()). + toBe('1 person is viewing.'); + expect(element('.doc-example-live ng-pluralize:last').text()). + toBe('Igor is viewing.'); + + using('.doc-example-live').input('personCount').enter('0'); + expect(element('.doc-example-live ng-pluralize:first').text()). + toBe('Nobody is viewing.'); + expect(element('.doc-example-live ng-pluralize:last').text()). + toBe('Nobody is viewing.'); + + using('.doc-example-live').input('personCount').enter('2'); + expect(element('.doc-example-live ng-pluralize:first').text()). + toBe('2 people are viewing.'); + expect(element('.doc-example-live ng-pluralize:last').text()). + toBe('Igor and Misko are viewing.'); + + using('.doc-example-live').input('personCount').enter('3'); + expect(element('.doc-example-live ng-pluralize:first').text()). + toBe('3 people are viewing.'); + expect(element('.doc-example-live ng-pluralize:last').text()). + toBe('Igor, Misko and one other person are viewing.'); + + using('.doc-example-live').input('personCount').enter('4'); + expect(element('.doc-example-live ng-pluralize:first').text()). + toBe('4 people are viewing.'); + expect(element('.doc-example-live ng-pluralize:last').text()). + toBe('Igor, Misko and 2 other people are viewing.'); + }); + + it('should show data-binded names', function() { + using('.doc-example-live').input('personCount').enter('4'); + expect(element('.doc-example-live ng-pluralize:last').text()). + toBe('Igor, Misko and 2 other people are viewing.'); + + using('.doc-example-live').input('person1').enter('Di'); + using('.doc-example-live').input('person2').enter('Vojta'); + expect(element('.doc-example-live ng-pluralize:last').text()). + toBe('Di, Vojta and 2 other people are viewing.'); + }); + +
+ */ +var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) { + var BRACE = /{}/g; + return { + restrict: 'EA', + link: function(scope, element, attr) { + var numberExp = attr.count, + whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs + offset = attr.offset || 0, + whens = scope.$eval(whenExp) || {}, + whensExpFns = {}, + startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + isWhen = /^when(Minus)?(.+)$/; + + forEach(attr, function(expression, attributeName) { + if (isWhen.test(attributeName)) { + whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] = + element.attr(attr.$attr[attributeName]); + } + }); + forEach(whens, function(expression, key) { + whensExpFns[key] = + $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' + + offset + endSymbol)); + }); + + scope.$watch(function ngPluralizeWatch() { + var value = parseFloat(scope.$eval(numberExp)); + + if (!isNaN(value)) { + //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise, + //check it against pluralization rules in $locale service + if (!(value in whens)) value = $locale.pluralCat(value - offset); + return whensExpFns[value](scope, element, true); + } else { + return ''; + } + }, function ngPluralizeWatchAction(newVal) { + element.text(newVal); + }); + } + }; +}]; + +/** + * @ngdoc directive + * @name ng.directive:ngRepeat + * + * @description + * The `ngRepeat` directive instantiates a template once per item from a collection. Each template + * instance gets its own scope, where the given loop variable is set to the current collection item, + * and `$index` is set to the item index or key. + * + * Special properties are exposed on the local scope of each template instance, including: + * + * | Variable | Type | Details | + * |-----------|-----------------|-----------------------------------------------------------------------------| + * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) | + * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. | + * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. | + * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. | + * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). | + * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). | + * + * + * # Special repeat start and end points + * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending + * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively. + * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on) + * up to and including the ending HTML tag where **ng-repeat-end** is placed. + * + * The example below makes use of this feature: + *
+ *   
+ * Header {{ item }} + *
+ *
+ * Body {{ item }} + *
+ *
+ * Footer {{ item }} + *
+ *
+ * + * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to: + *
+ *   
+ * Header A + *
+ *
+ * Body A + *
+ *
+ * Footer A + *
+ *
+ * Header B + *
+ *
+ * Body B + *
+ *
+ * Footer B + *
+ *
+ * + * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such + * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**). + * + * @animations + * enter - when a new item is added to the list or when an item is revealed after a filter + * leave - when an item is removed from the list or when an item is filtered out + * move - when an adjacent item is filtered out causing a reorder or when the item contents are reordered + * + * @element ANY + * @scope + * @priority 1000 + * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These + * formats are currently supported: + * + * * `variable in expression` – where variable is the user defined loop variable and `expression` + * is a scope expression giving the collection to enumerate. + * + * For example: `album in artist.albums`. + * + * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers, + * and `expression` is the scope expression giving the collection to enumerate. + * + * For example: `(name, age) in {'adam':10, 'amalie':12}`. + * + * * `variable in expression track by tracking_expression` – You can also provide an optional tracking function + * which can be used to associate the objects in the collection with the DOM elements. If no tracking function + * is specified the ng-repeat associates elements by identity in the collection. It is an error to have + * more than one tracking function to resolve to the same key. (This would mean that two distinct objects are + * mapped to the same DOM element, which is not possible.) Filters should be applied to the expression, + * before specifying a tracking expression. + * + * For example: `item in items` is equivalent to `item in items track by $id(item)'. This implies that the DOM elements + * will be associated by item identity in the array. + * + * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique + * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements + * with the corresponding item in the array by identity. Moving the same object in array would move the DOM + * element in the same way in the DOM. + * + * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this + * case the object identity does not matter. Two objects are considered equivalent as long as their `id` + * property is same. + * + * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter + * to items in conjunction with a tracking expression. + * + * @example + * This example initializes the scope to a list of names and + * then uses `ngRepeat` to display every person: + + +
+ I have {{friends.length}} friends. They are: + +
    +
  • + [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. +
  • +
+
+
+ + .example-animate-container { + background:white; + border:1px solid black; + list-style:none; + margin:0; + padding:0 10px; + } + + .animate-repeat { + line-height:40px; + list-style:none; + box-sizing:border-box; + } + + .animate-repeat.ng-move, + .animate-repeat.ng-enter, + .animate-repeat.ng-leave { + -webkit-transition:all linear 0.5s; + transition:all linear 0.5s; + } + + .animate-repeat.ng-leave.ng-leave-active, + .animate-repeat.ng-move, + .animate-repeat.ng-enter { + opacity:0; + max-height:0; + } + + .animate-repeat.ng-leave, + .animate-repeat.ng-move.ng-move-active, + .animate-repeat.ng-enter.ng-enter-active { + opacity:1; + max-height:40px; + } + + + it('should render initial data set', function() { + var r = using('.doc-example-live').repeater('ul li'); + expect(r.count()).toBe(10); + expect(r.row(0)).toEqual(["1","John","25"]); + expect(r.row(1)).toEqual(["2","Jessie","30"]); + expect(r.row(9)).toEqual(["10","Samantha","60"]); + expect(binding('friends.length')).toBe("10"); + }); + + it('should update repeater when filter predicate changes', function() { + var r = using('.doc-example-live').repeater('ul li'); + expect(r.count()).toBe(10); + + input('q').enter('ma'); + + expect(r.count()).toBe(2); + expect(r.row(0)).toEqual(["1","Mary","28"]); + expect(r.row(1)).toEqual(["2","Samantha","60"]); + }); + +
+ */ +var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { + var NG_REMOVED = '$$NG_REMOVED'; + var ngRepeatMinErr = minErr('ngRepeat'); + return { + transclude: 'element', + priority: 1000, + terminal: true, + $$tlb: true, + link: function($scope, $element, $attr, ctrl, $transclude){ + var expression = $attr.ngRepeat; + var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/), + trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn, + lhs, rhs, valueIdentifier, keyIdentifier, + hashFnLocals = {$id: hashKey}; + + if (!match) { + throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", + expression); + } + + lhs = match[1]; + rhs = match[2]; + trackByExp = match[4]; + + if (trackByExp) { + trackByExpGetter = $parse(trackByExp); + trackByIdExpFn = function(key, value, index) { + // assign key, value, and $index to the locals so that they can be used in hash functions + if (keyIdentifier) hashFnLocals[keyIdentifier] = key; + hashFnLocals[valueIdentifier] = value; + hashFnLocals.$index = index; + return trackByExpGetter($scope, hashFnLocals); + }; + } else { + trackByIdArrayFn = function(key, value) { + return hashKey(value); + }; + trackByIdObjFn = function(key) { + return key; + }; + } + + match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/); + if (!match) { + throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.", + lhs); + } + valueIdentifier = match[3] || match[1]; + keyIdentifier = match[2]; + + // Store a list of elements from previous run. This is a hash where key is the item from the + // iterator, and the value is objects with following properties. + // - scope: bound scope + // - element: previous element. + // - index: position + var lastBlockMap = {}; + + //watch props + $scope.$watchCollection(rhs, function ngRepeatAction(collection){ + var index, length, + previousNode = $element[0], // current position of the node + nextNode, + // Same as lastBlockMap but it has the current state. It will become the + // lastBlockMap on the next iteration. + nextBlockMap = {}, + arrayLength, + childScope, + key, value, // key/value of iteration + trackById, + trackByIdFn, + collectionKeys, + block, // last object information {scope, element, id} + nextBlockOrder = [], + elementsToRemove; + + + if (isArrayLike(collection)) { + collectionKeys = collection; + trackByIdFn = trackByIdExpFn || trackByIdArrayFn; + } else { + trackByIdFn = trackByIdExpFn || trackByIdObjFn; + // if object, extract keys, sort them and use to determine order of iteration over obj props + collectionKeys = []; + for (key in collection) { + if (collection.hasOwnProperty(key) && key.charAt(0) != '$') { + collectionKeys.push(key); + } + } + collectionKeys.sort(); + } + + arrayLength = collectionKeys.length; + + // locate existing items + length = nextBlockOrder.length = collectionKeys.length; + for(index = 0; index < length; index++) { + key = (collection === collectionKeys) ? index : collectionKeys[index]; + value = collection[key]; + trackById = trackByIdFn(key, value, index); + assertNotHasOwnProperty(trackById, '`track by` id'); + if(lastBlockMap.hasOwnProperty(trackById)) { + block = lastBlockMap[trackById]; + delete lastBlockMap[trackById]; + nextBlockMap[trackById] = block; + nextBlockOrder[index] = block; + } else if (nextBlockMap.hasOwnProperty(trackById)) { + // restore lastBlockMap + forEach(nextBlockOrder, function(block) { + if (block && block.startNode) lastBlockMap[block.id] = block; + }); + // This is a duplicate and we need to throw an error + throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}", + expression, trackById); + } else { + // new never before seen block + nextBlockOrder[index] = { id: trackById }; + nextBlockMap[trackById] = false; + } + } + + // remove existing items + for (key in lastBlockMap) { + // lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn + if (lastBlockMap.hasOwnProperty(key)) { + block = lastBlockMap[key]; + elementsToRemove = getBlockElements(block); + $animate.leave(elementsToRemove); + forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; }); + block.scope.$destroy(); + } + } + + // we are not using forEach for perf reasons (trying to avoid #call) + for (index = 0, length = collectionKeys.length; index < length; index++) { + key = (collection === collectionKeys) ? index : collectionKeys[index]; + value = collection[key]; + block = nextBlockOrder[index]; + if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode; + + if (block.startNode) { + // if we have already seen this object, then we need to reuse the + // associated scope/element + childScope = block.scope; + + nextNode = previousNode; + do { + nextNode = nextNode.nextSibling; + } while(nextNode && nextNode[NG_REMOVED]); + + if (block.startNode != nextNode) { + // existing item which got moved + $animate.move(getBlockElements(block), null, jqLite(previousNode)); + } + previousNode = block.endNode; + } else { + // new item which we don't know about + childScope = $scope.$new(); + } + + childScope[valueIdentifier] = value; + if (keyIdentifier) childScope[keyIdentifier] = key; + childScope.$index = index; + childScope.$first = (index === 0); + childScope.$last = (index === (arrayLength - 1)); + childScope.$middle = !(childScope.$first || childScope.$last); + // jshint bitwise: false + childScope.$odd = !(childScope.$even = (index&1) === 0); + // jshint bitwise: true + + if (!block.startNode) { + $transclude(childScope, function(clone) { + clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' '); + $animate.enter(clone, null, jqLite(previousNode)); + previousNode = clone; + block.scope = childScope; + block.startNode = previousNode && previousNode.endNode ? previousNode.endNode : clone[0]; + block.endNode = clone[clone.length - 1]; + nextBlockMap[block.id] = block; + }); + } + } + lastBlockMap = nextBlockMap; + }); + } + }; +}]; + +/** + * @ngdoc directive + * @name ng.directive:ngShow + * + * @description + * The `ngShow` directive shows or hides the given HTML element based on the expression + * provided to the ngShow attribute. The element is shown or hidden by removing or adding + * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined + * in AngularJS and sets the display style to none (using an !important flag). + * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * + *
+ * 
+ * 
+ * + * + *
+ *
+ * + * When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute + * on the element causing it to become hidden. When true, the ng-hide CSS class is removed + * from the element causing the element not to appear hidden. + * + * ## Why is !important used? + * + * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector + * can be easily overridden by heavier selectors. For example, something as simple + * as changing the display style on a HTML list item would make hidden elements appear visible. + * This also becomes a bigger issue when dealing with CSS frameworks. + * + * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector + * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the + * styling to change how to hide an element then it is just a matter of using !important in their own CSS code. + * + * ### Overriding .ng-hide + * + * If you wish to change the hide behavior with ngShow/ngHide then this can be achieved by + * restating the styles for the .ng-hide class in CSS: + *
+ * .ng-hide {
+ *   //!annotate CSS Specificity|Not to worry, this will override the AngularJS default...
+ *   display:block!important;
+ *
+ *   //this is just another form of hiding an element
+ *   position:absolute;
+ *   top:-9999px;
+ *   left:-9999px;
+ * }
+ * 
+ * + * Just remember to include the important flag so the CSS override will function. + * + * ## A note about animations with ngShow + * + * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression + * is true and false. This system works like the animation system present with ngClass except that + * you must also include the !important flag to override the display property + * so that you can perform an animation when the element is hidden during the time of the animation. + * + *
+ * //
+ * //a working example can be found at the bottom of this page
+ * //
+ * .my-element.ng-hide-add, .my-element.ng-hide-remove {
+ *   transition:0.5s linear all;
+ *   display:block!important;
+ * }
+ *
+ * .my-element.ng-hide-add { ... }
+ * .my-element.ng-hide-add.ng-hide-add-active { ... }
+ * .my-element.ng-hide-remove { ... }
+ * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
+ * 
+ * + * @animations + * addClass: .ng-hide - happens after the ngShow expression evaluates to a truthy value and the just before contents are set to visible + * removeClass: .ng-hide - happens after the ngShow expression evaluates to a non truthy value and just before the contents are set to hidden + * + * @element ANY + * @param {expression} ngShow If the {@link guide/expression expression} is truthy + * then the element is shown or hidden respectively. + * + * @example + + + Click me:
+
+ Show: +
+ I show up when your checkbox is checked. +
+
+
+ Hide: +
+ I hide when your checkbox is checked. +
+
+
+ + .animate-show { + -webkit-transition:all linear 0.5s; + transition:all linear 0.5s; + line-height:20px; + opacity:1; + padding:10px; + border:1px solid black; + background:white; + } + + .animate-show.ng-hide-add, + .animate-show.ng-hide-remove { + display:block!important; + } + + .animate-show.ng-hide { + line-height:0; + opacity:0; + padding:0 10px; + } + + .check-element { + padding:10px; + border:1px solid black; + background:white; + } + + + it('should check ng-show / ng-hide', function() { + expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); + expect(element('.doc-example-live span:last:visible').count()).toEqual(1); + + input('checked').check(); + + expect(element('.doc-example-live span:first:visible').count()).toEqual(1); + expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); + }); + +
+ */ +var ngShowDirective = ['$animate', function($animate) { + return function(scope, element, attr) { + scope.$watch(attr.ngShow, function ngShowWatchAction(value){ + $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide'); + }); + }; +}]; + + +/** + * @ngdoc directive + * @name ng.directive:ngHide + * + * @description + * The `ngHide` directive shows or hides the given HTML element based on the expression + * provided to the ngHide attribute. The element is shown or hidden by removing or adding + * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined + * in AngularJS and sets the display style to none (using an !important flag). + * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * + *
+ * 
+ * 
+ * + * + *
+ *
+ * + * When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute + * on the element causing it to become hidden. When false, the ng-hide CSS class is removed + * from the element causing the element not to appear hidden. + * + * ## Why is !important used? + * + * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector + * can be easily overridden by heavier selectors. For example, something as simple + * as changing the display style on a HTML list item would make hidden elements appear visible. + * This also becomes a bigger issue when dealing with CSS frameworks. + * + * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector + * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the + * styling to change how to hide an element then it is just a matter of using !important in their own CSS code. + * + * ### Overriding .ng-hide + * + * If you wish to change the hide behavior with ngShow/ngHide then this can be achieved by + * restating the styles for the .ng-hide class in CSS: + *
+ * .ng-hide {
+ *   //!annotate CSS Specificity|Not to worry, this will override the AngularJS default...
+ *   display:block!important;
+ *
+ *   //this is just another form of hiding an element
+ *   position:absolute;
+ *   top:-9999px;
+ *   left:-9999px;
+ * }
+ * 
+ * + * Just remember to include the important flag so the CSS override will function. + * + * ## A note about animations with ngHide + * + * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression + * is true and false. This system works like the animation system present with ngClass, except that + * you must also include the !important flag to override the display property so + * that you can perform an animation when the element is hidden during the time of the animation. + * + *
+ * //
+ * //a working example can be found at the bottom of this page
+ * //
+ * .my-element.ng-hide-add, .my-element.ng-hide-remove {
+ *   transition:0.5s linear all;
+ *   display:block!important;
+ * }
+ *
+ * .my-element.ng-hide-add { ... }
+ * .my-element.ng-hide-add.ng-hide-add-active { ... }
+ * .my-element.ng-hide-remove { ... }
+ * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
+ * 
+ * + * @animations + * removeClass: .ng-hide - happens after the ngHide expression evaluates to a truthy value and just before the contents are set to hidden + * addClass: .ng-hide - happens after the ngHide expression evaluates to a non truthy value and just before the contents are set to visible + * + * @element ANY + * @param {expression} ngHide If the {@link guide/expression expression} is truthy then + * the element is shown or hidden respectively. + * + * @example + + + Click me:
+
+ Show: +
+ I show up when your checkbox is checked. +
+
+
+ Hide: +
+ I hide when your checkbox is checked. +
+
+
+ + .animate-hide { + -webkit-transition:all linear 0.5s; + transition:all linear 0.5s; + line-height:20px; + opacity:1; + padding:10px; + border:1px solid black; + background:white; + } + + .animate-hide.ng-hide-add, + .animate-hide.ng-hide-remove { + display:block!important; + } + + .animate-hide.ng-hide { + line-height:0; + opacity:0; + padding:0 10px; + } + + .check-element { + padding:10px; + border:1px solid black; + background:white; + } + + + it('should check ng-show / ng-hide', function() { + expect(element('.doc-example-live .check-element:first:hidden').count()).toEqual(1); + expect(element('.doc-example-live .check-element:last:visible').count()).toEqual(1); + + input('checked').check(); + + expect(element('.doc-example-live .check-element:first:visible').count()).toEqual(1); + expect(element('.doc-example-live .check-element:last:hidden').count()).toEqual(1); + }); + +
+ */ +var ngHideDirective = ['$animate', function($animate) { + return function(scope, element, attr) { + scope.$watch(attr.ngHide, function ngHideWatchAction(value){ + $animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide'); + }); + }; +}]; + +/** + * @ngdoc directive + * @name ng.directive:ngStyle + * @restrict AC + * + * @description + * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally. + * + * @element ANY + * @param {expression} ngStyle {@link guide/expression Expression} which evals to an + * object whose keys are CSS style names and values are corresponding values for those CSS + * keys. + * + * @example + + + + +
+ Sample Text +
myStyle={{myStyle}}
+
+ + span { + color: black; + } + + + it('should check ng-style', function() { + expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); + element('.doc-example-live :button[value=set]').click(); + expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)'); + element('.doc-example-live :button[value=clear]').click(); + expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); + }); + +
+ */ +var ngStyleDirective = ngDirective(function(scope, element, attr) { + scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { + if (oldStyles && (newStyles !== oldStyles)) { + forEach(oldStyles, function(val, style) { element.css(style, '');}); + } + if (newStyles) element.css(newStyles); + }, true); +}); + +/** + * @ngdoc directive + * @name ng.directive:ngSwitch + * @restrict EA + * + * @description + * The ngSwitch directive is used to conditionally swap DOM structure on your template based on a scope expression. + * Elements within ngSwitch but without ngSwitchWhen or ngSwitchDefault directives will be preserved at the location + * as specified in the template. + * + * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it + * from the template cache), ngSwitch simply choses one of the nested elements and makes it visible based on which element + * matches the value obtained from the evaluated expression. In other words, you define a container element + * (where you place the directive), place an expression on the **on="..." attribute** + * (or the **ng-switch="..." attribute**), define any inner elements inside of the directive and place + * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on + * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default + * attribute is displayed. + * + * @animations + * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container + * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM + * + * @usage + * + * ... + * ... + * ... + * + * + * @scope + * @priority 800 + * @param {*} ngSwitch|on expression to match against ng-switch-when. + * @paramDescription + * On child elements add: + * + * * `ngSwitchWhen`: the case statement to match against. If match then this + * case will be displayed. If the same match appears multiple times, all the + * elements will be displayed. + * * `ngSwitchDefault`: the default case when no other case match. If there + * are multiple default cases, all of them will be displayed when no other + * case match. + * + * + * @example + + +
+ + selection={{selection}} +
+
+
Settings Div
+
Home Span
+
default
+
+
+
+ + function Ctrl($scope) { + $scope.items = ['settings', 'home', 'other']; + $scope.selection = $scope.items[0]; + } + + + .animate-switch-container { + position:relative; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .animate-switch { + padding:10px; + } + + .animate-switch.ng-animate { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + } + + .animate-switch.ng-leave.ng-leave-active, + .animate-switch.ng-enter { + top:-50px; + } + .animate-switch.ng-leave, + .animate-switch.ng-enter.ng-enter-active { + top:0; + } + + + it('should start in settings', function() { + expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/); + }); + it('should change to home', function() { + select('selection').option('home'); + expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/); + }); + it('should select default', function() { + select('selection').option('other'); + expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/); + }); + +
+ */ +var ngSwitchDirective = ['$animate', function($animate) { + return { + restrict: 'EA', + require: 'ngSwitch', + + // asks for $scope to fool the BC controller module + controller: ['$scope', function ngSwitchController() { + this.cases = {}; + }], + link: function(scope, element, attr, ngSwitchController) { + var watchExpr = attr.ngSwitch || attr.on, + selectedTranscludes, + selectedElements, + selectedScopes = []; + + scope.$watch(watchExpr, function ngSwitchWatchAction(value) { + for (var i= 0, ii=selectedScopes.length; i + + +
+
+
+ {{text}} +
+
+ + it('should have transcluded', function() { + input('title').enter('TITLE'); + input('text').enter('TEXT'); + expect(binding('title')).toEqual('TITLE'); + expect(binding('text')).toEqual('TEXT'); + }); + + + * + */ +var ngTranscludeDirective = ngDirective({ + controller: ['$element', '$transclude', function($element, $transclude) { + if (!$transclude) { + throw minErr('ngTransclude')('orphan', + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); + } + + // remember the transclusion fn but call it during linking so that we don't process transclusion before directives on + // the parent element even when the transclusion replaces the current element. (we can't use priority here because + // that applies only to compile fns and not controllers + this.$transclude = $transclude; + }], + + link: function($scope, $element, $attrs, controller) { + controller.$transclude(function(clone) { + $element.html(''); + $element.append(clone); + }); + } +}); + +/** + * @ngdoc directive + * @name ng.directive:script + * @restrict E + * + * @description + * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the + * template can be used by `ngInclude`, `ngView` or directive templates. + * + * @param {'text/ng-template'} type must be set to `'text/ng-template'` + * + * @example + + + + + Load inlined template +
+
+ + it('should load template defined inside script tag', function() { + element('#tpl-link').click(); + expect(element('#tpl-content').text()).toMatch(/Content of the template/); + }); + +
+ */ +var scriptDirective = ['$templateCache', function($templateCache) { + return { + restrict: 'E', + terminal: true, + compile: function(element, attr) { + if (attr.type == 'text/ng-template') { + var templateUrl = attr.id, + // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent + text = element[0].text; + + $templateCache.put(templateUrl, text); + } + } + }; +}]; + +var ngOptionsMinErr = minErr('ngOptions'); +/** + * @ngdoc directive + * @name ng.directive:select + * @restrict E + * + * @description + * HTML `SELECT` element with angular data-binding. + * + * # `ngOptions` + * + * The `ngOptions` attribute can be used to dynamically generate a list of `` + * DOM element. + * * `trackexpr`: Used when working with an array of objects. The result of this expression will be + * used to identify the objects in the array. The `trackexpr` will most likely refer to the + * `value` variable (e.g. `value.propertyName`). + * + * @example + + + +
+
    +
  • + Name: + [X] +
  • +
  • + [add] +
  • +
+
+ Color (null not allowed): +
+ + Color (null allowed): + + +
+ + Color grouped by shade: +
+ + + Select bogus.
+
+ Currently selected: {{ {selected_color:color} }} +
+
+
+
+ + it('should check ng-options', function() { + expect(binding('{selected_color:color}')).toMatch('red'); + select('color').option('0'); + expect(binding('{selected_color:color}')).toMatch('black'); + using('.nullable').select('color').option(''); + expect(binding('{selected_color:color}')).toMatch('null'); + }); + +
+ */ + +var ngOptionsDirective = valueFn({ terminal: true }); +// jshint maxlen: false +var selectDirective = ['$compile', '$parse', function($compile, $parse) { + //0000111110000000000022220000000000000000000000333300000000000000444444444444444000000000555555555555555000000066666666666666600000000000000007777000000000000000000088888 + var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/, + nullModelCtrl = {$setViewValue: noop}; +// jshint maxlen: 100 + + return { + restrict: 'E', + require: ['select', '?ngModel'], + controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) { + var self = this, + optionsMap = {}, + ngModelCtrl = nullModelCtrl, + nullOption, + unknownOption; + + + self.databound = $attrs.ngModel; + + + self.init = function(ngModelCtrl_, nullOption_, unknownOption_) { + ngModelCtrl = ngModelCtrl_; + nullOption = nullOption_; + unknownOption = unknownOption_; + }; + + + self.addOption = function(value) { + assertNotHasOwnProperty(value, '"option value"'); + optionsMap[value] = true; + + if (ngModelCtrl.$viewValue == value) { + $element.val(value); + if (unknownOption.parent()) unknownOption.remove(); + } + }; + + + self.removeOption = function(value) { + if (this.hasOption(value)) { + delete optionsMap[value]; + if (ngModelCtrl.$viewValue == value) { + this.renderUnknownOption(value); + } + } + }; + + + self.renderUnknownOption = function(val) { + var unknownVal = '? ' + hashKey(val) + ' ?'; + unknownOption.val(unknownVal); + $element.prepend(unknownOption); + $element.val(unknownVal); + unknownOption.prop('selected', true); // needed for IE + }; + + + self.hasOption = function(value) { + return optionsMap.hasOwnProperty(value); + }; + + $scope.$on('$destroy', function() { + // disable unknown option so that we don't do work when the whole select is being destroyed + self.renderUnknownOption = noop; + }); + }], + + link: function(scope, element, attr, ctrls) { + // if ngModel is not defined, we don't need to do anything + if (!ctrls[1]) return; + + var selectCtrl = ctrls[0], + ngModelCtrl = ctrls[1], + multiple = attr.multiple, + optionsExp = attr.ngOptions, + nullOption = false, // if false, user will not be able to select it (used by ngOptions) + emptyOption, + // we can't just jqLite('",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
t
",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t +}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("'; +html += '
'; +html += '
from table fragments + if ( !jQuery.support.tbody ) { + + // String was a
'; +html += '
Upload File
'; +html += '
Want to upload multiple files at once? Please upgrade to the latest Flash Player, then reload this page. For some reason our Flash based uploader did not load, so you are currently using our single file uploader.
'; +html += spacer(1,20) + '
'; +var url = zero_client.targetURL; +if (url.indexOf('?') > -1) url += '&'; else url += '?'; +url += 'format=jshtml&onafter=' + escape('window.parent.upload_basic_finish(response);'); +Debug.trace('upload', "Prepping basic upload: " + url); +html += '
'; +html += '
'; +html += '
'; +html += '

'; +html += ''; +html += ''; +html += ''; +html += '
' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('page_white_get.png', 'Upload', "upload_basic_go()") + '
'; +html += '
'; +html += ''; +html += '
'; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +show_popup_dialog(528, 200, html); +} +function upload_basic_go() { +$('f_upload_basic').submit(); +$('d_upload_form').hide(); +$('d_upload_progress').show(); +} +function upload_basic_finish(response) { +Debug.trace('upload', "Basic upload complete: " + dumper(response)); +setTimeout( 'upload_basic_finish_2()', 100 ); +} +function upload_basic_finish_2() { +$('i_upload_basic').src = 'blank.html'; +setTimeout( 'upload_basic_finish_3()', 100 ); +} +function upload_basic_finish_3() { +hide_popup_dialog(); +delete session.progress; +show_progress_dialog( 0, 'Finishing Upload...', true ); +fire_callback( session.upload_callback ); +} +function upload_destroy() { +if (zero_client) { +zero_client.destroy(); +delete ZeroUpload.clients[ zero_client.id ]; +zero_client = null; +} +} +function prep_upload(dom_id, url, callback, types) { +session.upload_callback = callback; +if (url) { +if (url.indexOf('?') > -1) url += '&'; else url += '?'; +url += 'session=' + session.cookie.get('effect_session_id'); +} +upload_destroy(); +zero_client = new ZeroUpload.Client(); +if (url) zero_client.setURL( url ); +zero_client.setHandCursor( true ); +if (types) zero_client.setFileTypes( types[0], types[1] ); +zero_client.addEventListener( 'queueStart', uploadQueueStart ); +zero_client.addEventListener( 'fileStart', uploadFileStart ); +zero_client.addEventListener( 'progress', uploadProgress ); +zero_client.addEventListener( 'fileComplete', uploadFileComplete ); +zero_client.addEventListener( 'queueComplete', uploadQueueComplete ); +zero_client.addEventListener( 'error', uploadError ); +zero_client.addEventListener( 'debug', function(client, eventName, args) { +Debug.trace('upload', "Caught event: " + eventName); +} ); +if (dom_id) { +Debug.trace('upload', "Gluing ZeroUpload to: " + dom_id); +zero_client.glue( dom_id ); +} +} +Class.create( 'Debug', { +__static: { +enabled: false, +categories: { all: 1 }, +buffer: [], +max_rows: 5000, +win: null, +ie: !!navigator.userAgent.match(/MSIE/), +ie6: !!navigator.userAgent.match(/MSIE\D+6/), +init: function() { +Debug.enabled = true; +Debug.trace( 'debug', 'Debug log start' ); +var html = '

'; +if (Debug.ie) { +setTimeout( function() { +document.body.insertAdjacentHTML('beforeEnd', +'
' + html + '
' +); +}, 1000 ); +} +else { +var div = document.createElement('DIV'); +div.id = 'd_debug'; +div.setAttribute('id', 'd_debug'); +div.style.position = Debug.ie6 ? 'absolute' : 'fixed'; +div.style.zIndex = '101'; +div.style.left = '0px'; +div.style.top = '0px'; +div.style.width = '100%'; +div.innerHTML = html; +document.getElementsByTagName('body')[0].appendChild(div); +} +}, +show: function() { +if (!Debug.win || Debug.win.closed) { +Debug.trace('debug', "Opening debug window"); +Debug.win = window.open( '', 'DebugWindow', 'width=600,height=500,menubar=no,resizable=yes,scrollbars=yes,location=no,status=no,toolbar=no,directories=no' ); +if (!Debug.win) return alert("Failed to open window. Popup blocker maybe?"); +var doc = Debug.win.document; +doc.open(); +doc.writeln( 'Debug Log' ); +doc.writeln( '
' ); +doc.writeln( '
' ); +doc.writeln( '
' ); +doc.writeln( '' ); +doc.writeln( '' ); +doc.writeln( '
' ); +doc.writeln( '' ); +doc.close(); +} +Debug.win.focus(); +}, +console_execute: function() { +var cmd = Debug.win.document.getElementById('fe_command'); +if (cmd.value.length) { +Debug.trace( 'console', cmd.value ); +try { +Debug.trace( 'console', '' + eval(cmd.value) ); +} +catch (e) { +Debug.trace( 'error', 'JavaScript Interpreter Exception: ' + e.toString() ); +} +} +}, +get_time_stamp: function(now) { +var date = new Date( now * 1000 ); +var hh = date.getHours(); if (hh < 10) hh = "0" + hh; +var mi = date.getMinutes(); if (mi < 10) mi = "0" + mi; +var ss = date.getSeconds(); if (ss < 10) ss = "0" + ss; +var sss = '' + date.getMilliseconds(); while (sss.length < 3) sss = "0" + sss; +return '' + hh + ':' + mi + ':' + ss + '.' + sss; +}, +refresh_console: function() { +if (!Debug.win || Debug.win.closed) return; +var div = Debug.win.document.getElementById('d_debug_log'); +if (div) { +var row = null; +while ( row = Debug.buffer.shift() ) { +var time_stamp = Debug.get_time_stamp(row.time); +var msg = row.msg; +msg = msg.replace(/\t/g, "    "); +msg = msg.replace(//g, ">"); +msg = msg.replace(/\n/g, "
\n"); +var html = ''; +var sty = 'float:left; font-family: Consolas, Courier, mono; font-size: 12px; cursor:default; margin-right:10px; margin-bottom:1px; padding:2px;'; +html += '
' + time_stamp + '
'; +html += '
' + row.cat + '
'; +html += '
' + msg + '
'; +html += '
'; +var chunk = Debug.win.document.createElement('DIV'); +chunk.style['float'] = 'none'; +chunk.innerHTML = html; +div.appendChild(chunk); +} +var cmd = Debug.win.document.getElementById('fe_command'); +cmd.focus(); +} +Debug.dirty = 0; +Debug.win.scrollTo(0, 99999); +}, +hires_time_now: function() { +var now = new Date(); +return ( now.getTime() / 1000 ); +}, +trace: function(cat, msg) { +if (arguments.length == 1) { +msg = cat; +cat = 'debug'; +} +if (Debug.categories.all || Debug.categories[cat]) { +Debug.buffer.push({ cat: cat, msg: msg, time: Debug.hires_time_now() }); +if (Debug.buffer.length > Debug.max_rows) Debug.buffer.shift(); +if (!Debug.dirty) { +Debug.dirty = 1; +setTimeout( 'Debug.refresh_console();', 1 ); +} +} +} +} +} ); +var session = { +inited: false, +api_mod_cache: {}, +query: parseQueryString( ''+location.search ), +cookie: new CookieTree({ path: '/effect/' }), +storage: {}, +storage_dirty: false, +hooks: { +keys: {} +}, +username: '', +em_width: 11, +audioResourceMatch: /\.mp3$/i, +imageResourceMatch: /\.(jpe|jpeg|jpg|png|gif)$/i, +textResourceMatch: /\.xml$/i, +movieResourceMatch: /\.(flv|mp4|mp4v|mov|3gp|3g2)$/i, +imageResourceMatchString: '\.(jpe|jpeg|jpg|png|gif)$' +}; +session.debug = session.query.debug ? true : false; +var page_manager = null; +var preload_icons = []; +var preload_images = [ +'loading.gif', +'aquaprogressbar.gif', +'aquaprogressbar_bkgnd.gif' +]; +function get_base_url() { +return protocol + '://' + location.hostname + session.config.BaseURI; +} +function effect_init() { +if (session.inited) return; +session.inited = true; +assert( window.config, "Config not loaded" ); +session.config = window.config; +Debug.trace("Starting up"); +rendering_page = false; +preload(); +window.$R = {}; +for (var key in config.RegExpShortcuts) { +$R[key] = new RegExp( config.RegExpShortcuts[key] ); +} +ww_precalc_font("body", "effect_precalc_font_finish"); +page_manager = new Effect.PageManager( config.Pages.Page ); +var session_id = session.cookie.get('effect_session_id'); +if (session_id && session_id.match(/^login/)) { +do_session_recover(); +} +else { +show_default_login_status(); +Nav.init(); +} +Blog.search({ +stag: 'sidebar_docs', +limit: 20, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_documents', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +Blog.search({ +stag: 'sidebar_tutorials', +limit: 5, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_tutorials', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +Blog.search({ +stag: 'sidebar_plugins', +limit: 5, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_plugins', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +$('fe_search_bar').onkeydown = delay_onChange_input_text; +user_storage_idle(); +} +function effect_precalc_font_finish(width, height) { +session.em_width = width; +} +function preload() { +for (var idx = 0, len = preload_icons.length; idx < len; idx++) { +var url = images_uri + '/icons/' + preload_icons[idx] + '.gif'; +preload_icons[idx] = new Image(); +preload_icons[idx].src = url; +} +for (var idx = 0, len = preload_images.length; idx < len; idx++) { +var url = images_uri + '/' + preload_images[idx]; +preload_images[idx] = new Image(); +preload_images[idx].src = url; +} +} +function $P(id) { +if (!id) id = page_manager.current_page_id; +var page = page_manager.find(id); +assert( !!page, "Failed to locate page: " + id ); +return page; +} +function get_pref(name) { +if (!session.user || !session.user.Preferences) return alert("ASSERT FAILURE! Tried to lookup pref " + name + " and user is not yet loaded!"); +return session.user.Preferences[name]; +} +function get_bool_pref(name) { +return (get_pref(name) == 1); +} +function set_pref(name, value) { +session.user.Preferences[name] = value; +} +function set_bool_pref(name, value) { +set_pref(name, value ? '1' : '0'); +} +function save_prefs() { +var prefs_to_save = {}; +if (arguments.length) { +for (var idx = 0, len = arguments.length; idx < len; idx++) { +var key = arguments[idx]; +prefs_to_save[key] = get_pref(key); +} +} +else prefs_to_save = session.user.Preferences; +effect_api_mod_touch('user_get'); +effect_api_send('user_update', { +Username: session.username, +Preferences: prefs_to_save +}, 'save_prefs_2'); +} +function save_prefs_2(response) { +do_message('success', 'Preferences saved.'); +} + +function get_full_name(username) { +var user = session.users[username]; +if (!user) return username; +return user.FullName; +} +function get_buddy_icon_url(username, size) { +var mod = session.api_mod_cache.get_buddy_icon || 0; +if (!size) size = 32; +var url = '/effect/api/get_buddy_icon?username='+username + '&mod=' + mod + '&size=' + size; +return url; +} +function get_buddy_icon_display(username, show_icon, show_name) { +if ((typeof(show_icon) == 'undefined') && get_bool_pref('show_user_icons')) show_icon = 1; +if ((typeof(show_name) == 'undefined') && get_bool_pref('show_user_names')) show_name = 1; +var html = ''; +if (show_icon) html += ''; +if (show_icon && show_name) html += '
'; +if (show_name) html += username; +return html; +} +function do_session_recover() { +session.hooks.after_error = 'do_logout'; +effect_api_send('session_recover', {}, 'do_login_2', { _from_recover: 1 } ); +} +function require_login() { +if (session.user) return true; +Debug.trace('Page requires login, showing login page'); +session.nav_after_login = Nav.currentAnchor(); +setTimeout( function() { +Nav.go( 'Login' ); +}, 1 ); +return false; +} +function popup_window(url, name) { +if (!url) url = ''; +if (!name) name = ''; +var win = window.open(url, name); +if (!win) return alert('Failed to open popup window. If you have a popup blocker, please disable it for this website and try again.'); +return win; +} +function do_login_prompt() { +hide_popup_dialog(); +delete session.progress; +if (!session.temp_password) session.temp_password = ''; +if (!session.username) session.username = ''; +var temp_username = session.open_id || session.username || ''; +var html = ''; +html += '
'; +html += '\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "
'; +html += '
Effect Developer Login
'; +html += '
'; +html += '
Effect Username  or  '+icon('openid', 'OpenID', 'popup_window(\'http://openid.net/\')', 'What is OpenID?')+'


'; +html += '
'; +html += '
'; +html += '

'; +html += ''; +html += ''; +html += ''; +html += '
' + large_icon_button('x', 'Cancel', "clear_login()") + ' ' + large_icon_button('check', 'Login', 'do_login()') + '
'; +html += '
'; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_login'; +session.hooks.keys[ESC_KEY] = 'clear_login'; +safe_focus( 'fe_username' ); +show_popup_dialog(450, 225, html); +} +function do_openid_reg(title, auto_login_button) { +hide_popup_dialog(); +delete session.progress; +if (!title) title = 'Register Account Using OpenID'; +if (typeof(auto_login_button) == 'undefined') auto_login_button = 1; +var html = ''; +html += '
'; +html += '
'; +html += '
'+title+'
'; +html += '
'; +html += '
'+icon('openid', 'Enter Your OpenID URL:')+'
'; +if (auto_login_button) html += '


'; +html += '
'; +html += '

'; +html += ''; +html += ''; +html += ''; +html += '
' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', title.match(/login/i) ? 'Login' : 'Register', 'do_openid_login()') + '
'; +html += '
'; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_openid_login'; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_username' ); +show_popup_dialog(450, 225, html); +} +function do_login_prompt_2() { +hide_popup_dialog(); +delete session.progress; +if (!session.temp_password) session.temp_password = ''; +if (!session.username) session.username = ''; +var html = ''; +html += '
'; +html += '"; + second_cell = ""; + row = $("").attr("id", "s" + index).attr("class", "location_row").html(first_cell + second_cell); + $locationsDiv.append(row); + } + if (index === this.numSearchToDisplay) { + $locationsDiv.append(""); + return $locationsDiv.append(""); + } + }, this); + return this.geocoder.geocode({ + address: address + }, __bind(function(result, status) { + if (status !== "OK") { + $('.error_message').html(t("Search Address Failed")).fadeIn(); + return; + } + _.each(result, showResults); + $("#search_results").html($locationsDiv); + this.locationChange("search"); + this.searchResults = result; + return this.displaySearchLoc(); + }, this)); + }; + ClientsRequestView.prototype.mouseoverLocation = function(e) { + var $el, id, marker; + $el = $(e.currentTarget); + id = $el.attr("id").substring(1); + marker = this.markers[id]; + return marker.setAnimation(google.maps.Animation.BOUNCE); + }; + ClientsRequestView.prototype.mouseoutLocation = function(e) { + var $el, id, marker; + $el = $(e.currentTarget); + id = $el.attr("id").substring(1); + marker = this.markers[id]; + return marker.setAnimation(null); + }; + ClientsRequestView.prototype.searchLocation = function(e) { + e.preventDefault(); + $("#address").val($(e.currentTarget).html()); + return this.searchAddress(); + }; + ClientsRequestView.prototype.favoriteClick = function(e) { + var index, location; + e.preventDefault(); + $(".favorites").attr("href", ""); + index = $(e.currentTarget).removeAttr("href").attr("id"); + location = new google.maps.LatLng(USER.locations[index].latitude, USER.locations[index].longitude); + return this.panToLocation(location); + }; + ClientsRequestView.prototype.clickLocation = function(e) { + var id; + id = $(e.currentTarget).attr("id").substring(1); + return this.panToLocation(this.markers[id].getPosition()); + }; + ClientsRequestView.prototype.panToLocation = function(location) { + this.map.panTo(location); + this.map.setZoom(16); + return this.pickup_icon.setPosition(location); + }; + ClientsRequestView.prototype.locationLinkHandle = function(e) { + var panelName; + e.preventDefault(); + panelName = $(e.currentTarget).attr("id"); + return this.locationChange(panelName); + }; + ClientsRequestView.prototype.locationChange = function(type) { + $(".locations_link").attr("href", "").css("font-weight", "normal"); + switch (type) { + case "favorite": + $(".search_results").attr("href", ""); + $(".locations_link#favorite").removeAttr("href").css("font-weight", "bold"); + $("#search_results").hide(); + $("#favorite_results").fadeIn(); + return this.displayFavLoc(); + case "search": + $(".favorites").attr("href", ""); + $(".locations_link#search").removeAttr("href").css("font-weight", "bold"); + $("#favorite_results").hide(); + $("#search_results").fadeIn(); + return this.displaySearchLoc(); + } + }; + ClientsRequestView.prototype.rateTrip = function(e) { + var rating; + rating = $(e.currentTarget).attr("id"); + $(".stars").attr("src", "/web/img/star_inactive.png"); + return _(rating).times(function(index) { + return $(".stars#" + (index + 1)).attr("src", "/web/img/star_active.png"); + }); + }; + ClientsRequestView.prototype.pickupHandle = function(e) { + var $el, callback, message; + e.preventDefault(); + $el = $(e.currentTarget).find("span"); + switch ($el.html()) { + case t("Request Pickup"): + _.delay(this.requestRide, 3000); + $("#status_message").html(t("Sending pickup request...")); + $el.html(t("Cancel Pickup")).parent().attr("class", "button_red"); + this.pickup_icon.setDraggable(false); + this.map.panTo(this.pickup_icon.getPosition()); + return this.map.setZoom(18); + case t("Cancel Pickup"): + if (this.status === "ready") { + $el.html(t("Request Pickup")).parent().attr("class", "button_green"); + return this.pickup_icon.setDraggable(true); + } else { + callback = __bind(function(v, m, f) { + if (v) { + this.AskDispatch("PickupCanceledClient"); + return this.setStatus("ready"); + } + }, this); + message = t("Cancel Request Prompt"); + if (this.status === "arriving") { + message = 'Cancel Request Arrived Prompt'; + } + return $.prompt(message, { + buttons: { + Ok: true, + Cancel: false + }, + callback: callback + }); + } + } + }; + ClientsRequestView.prototype.requestRide = function() { + if ($("#pickupHandle").find("span").html() === t("Cancel Pickup")) { + this.AskDispatch("Pickup"); + return this.setStatus("searching"); + } + }; + ClientsRequestView.prototype.removeCabs = function() { + _.each(this.cabs, __bind(function(point) { + return point.setMap(null); + }, this)); + return this.cabs = []; + }; + ClientsRequestView.prototype.addToFavLoc = function(e) { + var $el, lat, lng, nickname; + e.preventDefault(); + $el = $(e.currentTarget); + $el.find(".error_message").html(""); + nickname = $el.find("#favLocNickname").val().toString(); + lat = $el.find("#pickupLat").val().toString(); + lng = $el.find("#pickupLng").val().toString(); + if (nickname.length < 3) { + $el.find(".error_message").html(t("Favorite Location Nickname Length Error")); + return; + } + this.ShowSpinner("submit"); + return $.ajax({ + type: 'POST', + url: API + "/locations", + dataType: 'json', + data: { + token: USER.token, + nickname: nickname, + latitude: lat, + longitude: lng + }, + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Favorite Location Save Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.find(".error_message").html(t("Favorite Location Save Failed")); + }, this), + complete: __bind(function(data) { + return this.HideSpinner(); + }, this) + }); + }; + ClientsRequestView.prototype.showFavLoc = function(e) { + $(e.currentTarget).fadeOut(); + return $("#favLoc_form").fadeIn(); + }; + ClientsRequestView.prototype.selectInputText = function(e) { + e.currentTarget.focus(); + return e.currentTarget.select(); + }; + ClientsRequestView.prototype.displayFavLoc = function() { + var alphabet, bounds; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + this.removeMarkers(); + bounds = new google.maps.LatLngBounds(); + _.each(USER.locations, __bind(function(location, index) { + var marker; + marker = new google.maps.Marker({ + position: new google.maps.LatLng(location.latitude, location.longitude), + map: this.map, + title: t("Favorite Location Title", { + id: alphabet != null ? alphabet[index] : void 0 + }), + icon: "https://www.google.com/mapfiles/marker" + alphabet[index] + ".png" + }); + this.markers.push(marker); + bounds.extend(marker.getPosition()); + return google.maps.event.addListener(marker, 'click', __bind(function() { + return this.pickup_icon.setPosition(marker.getPosition()); + }, this)); + }, this)); + this.pickup_icon.setPosition(_.first(this.markers).getPosition()); + return this.map.fitBounds(bounds); + }; + ClientsRequestView.prototype.displaySearchLoc = function() { + var alphabet; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + this.removeMarkers(); + return _.each(this.searchResults, __bind(function(result, index) { + var marker; + if (index < this.numSearchToDisplay) { + marker = new google.maps.Marker({ + position: result.geometry.location, + map: this.map, + title: t("Search Location Title", { + id: alphabet != null ? alphabet[index] : void 0 + }), + icon: "https://www.google.com/mapfiles/marker" + alphabet[index] + ".png" + }); + this.markers.push(marker); + return this.panToLocation(result.geometry.location); + } + }, this)); + }; + ClientsRequestView.prototype.removeMarkers = function() { + _.each(this.markers, __bind(function(marker) { + return marker.setMap(null); + }, this)); + return this.markers = []; + }; + ClientsRequestView.prototype.AskDispatch = function(ask, options) { + var attrs, lowestETA, processData, showCab; + if (ask == null) { + ask = ""; + } + if (options == null) { + options = {}; + } + switch (ask) { + case "NearestCab": + attrs = { + latitude: this.pickup_icon.getPosition().lat(), + longitude: this.pickup_icon.getPosition().lng() + }; + lowestETA = 99999; + showCab = __bind(function(cab) { + var point; + point = new google.maps.Marker({ + position: new google.maps.LatLng(cab.latitude, cab.longitude), + map: this.map, + icon: this.cabMarker, + title: t("ETA Message", { + minutes: app.helpers.FormatSeconds(cab != null ? cab.eta : void 0, true) + }) + }); + if (cab.eta < lowestETA) { + lowestETA = cab.eta; + } + return this.cabs.push(point); + }, this); + processData = __bind(function(data, textStatus, jqXHR) { + if (this.status === "ready") { + this.removeCabs(); + if (data.sorry) { + $("#status_message").html(data.sorry).fadeIn(); + } else { + _.each(data.driverLocations, showCab); + $("#status_message").html(t("Nearest Cab Message", { + minutes: app.helpers.FormatSeconds(lowestETA, true) + })).fadeIn(); + } + if (Backbone.history.fragment === "!/request") { + return _.delay(this.showCabs, this.pollInterval); + } + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "StatusClient": + processData = __bind(function(data, textStatus, jqXHR) { + var bounds, cabLocation, locationSaved, point, userLocation; + if (data.messageType === "OK") { + switch (data.status) { + case "completed": + this.removeCabs(); + this.setStatus("rate"); + return this.fetchTripDetails(data.tripID); + case "open": + return this.setStatus("ready"); + case "begintrip": + this.setStatus("riding"); + cabLocation = new google.maps.LatLng(data.latitude, data.longitude); + this.removeCabs(); + this.pickup_icon.setMap(null); + point = new google.maps.Marker({ + position: cabLocation, + map: this.map, + icon: this.cabMarker + }); + this.cabs.push(point); + this.map.panTo(point.getPosition()); + $("#rideName").html(data.driverName); + $("#ridePhone").html(data.driverMobile); + $("#ride_address_wrapper").hide(); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + break; + case "pending": + this.setStatus("searching"); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + break; + case "accepted": + case "arrived": + if (data.status === "accepted") { + this.setStatus("waiting"); + $("#status_message").html(t("Arrival ETA Message", { + minutes: app.helpers.FormatSeconds(data.eta, true) + })); + } else { + this.setStatus("arriving"); + $("#status_message").html(t("Arriving Now Message")); + } + userLocation = new google.maps.LatLng(data.pickupLocation.latitude, data.pickupLocation.longitude); + cabLocation = new google.maps.LatLng(data.latitude, data.longitude); + this.pickup_icon.setPosition(userLocation); + this.removeCabs(); + $("#rideName").html(data.driverName); + $("#ridePhone").html(data.driverMobile); + if ($("#rideAddress").html() === "") { + locationSaved = false; + _.each(USER.locations, __bind(function(location) { + if (parseFloat(location.latitude) === parseFloat(data.pickupLocation.latitude) && parseFloat(location.longitude) === parseFloat(data.pickupLocation.longitude)) { + return locationSaved = true; + } + }, this)); + if (locationSaved) { + $("#addToFavButton").hide(); + } + $("#pickupLat").val(data.pickupLocation.latitude); + $("#pickupLng").val(data.pickupLocation.longitude); + this.geocoder.geocode({ + location: userLocation + }, __bind(function(result, status) { + $("#rideAddress").html(result[0].formatted_address); + return $("#favLocNickname").val("" + result[0].address_components[0].short_name + " " + result[0].address_components[1].short_name); + }, this)); + } + point = new google.maps.Marker({ + position: cabLocation, + map: this.map, + icon: this.cabMarker + }); + this.cabs.push(point); + bounds = bounds = new google.maps.LatLngBounds(); + bounds.extend(cabLocation); + bounds.extend(userLocation); + this.map.fitBounds(bounds); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + } + } + }, this); + return this.AjaxCall(ask, processData); + case "Pickup": + attrs = { + latitude: this.pickup_icon.getPosition().lat(), + longitude: this.pickup_icon.getPosition().lng() + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "Error") { + return $("#status_message").html(data.description); + } else { + return this.AskDispatch("StatusClient"); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "PickupCanceledClient": + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + return this.setStatus("ready"); + } else { + return $("#status_message").html(data.description); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "RatingDriver": + attrs = { + rating: options.rating + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + this.setStatus("init"); + } else { + $("status_message").html(t("Rating Driver Failed")); + } + return this.HideSpinner(); + }, this); + return this.AjaxCall(ask, processData, attrs); + case "Feedback": + attrs = { + message: options.message + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + return alert("rated"); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + } + }; + ClientsRequestView.prototype.AjaxCall = function(type, successCallback, attrs) { + if (attrs == null) { + attrs = {}; + } + _.extend(attrs, { + token: USER.token, + messageType: type, + app: "client", + version: "1.0.60", + device: "web" + }); + return $.ajax({ + type: 'POST', + url: DISPATCH + "/", + processData: false, + data: JSON.stringify(attrs), + success: successCallback, + dataType: 'json', + error: __bind(function(jqXHR, textStatus, errorThrown) { + $("#status_message").html(errorThrown); + return this.HideSpinner(); + }, this) + }); + }; + return ClientsRequestView; + })(); +}).call(this); +}, "views/clients/settings": function(exports, require, module) {(function() { + var clientsSettingsTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsSettingsTemplate = require('templates/clients/settings'); + exports.ClientsSettingsView = (function() { + __extends(ClientsSettingsView, UberView); + function ClientsSettingsView() { + this.render = __bind(this.render, this); + this.initialize = __bind(this.initialize, this); + ClientsSettingsView.__super__.constructor.apply(this, arguments); + } + ClientsSettingsView.prototype.id = 'settings_view'; + ClientsSettingsView.prototype.className = 'view_container'; + ClientsSettingsView.prototype.events = { + 'submit #profile_pic_form': 'processPicUpload', + 'click #submit_pic': 'processPicUpload', + 'click a.setting_change': "changeTab", + 'submit #edit_info_form': "submitInfo", + 'click #change_password': 'changePass' + }; + ClientsSettingsView.prototype.divs = { + 'info_div': "Information", + 'pic_div': "Picture" + }; + ClientsSettingsView.prototype.pageTitle = t("Settings") + " | " + t("Uber"); + ClientsSettingsView.prototype.tabTitle = { + 'info_div': t("Information"), + 'pic_div': t("Picture") + }; + ClientsSettingsView.prototype.initialize = function() { + return this.mixin(require('web-lib/mixins/i18n_phone_form').i18nPhoneForm); + }; + ClientsSettingsView.prototype.render = function(type) { + if (type == null) { + type = "info"; + } + this.RefreshUserInfo(__bind(function() { + var $el, alphabet; + this.delegateEvents(); + this.HideSpinner(); + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $el = $(this.el); + $(this.el).html(clientsSettingsTemplate({ + type: type + })); + $el.find("#" + type + "_div").show(); + $el.find("a[href='" + type + "_div']").parent().addClass("active"); + return document.title = "" + this.tabTitle[type + '_div'] + " " + this.pageTitle; + }, this)); + this.delegateEvents(); + return this; + }; + ClientsSettingsView.prototype.changeTab = function(e) { + var $eTarget, $el, div, link, pageDiv, _i, _j, _len, _len2, _ref, _ref2; + e.preventDefault(); + $eTarget = $(e.currentTarget); + this.ClearGlobalStatus(); + $el = $(this.el); + _ref = $el.find(".setting_change"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + $(link).parent().removeClass("active"); + } + $eTarget.parent().addClass("active"); + _ref2 = _.keys(this.divs); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + div = _ref2[_j]; + $el.find("#" + div).hide(); + } + pageDiv = $eTarget.attr('href'); + $el.find("#" + pageDiv).show(); + Backbone.history.navigate("!/settings/" + (this.divs[pageDiv].toLowerCase().replace(" ", "-")), false); + document.title = "" + this.tabTitle[pageDiv] + " " + this.pageTitle; + if (pageDiv === "loc_div") { + try { + google.maps.event.trigger(this.map, 'resize'); + return this.map.fitBounds(this.bounds); + } catch (_e) {} + } + }; + ClientsSettingsView.prototype.submitInfo = function(e) { + var $e, attrs, client, options; + $('#global_status').find('.success_message').text(''); + $('#global_status').find('.error_message').text(''); + $('.error_message').text(''); + e.preventDefault(); + $e = $(e.currentTarget); + attrs = $e.serializeToJson(); + attrs['mobile_country_id'] = this.$('#mobile_country_id').val(); + if (attrs['password'] === '') { + delete attrs['password']; + } + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Information Update Succeeded")); + return this.RefreshUserInfo(); + }, this), + error: __bind(function(model, data) { + var errors; + if (data.status === 406) { + errors = JSON.parse(data.responseText); + return _.each(_.keys(errors), function(field) { + return $("#" + field).parent().find('span.error_message').text(errors[field]); + }); + } else { + return this.ShowError(t("Information Update Failed")); + } + }, this), + type: "PUT" + }; + client = new app.models.client({ + id: USER.id + }); + return client.save(attrs, options); + }; + ClientsSettingsView.prototype.changePass = function(e) { + e.preventDefault(); + $(e.currentTarget).hide(); + return $("#password").show(); + }; + ClientsSettingsView.prototype.processPicUpload = function(e) { + e.preventDefault(); + this.ShowSpinner("submit"); + return $.ajaxFileUpload({ + url: API + '/user_pictures', + secureuri: false, + fileElementId: 'picture', + data: { + token: USER.token + }, + dataType: 'json', + complete: __bind(function(data, status) { + this.HideSpinner(); + if (status === 'success') { + this.ShowSuccess(t("Picture Update Succeeded")); + return this.RefreshUserInfo(__bind(function() { + return $("#settingsProfPic").attr("src", USER.picture_url + ("?" + (Math.floor(Math.random() * 1000)))); + }, this)); + } else { + if (data.error) { + return this.ShowError(data.error); + } else { + return this.ShowError("Picture Update Failed"); + } + } + }, this) + }); + }; + return ClientsSettingsView; + })(); +}).call(this); +}, "views/clients/sign_up": function(exports, require, module) {(function() { + var clientsSignUpTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsSignUpTemplate = require('templates/clients/sign_up'); + exports.ClientsSignUpView = (function() { + __extends(ClientsSignUpView, UberView); + function ClientsSignUpView() { + ClientsSignUpView.__super__.constructor.apply(this, arguments); + } + ClientsSignUpView.prototype.id = 'signup_view'; + ClientsSignUpView.prototype.className = 'view_container'; + ClientsSignUpView.prototype.initialize = function() { + this.mixin(require('web-lib/mixins/i18n_phone_form').i18nPhoneForm); + return $('#location_country').live('change', function() { + if (!$('#mobile').val()) { + return $('#mobile_country').find("option[value=" + ($(this).val()) + "]").attr('selected', 'selected').end().trigger('change'); + } + }); + }; + ClientsSignUpView.prototype.events = { + 'submit form': 'signup', + 'click button': 'signup', + 'change #card_number': 'showCardType', + 'change #location_country': 'countryChange' + }; + ClientsSignUpView.prototype.render = function(invite) { + this.HideSpinner(); + $(this.el).html(clientsSignUpTemplate({ + invite: invite + })); + return this; + }; + ClientsSignUpView.prototype.signup = function(e) { + var $el, attrs, client, error_messages, options; + e.preventDefault(); + $el = $("form"); + $el.find('#terms_error').hide(); + if (!$el.find('#signup_terms input[type=checkbox]').attr('checked')) { + $('#spinner.submit').hide(); + $el.find('#terms_error').show(); + return; + } + error_messages = $el.find('.error_message').html(""); + attrs = { + first_name: $el.find('#first_name').val(), + last_name: $el.find('#last_name').val(), + email: $el.find('#email').val(), + password: $el.find('#password').val(), + location_country: $el.find('#location_country option:selected').attr('data-iso2'), + location: $el.find('#location').val(), + language: $el.find('#language').val(), + mobile_country: $el.find('#mobile_country option:selected').attr('data-iso2'), + mobile: $el.find('#mobile').val(), + card_number: $el.find('#card_number').val(), + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + card_code: $el.find('#card_code').val(), + use_case: $el.find('#use_case').val(), + promotion_code: $el.find('#promotion_code').val() + }; + options = { + statusCode: { + 200: function(response) { + $.cookie('token', response.token); + amplify.store('USERjson', response); + app.refreshMenu(); + return app.routers.clients.navigate('!/dashboard', true); + }, + 406: function(e) { + var error, errors, _i, _len, _ref, _results; + errors = JSON.parse(e.responseText); + _ref = _.keys(errors); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + error = _ref[_i]; + _results.push($('#' + error).parent().find('span').html($('#' + error).parent().find('span').html() + " " + errors[error])); + } + return _results; + } + }, + complete: __bind(function(response) { + return this.HideSpinner(); + }, this) + }; + client = new app.models.client; + $('.spinner#submit').show(); + return client.save(attrs, options); + }; + ClientsSignUpView.prototype.countryChange = function(e) { + var $e; + $e = $(e.currentTarget); + return $("#mobile_country").val($e.val()).trigger('change'); + }; + ClientsSignUpView.prototype.showCardType = function(e) { + var $el, reAmerica, reDiscover, reMaster, reVisa, validCard; + reVisa = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/; + reMaster = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/; + reAmerica = /^6011-?\d{4}-?\d{4}-?\d{4}$/; + reDiscover = /^3[4,7]\d{13}$/; + $el = $("#card_logos_signup"); + validCard = false; + if (e.currentTarget.value.match(reVisa)) { + $el.find("#overlay_left").css('width', "0px"); + return $el.find("#overlay_right").css('width', "75%"); + } else if (e.currentTarget.value.match(reMaster)) { + $el.find("#overlay_left").css('width', "25%"); + return $el.find("#overlay_right").css('width', "50%"); + } else if (e.currentTarget.value.match(reAmerica)) { + $el.find("#overlay_left").css('width', "75%"); + $el.find("#overlay_right").css('width', "0px"); + return console.log("amex"); + } else if (e.currentTarget.value.match(reDiscover)) { + $el.find("#overlay_left").css('width', "50%"); + return $el.find("#overlay_right").css('width', "25%"); + } else { + $el.find("#overlay_left").css('width', "0px"); + return $el.find("#overlay_right").css('width', "0px"); + } + }; + return ClientsSignUpView; + })(); +}).call(this); +}, "views/clients/trip_detail": function(exports, require, module) {(function() { + var clientsTripDetailTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsTripDetailTemplate = require('templates/clients/trip_detail'); + exports.TripDetailView = (function() { + __extends(TripDetailView, UberView); + function TripDetailView() { + this.resendReceipt = __bind(this.resendReceipt, this); + TripDetailView.__super__.constructor.apply(this, arguments); + } + TripDetailView.prototype.id = 'trip_detail_view'; + TripDetailView.prototype.className = 'view_container'; + TripDetailView.prototype.events = { + 'click a#fare_review': 'showFareReview', + 'click #fare_review_hide': 'hideFareReview', + 'submit #form_review_form': 'submitFareReview', + 'click #submit_fare_review': 'submitFareReview', + 'click .resendReceipt': 'resendReceipt' + }; + TripDetailView.prototype.render = function(id) { + if (id == null) { + id = 'invalid'; + } + this.ReadUserInfo(); + this.HideSpinner(); + this.model = new app.models.trip({ + id: id + }); + this.model.fetch({ + data: { + relationships: 'points,driver,city.country' + }, + dataType: 'json', + success: __bind(function() { + var trip; + trip = this.model; + $(this.el).html(clientsTripDetailTemplate({ + trip: trip + })); + this.RequireMaps(__bind(function() { + var bounds, endPos, map, myOptions, path, polyline, startPos; + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(this.model.get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + myOptions = { + zoom: 12, + center: path[0], + mapTypeId: google.maps.MapTypeId.ROADMAP, + zoomControl: false, + rotateControl: false, + panControl: false, + mapTypeControl: false, + scrollwheel: false + }; + map = new google.maps.Map(document.getElementById("trip_details_map"), myOptions); + map.fitBounds(bounds); + startPos = new google.maps.Marker({ + position: _.first(path), + map: map, + title: t("Trip started here"), + icon: 'https://uber-static.s3.amazonaws.com/marker_start.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: map, + title: t("Trip ended here"), + icon: 'https://uber-static.s3.amazonaws.com/marker_end.png' + }); + startPos.setMap(map); + endPos.setMap(map); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + return polyline.setMap(map); + }, this)); + return this.HideSpinner(); + }, this) + }); + this.ShowSpinner('load'); + this.delegateEvents(); + return this; + }; + TripDetailView.prototype.showFareReview = function(e) { + e.preventDefault(); + $('#fare_review_box').slideDown(); + return $('#fare_review').hide(); + }; + TripDetailView.prototype.hideFareReview = function(e) { + e.preventDefault(); + $('#fare_review_box').slideUp(); + return $('#fare_review').show(); + }; + TripDetailView.prototype.submitFareReview = function(e) { + var attrs, errorMessage, id, options; + e.preventDefault(); + errorMessage = $(".error_message"); + errorMessage.hide(); + id = $("#tripid").val(); + this.model = new app.models.trip({ + id: id + }); + attrs = { + note: $('#form_review_message').val(), + note_type: 'client_fare_review' + }; + options = { + success: __bind(function(response) { + $(".success_message").fadeIn(); + return $("#fare_review_form_wrapper").slideUp(); + }, this), + error: __bind(function(error) { + return errorMessage.fadeIn(); + }, this) + }; + return this.model.save(attrs, options); + }; + TripDetailView.prototype.resendReceipt = function(e) { + var $e; + e.preventDefault(); + $e = $(e.currentTarget); + this.$(".resendReceiptSuccess").empty().show(); + this.$(".resentReceiptError").empty().show(); + e.preventDefault(); + $('#spinner').show(); + return $.ajax('/api/trips/func/resend_receipt', { + data: { + token: $.cookie('token'), + trip_id: this.model.id + }, + type: 'POST', + complete: __bind(function(xhr) { + var response; + response = JSON.parse(xhr.responseText); + $('#spinner').hide(); + switch (xhr.status) { + case 200: + this.$(".resendReceiptSuccess").html("Receipt has been emailed"); + return this.$(".resendReceiptSuccess").fadeOut(2000); + default: + this.$(".resendReceiptError").html("Receipt has failed to be emailed"); + return this.$(".resendReceiptError").fadeOut(2000); + } + }, this) + }); + }; + return TripDetailView; + })(); +}).call(this); +}, "views/shared/menu": function(exports, require, module) {(function() { + var menuTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + menuTemplate = require('templates/shared/menu'); + exports.SharedMenuView = (function() { + __extends(SharedMenuView, Backbone.View); + function SharedMenuView() { + SharedMenuView.__super__.constructor.apply(this, arguments); + } + SharedMenuView.prototype.id = 'menu_view'; + SharedMenuView.prototype.render = function() { + var type; + if ($.cookie('token') === null) { + type = 'guest'; + } else { + type = 'client'; + } + $(this.el).html(menuTemplate({ + type: type + })); + return this; + }; + return SharedMenuView; + })(); +}).call(this); +}, "web-lib/collections/countries": function(exports, require, module) {(function() { + var UberCollection; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberCollection = require('web-lib/uber_collection').UberCollection; + exports.CountriesCollection = (function() { + __extends(CountriesCollection, UberCollection); + function CountriesCollection() { + CountriesCollection.__super__.constructor.apply(this, arguments); + } + CountriesCollection.prototype.model = app.models.country; + CountriesCollection.prototype.url = '/countries'; + return CountriesCollection; + })(); +}).call(this); +}, "web-lib/collections/vehicle_types": function(exports, require, module) {(function() { + var UberCollection, vehicleType, _ref; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberCollection = require('web-lib/uber_collection').UberCollection; + vehicleType = (typeof app !== "undefined" && app !== null ? (_ref = app.models) != null ? _ref.vehicleType : void 0 : void 0) || require('models/vehicle_type').VehicleType; + exports.VehicleTypesCollection = (function() { + __extends(VehicleTypesCollection, UberCollection); + function VehicleTypesCollection() { + VehicleTypesCollection.__super__.constructor.apply(this, arguments); + } + VehicleTypesCollection.prototype.model = vehicleType; + VehicleTypesCollection.prototype.url = '/vehicle_types'; + VehicleTypesCollection.prototype.defaultColumns = ['id', 'created_at', 'updated_at', 'deleted_at', 'created_by_user_id', 'updated_by_user_id', 'city_id', 'type', 'make', 'model', 'capacity', 'minimum_year', 'actions']; + VehicleTypesCollection.prototype.tableColumns = function(cols) { + var actions, c, capacity, city_id, columnValues, created_at, created_by_user_id, deleted_at, headerRow, id, make, minimum_year, model, type, updated_at, updated_by_user_id, _i, _len; + id = { + sTitle: 'Id' + }; + created_at = { + sTitle: 'Created At (UTC)', + 'sType': 'string' + }; + updated_at = { + sTitle: 'Updated At (UTC)', + 'sType': 'string' + }; + deleted_at = { + sTitle: 'Deleted At (UTC)', + 'sType': 'string' + }; + created_by_user_id = { + sTitle: 'Created By' + }; + updated_by_user_id = { + sTitle: 'Updated By' + }; + city_id = { + sTitle: 'City' + }; + type = { + sTitle: 'Type' + }; + make = { + sTitle: 'Make' + }; + model = { + sTitle: 'Model' + }; + capacity = { + sTitle: 'Capacity' + }; + minimum_year = { + sTitle: 'Min. Year' + }; + actions = { + sTitle: 'Actions' + }; + columnValues = { + id: id, + created_at: created_at, + updated_at: updated_at, + deleted_at: deleted_at, + created_by_user_id: created_by_user_id, + updated_by_user_id: updated_by_user_id, + city_id: city_id, + type: type, + make: make, + model: model, + capacity: capacity, + minimum_year: minimum_year, + actions: actions + }; + headerRow = []; + for (_i = 0, _len = cols.length; _i < _len; _i++) { + c = cols[_i]; + if (columnValues[c]) { + headerRow.push(columnValues[c]); + } + } + return headerRow; + }; + return VehicleTypesCollection; + })(); +}).call(this); +}, "web-lib/helpers": function(exports, require, module) {(function() { + var __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + exports.helpers = { + pin: function(num, color) { + if (color == null) { + color = 'FF0000'; + } + return ""; + }, + reverseGeocode: function(latitude, longitude) { + if (latitude && longitude) { + return "" + latitude + ", " + longitude + ""; + } else { + return ''; + } + }, + linkedName: function(model) { + var first_name, id, last_name, role, url; + role = model.role || model.get('role'); + id = model.id || model.get('id'); + first_name = model.first_name || model.get('first_name'); + last_name = model.last_name || model.get('last_name'); + url = "/" + role + "s/" + id; + return "" + first_name + " " + last_name + ""; + }, + linkedVehicle: function(vehicle, vehicleType) { + return " " + (vehicleType != null ? vehicleType.get('make') : void 0) + " " + (vehicleType != null ? vehicleType.get('model') : void 0) + " " + (vehicle.get('year')) + " "; + }, + linkedUserId: function(userType, userId) { + return "" + userType + " " + userId + ""; + }, + timeDelta: function(start, end) { + var delta; + if (typeof start === 'string') { + start = this.parseDate(start); + } + if (typeof end === 'string') { + end = this.parseDate(end); + } + if (end && start) { + delta = end.getTime() - start.getTime(); + return this.formatSeconds(delta / 1000); + } else { + return '00:00'; + } + }, + formatSeconds: function(s) { + var minutes, seconds; + s = Math.floor(s); + minutes = Math.floor(s / 60); + seconds = s - minutes * 60; + return "" + (this.leadingZero(minutes)) + ":" + (this.leadingZero(seconds)); + }, + formatCurrency: function(strValue, reverseSign, currency) { + var currency_locale, lc, mf; + if (reverseSign == null) { + reverseSign = false; + } + if (currency == null) { + currency = null; + } + strValue = String(strValue); + if (reverseSign) { + strValue = ~strValue.indexOf('-') ? strValue.split('-').join('') : ['-', strValue].join(''); + } + currency_locale = i18n.currencyToLocale[currency]; + try { + if (!(currency_locale != null) || currency_locale === i18n.locale) { + return i18n.jsworld.mf.format(strValue); + } else { + lc = new jsworld.Locale(POSIX_LC[currency_locale]); + mf = new jsworld.MonetaryFormatter(lc); + return mf.format(strValue); + } + } catch (error) { + i18n.log(error); + return strValue; + } + }, + formatTripFare: function(trip, type) { + var _ref, _ref2; + if (type == null) { + type = "fare"; + } + if (!trip.get('fare')) { + return 'n/a'; + } + if (((_ref = trip.get('fare_breakdown_local')) != null ? _ref.currency : void 0) != null) { + return app.helpers.formatCurrency(trip.get("" + type + "_local"), false, (_ref2 = trip.get('fare_breakdown_local')) != null ? _ref2.currency : void 0); + } else if (trip.get("" + type + "_string") != null) { + return trip.get("" + type + "_string"); + } else if (trip.get("" + type + "_local") != null) { + return trip.get("" + type + "_local"); + } else { + return 'n/a'; + } + }, + formatPhoneNumber: function(phoneNumber, countryCode) { + if (countryCode == null) { + countryCode = "+1"; + } + if (phoneNumber != null) { + phoneNumber = String(phoneNumber); + switch (countryCode) { + case '+1': + return countryCode + ' ' + phoneNumber.substring(0, 3) + '-' + phoneNumber.substring(3, 6) + '-' + phoneNumber.substring(6, 10); + case '+33': + return countryCode + ' ' + phoneNumber.substring(0, 1) + ' ' + phoneNumber.substring(1, 3) + ' ' + phoneNumber.substring(3, 5) + ' ' + phoneNumber.substring(5, 7) + ' ' + phoneNumber.substring(7, 9); + default: + countryCode + phoneNumber; + } + } + return "" + countryCode + " " + phoneNumber; + }, + parseDate: function(d, cityTime, tz) { + var city_filter, parsed, _ref; + if (cityTime == null) { + cityTime = true; + } + if (tz == null) { + tz = null; + } + if (((_ref = !d.substr(-6, 1)) === '+' || _ref === '-') || d.length === 19) { + d += '+00:00'; + } + if (/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/.test(d)) { + parsed = d.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/); + d = new Date(); + d.setUTCFullYear(parsed[1]); + d.setUTCMonth(parsed[2] - 1); + d.setUTCDate(parsed[3]); + d.setUTCHours(parsed[4]); + d.setUTCMinutes(parsed[5]); + d.setUTCSeconds(parsed[6]); + } else { + d = Date.parse(d); + } + if (typeof d === 'number') { + d = new Date(d); + } + d = new timezoneJS.Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), 'Etc/UTC'); + if (tz) { + d.convertToTimezone(tz); + } else if (cityTime) { + city_filter = $.cookie('city_filter'); + if (city_filter) { + tz = $("#city_filter option[value=" + city_filter + "]").attr('data-timezone'); + if (tz) { + d.convertToTimezone(tz); + } + } + } + return d; + }, + dateToTimezone: function(d) { + var city_filter, tz; + d = new timezoneJS.Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), 'Etc/UTC'); + city_filter = $.cookie('city_filter'); + if (city_filter) { + tz = $("#city_filter option[value=" + city_filter + "]").attr('data-timezone'); + d.convertToTimezone(tz); + } + return d; + }, + fixAMPM: function(d, formatted) { + if (d.hours >= 12) { + return formatted.replace(/\b[AP]M\b/, 'PM'); + } else { + return formatted.replace(/\b[AP]M\b/, 'AM'); + } + }, + formatDate: function(d, time, timezone) { + var formatted; + if (time == null) { + time = true; + } + if (timezone == null) { + timezone = null; + } + d = this.parseDate(d, true, timezone); + formatted = time ? ("" + (i18n.jsworld.dtf.formatDate(d)) + " ") + this.formatTime(d, d.getTimezoneInfo()) : i18n.jsworld.dtf.formatDate(d); + return this.fixAMPM(d, formatted); + }, + formatDateLong: function(d, time, timezone) { + if (time == null) { + time = true; + } + if (timezone == null) { + timezone = null; + } + d = this.parseDate(d, true, timezone); + timezone = d.getTimezoneInfo().tzAbbr; + if (time) { + return (i18n.jsworld.dtf.formatDateTime(d)) + (" " + timezone); + } else { + return i18n.jsworld.dtf.formatDate(d); + } + }, + formatTimezoneJSDate: function(d) { + var day, hours, jsDate, minutes, month, year; + year = d.getFullYear(); + month = this.leadingZero(d.getMonth()); + day = this.leadingZero(d.getDate()); + hours = this.leadingZero(d.getHours()); + minutes = this.leadingZero(d.getMinutes()); + jsDate = new Date(year, month, day, hours, minutes, 0); + return jsDate.toDateString(); + }, + formatTime: function(d, timezone) { + var formatted; + if (timezone == null) { + timezone = null; + } + formatted = ("" + (i18n.jsworld.dtf.formatTime(d))) + (timezone != null ? " " + (timezone != null ? timezone.tzAbbr : void 0) : ""); + return this.fixAMPM(d, formatted); + }, + formatISODate: function(d) { + var pad; + pad = function(n) { + if (n < 10) { + return '0' + n; + } + return n; + }; + return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + 'Z'; + }, + formatExpDate: function(d) { + var month, year; + d = this.parseDate(d); + year = d.getFullYear(); + month = this.leadingZero(d.getMonth() + 1); + return "" + year + "-" + month; + }, + formatLatLng: function(lat, lng, precision) { + if (precision == null) { + precision = 8; + } + return parseFloat(lat).toFixed(precision) + ',' + parseFloat(lng).toFixed(precision); + }, + leadingZero: function(num) { + if (num < 10) { + return "0" + num; + } else { + return num; + } + }, + roundNumber: function(num, dec) { + return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec); + }, + notesToHTML: function(notes) { + var i, note, notesHTML, _i, _len; + notesHTML = ''; + i = 1; + if (notes) { + for (_i = 0, _len = notes.length; _i < _len; _i++) { + note = notes[_i]; + notesHTML += "" + note['userid'] + "     " + (this.formatDate(note['created_at'])) + "

" + note['note'] + "

"; + notesHTML += "
"; + } + } + return notesHTML.replace("'", '"e'); + }, + formatPhone: function(n) { + var parts, phone, regexObj; + n = "" + n; + regexObj = /^(?:\+?1[-. ]?)?(?:\(?([0-9]{3})\)?[-. ]?)?([0-9]{3})[-. ]?([0-9]{4})$/; + if (regexObj.test(n)) { + parts = n.match(regexObj); + phone = ""; + if (parts[1]) { + phone += "(" + parts[1] + ") "; + } + phone += "" + parts[2] + "-" + parts[3]; + } else { + phone = n; + } + return phone; + }, + usStates: ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'District of Columbia', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'], + onboardingPages: ['applied', 'ready_to_interview', 'pending_interview', 'interviewed', 'accepted', 'ready_to_onboard', 'pending_onboarding', 'active', 'waitlisted', 'rejected'], + driverBreadCrumb: function(loc, model) { + var onboardingPage, out, _i, _len, _ref; + out = "Drivers > "; + if (!(model != null)) { + out += ""; + } else { + out += "" + (this.onboardingUrlToName(model.get('driver_status'))) + ""; + out += " > " + (this.linkedName(model)) + " (" + (model.get('role')) + ") #" + (model.get('id')); + } + return out; + }, + onboardingUrlToName: function(url) { + return url != null ? url.replace(/_/g, " ").replace(/(^|\s)([a-z])/g, function(m, p1, p2) { + return p1 + p2.toUpperCase(); + }) : void 0; + }, + formatVehicle: function(vehicle) { + if (vehicle.get('make') && vehicle.get('model') && vehicle.get('license_plate')) { + return "" + (vehicle.get('make')) + " " + (vehicle.get('model')) + " (" + (vehicle.get('license_plate')) + ")"; + } + }, + docArbitraryFields: function(docName, cityDocs) { + var doc, field, out, _i, _j, _len, _len2, _ref; + out = ""; + for (_i = 0, _len = cityDocs.length; _i < _len; _i++) { + doc = cityDocs[_i]; + if (doc.name === docName && __indexOf.call(_.keys(doc), "metaFields") >= 0) { + _ref = doc.metaFields; + for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) { + field = _ref[_j]; + out += "" + field.label + ":
"; + } + } + } + return out; + }, + capitaliseFirstLetter: function(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + }, + createDocUploadForm: function(docName, driverId, vehicleId, cityMeta, vehicleName, expirationRequired) { + var ddocs, expDropdowns, pdocs, vdocs; + if (driverId == null) { + driverId = "None"; + } + if (vehicleId == null) { + vehicleId = "None"; + } + if (cityMeta == null) { + cityMeta = []; + } + if (vehicleName == null) { + vehicleName = false; + } + if (expirationRequired == null) { + expirationRequired = false; + } + ddocs = cityMeta["driverRequiredDocs"] || []; + pdocs = cityMeta["partnerRequiredDocs"] || []; + vdocs = cityMeta["vehicleRequiredDocs"] || []; + expDropdowns = "Expiration Date:\n -\n"; + return " \n
\n \n \n \n\n
\n " + (vehicleName ? vehicleName : "") + " " + docName + "\n
\n\n
\n \n
\n\n
\n " + (expirationRequired ? expDropdowns : "") + "\n
\n\n
\n " + (app.helpers.docArbitraryFields(docName, _.union(ddocs, pdocs, vdocs))) + "\n
\n\n
\n \n
\n\n
\n"; + }, + countrySelector: function(name, options) { + var countries, countryCodePrefix, defaultOptions; + if (options == null) { + options = {}; + } + defaultOptions = { + selectedKey: 'telephone_code', + selectedValue: '+1', + silent: false + }; + _.extend(defaultOptions, options); + options = defaultOptions; + countries = new app.collections.countries(); + countries.fetch({ + data: { + limit: 300 + }, + success: function(countries) { + var $option, $select, country, selected, _i, _len, _ref; + selected = false; + _ref = countries.models || []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + country = _ref[_i]; + $select = $("select[name=" + name + "]"); + $option = $('').val(country.id).attr('data-iso2', country.get('iso2')).attr('data-prefix', country.get('telephone_code')).html(country.get('name')); + if (country.get(options.selectedKey) === options.selectedValue && !selected) { + selected = true; + $option.attr('selected', 'selected'); + } + $select.append($option); + } + if (selected && !options.silent) { + return $select.val(options.selected).trigger('change'); + } + } + }); + countryCodePrefix = options.countryCodePrefix ? "data-country-code-prefix='" + options.countryCodePrefix + "'" : ''; + return ""; + }, + missingDocsOnDriver: function(driver) { + var city, docsReq, documents, partnerDocs; + city = driver.get('city'); + documents = driver.get('documents'); + if ((city != null) && (documents != null)) { + docsReq = _.pluck(city != null ? city.get('meta')["driverRequiredDocs"] : void 0, "name"); + if (driver.get('role') === "partner") { + partnerDocs = _.pluck(city != null ? city.get('meta')["partnerRequiredDocs"] : void 0, "name"); + docsReq = _.union(docsReq, partnerDocs); + } + return _.reject(docsReq, __bind(function(doc) { + return __indexOf.call((documents != null ? documents.pluck("name") : void 0) || [], doc) >= 0; + }, this)); + } else { + return []; + } + } + }; +}).call(this); +}, "web-lib/i18n": function(exports, require, module) {(function() { + exports.i18n = { + defaultLocale: 'en_US', + cookieName: '_LOCALE_', + locales: { + 'en_US': "English (US)", + 'fr_FR': "Français" + }, + currencyToLocale: { + 'USD': 'en_US', + 'EUR': 'fr_FR' + }, + logglyKey: 'd2d5a9bc-7ebe-4538-a180-81e62c705b1b', + logglyHost: 'https://logs.loggly.com', + init: function() { + this.castor = new window.loggly({ + url: this.logglyHost + '/inputs/' + this.logglyKey + '?rt=1', + level: 'error' + }); + this.setLocale($.cookie(this.cookieName) || this.defaultLocale); + window.t = _.bind(this.t, this); + this.loadLocaleTranslations(this.locale); + if (!(this[this.defaultLocale] != null)) { + return this.loadLocaleTranslations(this.defaultLocale); + } + }, + loadLocaleTranslations: function(locale) { + var loadPaths, path, _i, _len, _results; + loadPaths = ['web-lib/translations/' + locale, 'web-lib/translations/' + locale.slice(0, 2), 'translations/' + locale, 'translations/' + locale.slice(0, 2)]; + _results = []; + for (_i = 0, _len = loadPaths.length; _i < _len; _i++) { + path = loadPaths[_i]; + locale = path.substring(path.lastIndexOf('/') + 1); + if (this[locale] == null) { + this[locale] = {}; + } + _results.push((function() { + try { + return _.extend(this[locale], require(path).translations); + } catch (error) { + + } + }).call(this)); + } + return _results; + }, + getLocale: function() { + return this.locale; + }, + setLocale: function(locale) { + var message, parts, _ref; + parts = locale.split('_'); + this.locale = parts[0].toLowerCase(); + if (parts.length > 1) { + this.locale += "_" + (parts[1].toUpperCase()); + } + if (this.locale) { + $.cookie(this.cookieName, this.locale, { + path: '/', + domain: '.uber.com' + }); + } + try { + ((_ref = this.jsworld) != null ? _ref : this.jsworld = {}).lc = new jsworld.Locale(POSIX_LC[this.locale]); + this.jsworld.mf = new jsworld.MonetaryFormatter(this.jsworld.lc); + this.jsworld.nf = new jsworld.NumericFormatter(this.jsworld.lc); + this.jsworld.dtf = new jsworld.DateTimeFormatter(this.jsworld.lc); + this.jsworld.np = new jsworld.NumericParser(this.jsworld.lc); + this.jsworld.mp = new jsworld.MonetaryParser(this.jsworld.lc); + return this.jsworld.dtp = new jsworld.DateTimeParser(this.jsworld.lc); + } catch (error) { + message = 'JsWorld error with locale: ' + this.locale; + return this.log({ + message: message, + error: error + }); + } + }, + getTemplate: function(id) { + var _ref, _ref2; + return ((_ref = this[this.locale]) != null ? _ref[id] : void 0) || ((_ref2 = this[this.locale.slice(0, 2)]) != null ? _ref2[id] : void 0); + }, + getTemplateDefault: function(id) { + var _ref, _ref2; + return ((_ref = this[this.defaultLocale]) != null ? _ref[id] : void 0) || ((_ref2 = this[this.defaultLocale.slice(0, 2)]) != null ? _ref2[id] : void 0); + }, + getTemplateOrDefault: function(id) { + return this.getTemplate(id) || this.getTemplateDefault(id); + }, + t: function(id, vars) { + var errStr, locale, template; + if (vars == null) { + vars = {}; + } + locale = this.getLocale(); + template = this.getTemplate(id); + if (template == null) { + if (/dev|test/.test(window.location.host)) { + template = "(?) " + id; + } else { + template = this.getTemplateDefault(id); + } + errStr = "Missing [" + locale + "] translation for [" + id + "] at [" + window.location.hash + "] - Default template is [" + template + "]"; + this.log({ + error: errStr, + locale: locale, + id: id, + defaultTemplate: template + }); + } + if (template) { + return _.template(template, vars); + } else { + return id; + } + }, + log: function(error) { + if (/dev/.test(window.location.host)) { + if ((typeof console !== "undefined" && console !== null ? console.log : void 0) != null) { + return console.log(error); + } + } else { + _.extend(error, { + host: window.location.host, + hash: window.location.hash + }); + return this.castor.error(JSON.stringify(error)); + } + } + }; +}).call(this); +}, "web-lib/mixins/i18n_phone_form": function(exports, require, module) {(function() { + exports.i18nPhoneForm = { + _events: { + 'change select[data-country-code-prefix]': 'setCountryCodePrefix' + }, + setCountryCodePrefix: function(e) { + var $el, prefix; + $el = $(e.currentTarget); + prefix = $el.find('option:selected').attr('data-prefix'); + return $("#" + ($el.attr('data-country-code-prefix'))).text(prefix); + } + }; +}).call(this); +}, "web-lib/models/country": function(exports, require, module) {(function() { + var UberModel; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberModel = require('web-lib/uber_model').UberModel; + exports.Country = (function() { + __extends(Country, UberModel); + function Country() { + Country.__super__.constructor.apply(this, arguments); + } + Country.prototype.url = function() { + if (this.id) { + return "/countries/" + this.id; + } else { + return '/countries'; + } + }; + return Country; + })(); +}).call(this); +}, "web-lib/models/vehicle_type": function(exports, require, module) {(function() { + var UberModel; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberModel = require('web-lib/uber_model').UberModel; + exports.VehicleType = (function() { + __extends(VehicleType, UberModel); + function VehicleType() { + this.toString = __bind(this.toString, this); + VehicleType.__super__.constructor.apply(this, arguments); + } + VehicleType.prototype.endpoint = 'vehicle_types'; + VehicleType.prototype.toTableRow = function(cols) { + var actions, c, capacity, city_id, columnValues, created_at, created_by_user_id, deleted_at, id, make, minimum_year, model, rows, type, updated_at, updated_by_user_id, _i, _len, _ref; + id = "" + (this.get('id')) + ""; + if (this.get('created_at')) { + created_at = app.helpers.formatDate(this.get('created_at')); + } + if (this.get('updated_at')) { + updated_at = app.helpers.formatDate(this.get('updated_at')); + } + if (this.get('deleted_at')) { + deleted_at = app.helpers.formatDate(this.get('deleted_at')); + } + created_by_user_id = "" + (this.get('created_by_user_id')) + ""; + updated_by_user_id = "" + (this.get('updated_by_user_id')) + ""; + city_id = (_ref = this.get('city')) != null ? _ref.get('display_name') : void 0; + type = this.get('type'); + make = this.get('make'); + model = this.get('model'); + capacity = this.get('capacity'); + minimum_year = this.get('minimum_year'); + actions = "Show"; + if (!this.get('deleted_at')) { + actions += " Edit"; + actions += " Delete"; + } + columnValues = { + id: id, + created_at: created_at, + updated_at: updated_at, + deleted_at: deleted_at, + created_by_user_id: created_by_user_id, + updated_by_user_id: updated_by_user_id, + city_id: city_id, + type: type, + make: make, + model: model, + capacity: capacity, + minimum_year: minimum_year, + actions: actions + }; + rows = []; + for (_i = 0, _len = cols.length; _i < _len; _i++) { + c = cols[_i]; + rows.push(columnValues[c] ? columnValues[c] : '-'); + } + return rows; + }; + VehicleType.prototype.toString = function() { + return this.get('make') + ' ' + this.get('model') + ' ' + this.get('type') + (" (" + (this.get('capacity')) + ")"); + }; + return VehicleType; + })(); +}).call(this); +}, "web-lib/templates/footer": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var locale, title, _ref; + __out.push('\n\n\n\n\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "web-lib/translations/en": function(exports, require, module) {(function() { + exports.translations = { + "Info": "Info", + "Learn More": "Learn More", + "Pricing": "Pricing", + "FAQ": "FAQ", + "Support": "Support", + "Support & FAQ": "Support & FAQ", + "Contact Us": "Contact Us", + "Jobs": "Jobs", + "Phones": "Phones", + "Text Message": "Text Message", + "iPhone": "iPhone", + "Android": "Android", + "Drivers": "Drivers", + "Apply": "Apply", + "Sign In": "Sign In", + "Social": "Social", + "Twitter": "Twitter", + "Facebook": "Facebook", + "Blog": "Blog", + "Legal": "Legal", + "Company_Footer": "Company", + "Privacy Policy": "Privacy Policy", + "Terms": "Terms", + "Copyright © Uber Technologies, Inc.": "Copyright © Uber Technologies, Inc.", + "Language:": "Language:", + "Apply to Drive": "Apply to Drive", + "Expiration": "Expiration", + "Fare": "Fare", + "Driver": "Driver ", + "Dashboard": "Dashboard", + "Forgot Password": "Forgot Password", + "Trip Details": "Trip Details", + "Save": "Save", + "Cancel": "Cancel", + "Edit": "Edit", + "Password": "Password", + "First Name": "First Name", + "Last Name": "Last Name", + "Email Address": "Email Address", + "Submit": "Submit", + "Mobile Number": "Mobile Number", + "Zip Code": "Zip Code", + "Sign Out": "Sign Out", + "Confirm Email Message": "Attempting to confirm email...", + "Upload": "Upload", + "Rating": "Rating", + "Pickup Time": "Pickup Time", + "2011": "2011", + "2012": "2012", + "2013": "2013", + "2014": "2014", + "2015": "2015", + "2016": "2016", + "2017": "2017", + "2018": "2018", + "2019": "2019", + "2020": "2020", + "2021": "2021", + "2022": "2022", + "01": "01", + "02": "02", + "03": "03", + "04": "04", + "05": "05", + "06": "06", + "07": "07", + "08": "08", + "09": "09", + "10": "10", + "11": "11", + "12": "12" + }; +}).call(this); +}, "web-lib/translations/fr": function(exports, require, module) {(function() { + exports.translations = { + "Info": "Info", + "Learn More": "En Savoir Plus", + "Pricing": "Calcul du Prix", + "Support & FAQ": "Aide & FAQ", + "Contact Us": "Contactez Nous", + "Jobs": "Emplois", + "Phones": "Téléphones", + "Text Message": "SMS", + "iPhone": "iPhone", + "Android": "Android", + "Apply to Drive": "Candidature Chauffeur", + "Sign In": "Connexion", + "Social": "Contact", + "Twitter": "Twitter", + "Facebook": "Facebook", + "Blog": "Blog", + "Privacy Policy": "Protection des Données Personelles", + "Terms": "Conditions Générales", + "Copyright © Uber Technologies, Inc.": "© Uber, Inc.", + "Language:": "Langue:", + "Forgot Password": "Mot de passe oublié", + "Company_Footer": "À Propos d'Uber", + "Expiration": "Expiration", + "Fare": "Tarif", + "Driver": "Chauffeur", + "Drivers": "Chauffeurs", + "Dashboard": "Tableau de bord", + "Forgot Password": "Mot de passe oublié", + "Forgot Password?": "Mot de passe oublié?", + "Trip Details": "Détails de la course", + "Save": "Enregistrer", + "Cancel": "Annuler", + "Edit": "Modifier", + "Password": "Mot de passe", + "First Name": "Prénom", + "Last Name": "Nom", + "Email Address": "E-mail", + "Submit": "Soumettre", + "Mobile Number": "Téléphone Portable", + "Zip Code": "Code Postal", + "Sign Out": "Se déconnecter", + "Confirm Email Message": "E-mail de confirmation", + "Upload": "Télécharger", + "Rating": "Notation", + "Pickup Time": "Heure de prise en charge", + "2011": "2011", + "2012": "2012", + "2013": "2013", + "2014": "2014", + "2015": "2015", + "2016": "2016", + "2017": "2017", + "2018": "2018", + "2019": "2019", + "2020": "2020", + "2021": "2021", + "2022": "2022", + "01": "01", + "02": "02", + "03": "03", + "04": "04", + "05": "05", + "06": "06", + "07": "07", + "08": "08", + "09": "09", + "10": "10", + "11": "11", + "12": "12" + }; +}).call(this); +}, "web-lib/uber_collection": function(exports, require, module) {(function() { + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberCollection = (function() { + __extends(UberCollection, Backbone.Collection); + function UberCollection() { + UberCollection.__super__.constructor.apply(this, arguments); + } + UberCollection.prototype.parse = function(data) { + var model, tmp, _i, _in, _len, _out; + _in = data.resources || data; + _out = []; + if (data.meta) { + this.meta = data.meta; + } + for (_i = 0, _len = _in.length; _i < _len; _i++) { + model = _in[_i]; + tmp = new this.model; + tmp.set(tmp.parse(model)); + _out.push(tmp); + } + return _out; + }; + UberCollection.prototype.isRenderable = function() { + if (this.models.length) { + return true; + } + }; + UberCollection.prototype.toTableRows = function(cols) { + var tableRows; + tableRows = []; + _.each(this.models, function(model) { + return tableRows.push(model.toTableRow(cols)); + }); + return tableRows; + }; + return UberCollection; + })(); +}).call(this); +}, "web-lib/uber_model": function(exports, require, module) {(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }; + exports.UberModel = (function() { + __extends(UberModel, Backbone.Model); + function UberModel() { + this.refetch = __bind(this.refetch, this); + this.fetch = __bind(this.fetch, this); + this.save = __bind(this.save, this); + this.parse = __bind(this.parse, this); + UberModel.__super__.constructor.apply(this, arguments); + } + UberModel.prototype.endpoint = 'set_api_endpoint_in_subclass'; + UberModel.prototype.refetchOptions = {}; + UberModel.prototype.url = function(type) { + var endpoint_path; + endpoint_path = "/" + this.endpoint; + if (this.get('id')) { + return endpoint_path + ("/" + (this.get('id'))); + } else { + return endpoint_path; + } + }; + UberModel.prototype.isRenderable = function() { + var i, key, value, _ref; + i = 0; + _ref = this.attributes; + for (key in _ref) { + if (!__hasProp.call(_ref, key)) continue; + value = _ref[key]; + if (this.attributes.hasOwnProperty(key)) { + i += 1; + } + if (i > 1) { + return true; + } + } + return !(i === 1); + }; + UberModel.prototype.parse = function(response) { + var attrs, key, model, models, _i, _j, _k, _len, _len2, _len3, _ref, _ref2; + if (typeof response === 'object') { + _ref = _.intersection(_.keys(app.models), _.keys(response)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + if (response[key]) { + attrs = this.parse(response[key]); + if (typeof attrs === 'object') { + response[key] = new app.models[key](attrs); + } + } + } + _ref2 = _.intersection(_.keys(app.collections), _.keys(response)); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + key = _ref2[_j]; + models = response[key]; + if (_.isArray(models)) { + response[key] = new app.collections[key]; + for (_k = 0, _len3 = models.length; _k < _len3; _k++) { + model = models[_k]; + attrs = app.collections[key].prototype.model.prototype.parse(model); + response[key].add(new response[key].model(attrs)); + } + } + } + } + return response; + }; + UberModel.prototype.save = function(attributes, options) { + var attr, _i, _j, _len, _len2, _ref, _ref2; + if (options == null) { + options = {}; + } + _ref = _.intersection(_.keys(app.models), _.keys(this.attributes)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + attr = _ref[_i]; + if (typeof this.get(attr) === "object") { + this.unset(attr, { + silent: true + }); + } + } + _ref2 = _.intersection(_.keys(app.collections), _.keys(this.attributes)); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + attr = _ref2[_j]; + if (typeof this.get(attr) === "object") { + this.unset(attr, { + silent: true + }); + } + } + if ((options != null) && options.diff && (attributes != null) && attributes !== {}) { + attributes['id'] = this.get('id'); + attributes['token'] = this.get('token'); + this.clear({ + 'silent': true + }); + this.set(attributes, { + silent: true + }); + } + if (__indexOf.call(_.keys(options), "data") < 0 && __indexOf.call(_.keys(this.refetchOptions || {}), "data") >= 0) { + options.data = this.refetchOptions.data; + } + return Backbone.Model.prototype.save.call(this, attributes, options); + }; + UberModel.prototype.fetch = function(options) { + this.refetchOptions = options; + return Backbone.Model.prototype.fetch.call(this, options); + }; + UberModel.prototype.refetch = function() { + return this.fetch(this.refetchOptions); + }; + return UberModel; + })(); +}).call(this); +}, "web-lib/uber_router": function(exports, require, module) {(function() { + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberRouter = (function() { + __extends(UberRouter, Backbone.Router); + function UberRouter() { + UberRouter.__super__.constructor.apply(this, arguments); + } + UberRouter.prototype.datePickers = function(format) { + if (format == null) { + format = "%Z-%m-%dT%H:%i:%s%:"; + } + $('.datepicker').AnyTime_noPicker(); + return $('.datepicker').AnyTime_picker({ + 'format': format, + 'formatUtcOffset': '%@' + }); + }; + UberRouter.prototype.autoGrowInput = function() { + return $('.editable input').autoGrowInput(); + }; + UberRouter.prototype.windowTitle = function(title) { + return $(document).attr('title', title); + }; + return UberRouter; + })(); +}).call(this); +}, "web-lib/uber_show_view": function(exports, require, module) {(function() { + var UberView; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + UberView = require('web-lib/uber_view').UberView; + exports.UberShowView = (function() { + __extends(UberShowView, UberView); + function UberShowView() { + UberShowView.__super__.constructor.apply(this, arguments); + } + UberShowView.prototype.view = 'show'; + UberShowView.prototype.events = { + 'click #edit': 'edit', + 'submit form': 'save', + 'click .cancel': 'cancel' + }; + UberShowView.prototype.errors = null; + UberShowView.prototype.showTemplate = null; + UberShowView.prototype.editTemplate = null; + UberShowView.prototype.initialize = function() { + if (this.init_hook) { + this.init_hook(); + } + _.bindAll(this, 'render'); + return this.model.bind('change', this.render); + }; + UberShowView.prototype.render = function() { + var $el; + $el = $(this.el); + this.selectView(); + if (this.view === 'show') { + $el.html(this.showTemplate({ + model: this.model + })); + } else if (this.view === 'edit') { + $el.html(this.editTemplate({ + model: this.model, + errors: this.errors || {}, + collections: this.collections || {} + })); + } else { + $el.html(this.newTemplate({ + model: this.model, + errors: this.errors || {}, + collections: this.collections || {} + })); + } + if (this.render_hook) { + this.render_hook(); + } + this.errors = null; + this.userIdsToLinkedNames(); + this.datePickers(); + return this.place(); + }; + UberShowView.prototype.selectView = function() { + var url; + if (this.options.urlRendering) { + url = window.location.hash; + if (url.match(/\/new/)) { + return this.view = 'new'; + } else if (url.match(/\/edit/)) { + return this.view = 'edit'; + } else { + return this.view = 'show'; + } + } + }; + UberShowView.prototype.edit = function(e) { + e.preventDefault(); + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id') + '/edit'; + } else { + this.view = 'edit'; + } + return this.model.change(); + }; + UberShowView.prototype.save = function(e) { + var attributes, ele, form_attrs, _i, _len, _ref; + e.preventDefault(); + attributes = $(e.currentTarget).serializeToJson(); + form_attrs = {}; + _ref = $('input[type="radio"]'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + ele = _ref[_i]; + if ($(ele).is(':checked')) { + form_attrs[$(ele).attr('name')] = $(ele).attr('value'); + } + } + attributes = _.extend(attributes, form_attrs); + if (this.relationships) { + attributes = _.extend(attributes, { + relationships: this.relationships + }); + } + if (this.filter_attributes != null) { + this.filter_attributes(attributes); + } + return this.model.save(attributes, { + silent: true, + success: __bind(function(model) { + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id'); + } else { + this.view = 'show'; + } + return this.flash('success', "Uber save!"); + }, this), + statusCode: { + 406: __bind(function(xhr) { + this.errors = JSON.parse(xhr.responseText); + return this.flash('error', 'That was not Uber.'); + }, this) + }, + error: __bind(function(model, xhr) { + var code, message, responseJSON, responseText; + code = xhr.status; + responseText = xhr.responseText; + if (responseText) { + responseJSON = JSON.parse(responseText); + } + if (responseJSON && (typeof responseJSON === 'object') && (responseJSON.hasOwnProperty('error'))) { + message = responseJSON.error; + } + return this.flash('error', (code || 'Unknown') + ' error' + (': ' + message || '')); + }, this), + complete: __bind(function() { + return this.model.change(); + }, this) + }); + }; + UberShowView.prototype.cancel = function(e) { + e.preventDefault(); + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id'); + } else { + this.view = 'show'; + } + return this.model.fetch({ + silent: true, + complete: __bind(function() { + return this.model.change(); + }, this) + }); + }; + return UberShowView; + })(); +}).call(this); +}, "web-lib/uber_sync": function(exports, require, module) {(function() { + var methodType; + var __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }; + methodType = { + create: 'POST', + update: 'PUT', + "delete": 'DELETE', + read: 'GET' + }; + exports.UberSync = function(method, model, options) { + var token; + options.type = methodType[method]; + options.url = _.isString(this.url) ? '/api' + this.url : '/api' + this.url(options.type); + options.data = _.extend({}, options.data); + if (__indexOf.call(_.keys(options.data), "city_id") < 0) { + if ($.cookie('city_filter')) { + _.extend(options.data, { + city_id: $.cookie('city_filter') + }); + } + } else { + delete options.data['city_id']; + } + if (options.type === 'POST' || options.type === 'PUT') { + _.extend(options.data, model.toJSON()); + } + token = $.cookie('token') ? $.cookie('token') : typeof USER !== "undefined" && USER !== null ? USER.get('token') : ""; + _.extend(options.data, { + token: token + }); + if (method === "delete") { + options.contentType = 'application/json'; + options.data = JSON.stringify(options.data); + } + return $.ajax(options); + }; +}).call(this); +}, "web-lib/uber_view": function(exports, require, module) {(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberView = (function() { + __extends(UberView, Backbone.View); + function UberView() { + this.processDocumentUpload = __bind(this.processDocumentUpload, this); + UberView.__super__.constructor.apply(this, arguments); + } + UberView.prototype.className = 'view_container'; + UberView.prototype.hashId = function() { + return parseInt(location.hash.split('/')[2]); + }; + UberView.prototype.place = function(content) { + var $target; + $target = this.options.scope ? this.options.scope.find(this.options.selector) : $(this.options.selector); + $target[this.options.method || 'html'](content || this.el); + this.delegateEvents(); + $('#spinner').hide(); + return this; + }; + UberView.prototype.mixin = function(m, args) { + var events, self; + if (args == null) { + args = {}; + } + self = this; + events = m._events; + _.extend(this, m); + if (m.initialize) { + m.initialize(self, args); + } + return _.each(_.keys(events), function(key) { + var event, func, selector, split; + split = key.split(' '); + event = split[0]; + selector = split[1]; + func = events[key]; + return $(self.el).find(selector).live(event, function(e) { + return self[func](e); + }); + }); + }; + UberView.prototype.datePickers = function(format) { + if (format == null) { + format = "%Z-%m-%dT%H:%i:%s%:"; + } + $('.datepicker').AnyTime_noPicker(); + return $('.datepicker').AnyTime_picker({ + 'format': format, + 'formatUtcOffset': '%@' + }); + }; + UberView.prototype.dataTable = function(collection, selector, options, params, cols) { + var defaults; + if (selector == null) { + selector = 'table'; + } + if (options == null) { + options = {}; + } + if (params == null) { + params = {}; + } + if (cols == null) { + cols = []; + } + $(selector).empty(); + if (!cols.length) { + cols = collection.defaultColumns; + } + defaults = { + aoColumns: collection.tableColumns(cols), + bDestroy: true, + bSort: false, + bProcessing: true, + bFilter: false, + bServerSide: true, + bPaginate: true, + bScrollInfinite: true, + bScrollCollapse: true, + sScrollY: '600px', + iDisplayLength: 50, + fnServerData: function(source, data, callback) { + var defaultParams; + defaultParams = { + limit: data[4].value, + offset: data[3].value + }; + return collection.fetch({ + data: _.extend(defaultParams, params), + success: function() { + return callback({ + aaData: collection.toTableRows(cols), + iTotalRecords: collection.meta.count, + iTotalDisplayRecords: collection.meta.count + }); + }, + error: function() { + return new Error({ + message: 'Loading error.' + }); + } + }); + }, + fnRowCallback: function(nRow, aData, iDisplayIndex, iDisplayIndexFull) { + $('[data-tooltip]', nRow).qtip({ + content: { + attr: 'data-tooltip' + }, + style: { + classes: "ui-tooltip-light ui-tooltip-rounded ui-tooltip-shadow" + } + }); + return nRow; + } + }; + return $(this.el).find(selector).dataTable(_.extend(defaults, options)); + }; + UberView.prototype.dataTableLocal = function(collection, selector, options, params, cols) { + var $dataTable, defaults; + if (selector == null) { + selector = 'table'; + } + if (options == null) { + options = {}; + } + if (params == null) { + params = {}; + } + if (cols == null) { + cols = []; + } + $(selector).empty(); + if (!cols.length || cols.length === 0) { + cols = collection.defaultColumns; + } + defaults = { + aaData: collection.toTableRows(cols), + aoColumns: collection.tableColumns(cols), + bDestroy: true, + bSort: false, + bProcessing: true, + bFilter: false, + bScrollInfinite: true, + bScrollCollapse: true, + sScrollY: '600px', + iDisplayLength: -1 + }; + $dataTable = $(this.el).find(selector).dataTable(_.extend(defaults, options)); + _.delay(__bind(function() { + if ($dataTable && $dataTable.length > 0) { + return $dataTable.fnAdjustColumnSizing(); + } + }, this), 1); + return $dataTable; + }; + UberView.prototype.reverseGeocode = function() { + var $el; + return ''; + $el = $(this.el); + return this.requireMaps(function() { + var geocoder; + geocoder = new google.maps.Geocoder(); + return $el.find('[data-point]').each(function() { + var $this, latLng, point; + $this = $(this); + point = JSON.parse($this.attr('data-point')); + latLng = new google.maps.LatLng(point.latitude, point.longitude); + return geocoder.geocode({ + latLng: latLng + }, function(data, status) { + if (status === google.maps.GeocoderStatus.OK) { + return $this.text(data[0].formatted_address); + } + }); + }); + }); + }; + UberView.prototype.userIdsToLinkedNames = function() { + var $el; + $el = $(this.el); + return $el.find('a[data-user-id][data-user-type]').each(function() { + var $this, user, userType; + $this = $(this); + userType = $this.attr('data-user-type') === 'user' ? 'client' : $this.attr('data-user-type'); + user = new app.models[userType]({ + id: $this.attr('data-user-id') + }); + return user.fetch({ + success: function(user) { + return $this.html(app.helpers.linkedName(user)).attr('href', "!/" + user.role + "s/" + user.id); + }, + error: function() { + if ($this.attr('data-user-type') === 'user') { + user = new app.models['driver']({ + id: $this.attr('data-user-id') + }); + return user.fetch({ + success: function(user) { + return $this.html(app.helpers.linkedName(user)).attr('href', "!/driver/" + user.id); + } + }); + } + } + }); + }); + }; + UberView.prototype.selectedCity = function() { + var $selected, city, cityFilter; + cityFilter = $.cookie('city_filter'); + $selected = $("#city_filter option[value=" + cityFilter + "]"); + if (city_filter && $selected.length) { + return city = { + lat: parseFloat($selected.attr('data-lat')), + lng: parseFloat($selected.attr('data-lng')), + timezone: $selected.attr('data-timezone') + }; + } else { + return city = { + lat: 37.775, + lng: -122.45, + timezone: 'Etc/UTC' + }; + } + }; + UberView.prototype.updateModel = function(e, success) { + var $el, attrs, model, self; + e.preventDefault(); + $el = $(e.currentTarget); + self = this; + model = new this.model.__proto__.constructor({ + id: this.model.id + }); + attrs = {}; + $el.find('[name]').each(function() { + var $this; + $this = $(this); + return attrs["" + ($this.attr('name'))] = $this.val(); + }); + self.model.set(attrs); + $el.find('span.error').text(''); + return model.save(attrs, { + complete: function(xhr) { + var response; + response = JSON.parse(xhr.responseText); + switch (xhr.status) { + case 200: + self.model = model; + $el.find('[name]').val(''); + if (success) { + return success(); + } + break; + case 406: + return _.each(response, function(error, field) { + return $el.find("[name=" + field + "]").parent().find('span.error').text(error); + }); + default: + return this.unanticipatedError(response); + } + } + }); + }; + UberView.prototype.autoUpdateModel = function(e) { + var $el, arg, model, self, val; + $el = $(e.currentTarget); + val = $el.val(); + self = this; + if (val !== this.model.get($el.attr('id'))) { + arg = {}; + arg[$el.attr('id')] = $el.is(':checkbox') ? $el.is(':checked') ? 1 : 0 : val; + $('.editable span').empty(); + this.model.set(arg); + model = new this.model.__proto__.constructor({ + id: this.model.id + }); + return model.save(arg, { + complete: function(xhr) { + var key, response, _i, _len, _ref, _results; + response = JSON.parse(xhr.responseText); + switch (xhr.status) { + case 200: + self.flash('success', 'Saved!'); + return $el.blur(); + case 406: + self.flash('error', 'That was not Uber.'); + _ref = _.keys(response); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + _results.push($el.parent().find('span').html(response[key])); + } + return _results; + break; + default: + return self.unanticipatedError; + } + } + }); + } + }; + UberView.prototype.unanticipatedError = function(response) { + return self.flash('error', response); + }; + UberView.prototype.flash = function(type, text) { + var $banner; + $banner = $("." + type); + $banner.find('p').text(text).end().css('border', '1px solid #999').animate({ + top: 0 + }, 500); + return setTimeout(function() { + return $banner.animate({ + top: -$banner.outerHeight() + }, 500); + }, 3000); + }; + UberView.prototype.requireMaps = function(callback) { + if (typeof google !== 'undefined' && google.maps) { + return callback(); + } else { + return $.getScript("https://www.google.com/jsapi?key=" + CONFIG.googleJsApiKey, function() { + return google.load('maps', 3, { + callback: callback, + other_params: 'sensor=false&language=en' + }); + }); + } + }; + UberView.prototype.select_drop_down = function(model, key) { + var value; + value = model.get(key); + if (value) { + return $("select[id='" + key + "'] option[value='" + value + "']").attr('selected', 'selected'); + } + }; + UberView.prototype.processDocumentUpload = function(e) { + var $fi, $form, arbData, curDate, data, expDate, expM, expY, expiration, fileElementId, invalid; + e.preventDefault(); + $form = $(e.currentTarget); + $fi = $("input[type=file]", $form); + $(".validationError").removeClass("validationError"); + if (!$fi.val()) { + return $fi.addClass("validationError"); + } else { + fileElementId = $fi.attr('id'); + expY = $("select[name=expiration-year]", $form).val(); + expM = $("select[name=expiration-month]", $form).val(); + invalid = false; + if (expY && expM) { + expDate = new Date(expY, expM, 28); + curDate = new Date(); + if (expDate < curDate) { + invalid = true; + $(".expiration", $form).addClass("validationError"); + } + expiration = "" + expY + "-" + expM + "-28T23:59:59Z"; + } + arbData = {}; + $(".arbitraryField", $form).each(__bind(function(i, e) { + arbData[$(e).attr('name')] = $(e).val(); + if ($(e).val() === "") { + invalid = true; + return $(e).addClass("validationError"); + } + }, this)); + if (!invalid) { + data = { + token: $.cookie('token') || USER.get('token'), + name: $("input[name=fileName]", $form).val(), + meta: escape(JSON.stringify(arbData)), + user_id: $("input[name=driver_id]", $form).val(), + vehicle_id: $("input[name=vehicle_id]", $form).val() + }; + if (expiration) { + data['expiration'] = expiration; + } + $("#spinner").show(); + return $.ajaxFileUpload({ + url: '/api/documents', + secureuri: false, + fileElementId: fileElementId, + data: data, + complete: __bind(function(resp, status) { + var key, _i, _len, _ref, _results; + $("#spinner").hide(); + if (status === "success") { + if (this.model) { + this.model.refetch(); + } else { + USER.refetch(); + } + } + if (status === "error") { + _ref = _.keys(resp); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + _results.push($("*[name=" + key + "]", $form).addClass("validationError")); + } + return _results; + } + }, this) + }); + } + } + }; + return UberView; + })(); +}).call(this); +}, "web-lib/views/footer": function(exports, require, module) {(function() { + var footerTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + footerTemplate = require('web-lib/templates/footer'); + exports.SharedFooterView = (function() { + __extends(SharedFooterView, Backbone.View); + function SharedFooterView() { + SharedFooterView.__super__.constructor.apply(this, arguments); + } + SharedFooterView.prototype.id = 'footer_view'; + SharedFooterView.prototype.events = { + 'click .language': 'intl_set_cookie_locale' + }; + SharedFooterView.prototype.render = function() { + $(this.el).html(footerTemplate()); + this.delegateEvents(); + return this; + }; + SharedFooterView.prototype.intl_set_cookie_locale = function(e) { + var _ref; + i18n.setLocale(e != null ? (_ref = e.srcElement) != null ? _ref.id : void 0 : void 0); + return location.reload(); + }; + return SharedFooterView; + })(); +}).call(this); +}}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js new file mode 100755 index 00000000..61307eeb --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js @@ -0,0 +1,15 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("embed-tokens.js", "utf8").replace(/^#.*$/mg, ""); +var ast = jsp.parse(code, null, true); + +// trololo +function fooBar() {} + +console.log(sys.inspect(ast, null, null)); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js new file mode 100644 index 00000000..945960c2 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js @@ -0,0 +1,26 @@ +function unique(arqw) { + var a = [], i, j + outer: for (i = 0; i < arqw.length; i++) { + for (j = 0; j < a.length; j++) { + if (a[j] == arqw[i]) { + continue outer + } + } + a[a.length] = arqw[i] + } + return a +} + + +function unique(arqw) { + var crap = [], i, j + outer: for (i = 0; i < arqw.length; i++) { + for (j = 0; j < crap.length; j++) { + if (crap[j] == arqw[i]) { + continue outer + } + } + crap[crap.length] = arqw[i] + } + return crap +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js new file mode 100644 index 00000000..d13b2bc0 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js @@ -0,0 +1,8 @@ +function q(qooo) { + var a; + foo: for(;;) { + a++; + if (something) break foo; + return qooo; + } +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js new file mode 100644 index 00000000..4bf2b94d --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js @@ -0,0 +1,33 @@ +function foo(arg1, arg2, arg3, arg4, arg5, arg6) { + var a = 5; + { + var d = 10, mak = 20, buz = 30; + var q = buz * 2; + } + if (moo) { + var a, b, c; + } + for (var arg1 = 0, d = 20; arg1 < 10; ++arg1) + console.log(arg3); + for (var i in mak) {} + for (j in d) {} + var d; + + function test() { + + }; + + //test(); + + (function moo(first, second){ + console.log(first); + })(1); + + (function moo(first, second){ + console.log(moo()); + })(1); +} + + +var foo; +var bar; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js new file mode 100644 index 00000000..c6a9d798 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js @@ -0,0 +1,97 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", // XXX: "block" is safer + [ [ "stat", + [ "call", [ "name", "trace" ], + [ [ "string", this[0].toString() ], + [ "num", this[0].start.line ], + [ "num", this[0].start.col ], + [ "num", this[0].end.line ], + [ "num", this[0].end.col ]]]], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + }; + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + // note however that the following is broken. I guess we + // should add the block brackets in this case... + for (var i = 0; i < 5; ++i) + console.log("foo"); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js new file mode 100644 index 00000000..6aee5f3f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js @@ -0,0 +1,138 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + function trace (line, comment) { + var code = pro.gen_code(line, { beautify: true }); + var data = line[0] + + var args = [] + if (!comment) comment = "" + if (typeof data === "object") { + code = code.split(/\n/).shift() + args = [ [ "string", data.toString() ], + [ "string", code ], + [ "num", data.start.line ], + [ "num", data.start.col ], + [ "num", data.end.line ], + [ "num", data.end.col ]] + } else { + args = [ [ "string", data ], + [ "string", code ]] + + } + return [ "call", [ "name", "trace" ], args ]; + } + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", + [ [ "stat", trace(this) ], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + } + + function do_cond(c, t, f) { + return [ this[0], w.walk(c), + ["seq", trace(t), w.walk(t) ], + ["seq", trace(f), w.walk(f) ]]; + } + + function do_binary(c, l, r) { + if (c !== "&&" && c !== "||") { + return [this[0], c, w.walk(l), w.walk(r)]; + } + return [ this[0], c, + ["seq", trace(l), w.walk(l) ], + ["seq", trace(r), w.walk(r) ]]; + } + + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat, + "conditional" : do_cond, + "binary" : do_binary + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + for (var i = 0; i < 5; ++i) + console.log("foo"); + + for (var i = 0; i < 5; ++i) { + console.log("foo"); + } + + var k = plurp() ? 1 : 0; + var x = a ? doX(y) && goZoo("zoo") + : b ? blerg({ x: y }) + : null; + + var x = X || Y; +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js new file mode 100644 index 00000000..2f4b7fe2 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js @@ -0,0 +1,8 @@ +var UNUSED_VAR1 = 19; + +function main() { + var unused_var2 = 20; + alert(100); +} + +main(); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js new file mode 100755 index 00000000..f295fba8 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js @@ -0,0 +1,30 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("hoist.js", "utf8"); +var ast = jsp.parse(code); + +ast = pro.ast_lift_variables(ast); + +var w = pro.ast_walker(); +ast = w.with_walkers({ + "function": function() { + var node = w.dive(this); // walk depth first + console.log(pro.gen_code(node, { beautify: true })); + return node; + }, + "name": function(name) { + return [ this[0], "X" ]; + } +}, function(){ + return w.walk(ast); +}); + +console.log(pro.gen_code(ast, { + beautify: true +})); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js new file mode 100644 index 00000000..0d5b7e0e --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js @@ -0,0 +1,3930 @@ +/** + * @fileoverview + * + * JsWorld + * + *

Javascript library for localised formatting and parsing of: + *

    + *
  • Numbers + *
  • Dates and times + *
  • Currency + *
+ * + *

The library classes are configured with standard POSIX locale definitions + * derived from Unicode's Common Locale Data Repository (CLDR). + * + *

Website: JsWorld + * + * @author Vladimir Dzhuvinov + * @version 2.5 (2011-12-23) + */ + + + +/** + * @namespace Namespace container for the JsWorld library objects. + */ +jsworld = {}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 date/time + * string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the + * current date/time will be used. + * @param {Boolean} [withTZ] Include timezone offset, default false. + * + * @returns {String} The date/time formatted as YYYY-MM-DD HH:MM:SS. + */ +jsworld.formatIsoDateTime = function(d, withTZ) { + + if (typeof d === "undefined") + d = new Date(); // now + + if (typeof withTZ === "undefined") + withTZ = false; + + var s = jsworld.formatIsoDate(d) + " " + jsworld.formatIsoTime(d); + + if (withTZ) { + + var diff = d.getHours() - d.getUTCHours(); + var hourDiff = Math.abs(diff); + + var minuteUTC = d.getUTCMinutes(); + var minute = d.getMinutes(); + + if (minute != minuteUTC && minuteUTC < 30 && diff < 0) + hourDiff--; + + if (minute != minuteUTC && minuteUTC > 30 && diff > 0) + hourDiff--; + + var minuteDiff; + if (minute != minuteUTC) + minuteDiff = ":30"; + else + minuteDiff = ":00"; + + var timezone; + if (hourDiff < 10) + timezone = "0" + hourDiff + minuteDiff; + + else + timezone = "" + hourDiff + minuteDiff; + + if (diff < 0) + timezone = "-" + timezone; + + else + timezone = "+" + timezone; + + s = s + timezone; + } + + return s; +}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 date string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the current + * date will be used. + * + * @returns {String} The date formatted as YYYY-MM-DD. + */ +jsworld.formatIsoDate = function(d) { + + if (typeof d === "undefined") + d = new Date(); // now + + var year = d.getFullYear(); + var month = d.getMonth() + 1; + var day = d.getDate(); + + return year + "-" + jsworld._zeroPad(month, 2) + "-" + jsworld._zeroPad(day, 2); +}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 time string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the current + * time will be used. + * + * @returns {String} The time formatted as HH:MM:SS. + */ +jsworld.formatIsoTime = function(d) { + + if (typeof d === "undefined") + d = new Date(); // now + + var hour = d.getHours(); + var minute = d.getMinutes(); + var second = d.getSeconds(); + + return jsworld._zeroPad(hour, 2) + ":" + jsworld._zeroPad(minute, 2) + ":" + jsworld._zeroPad(second, 2); +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted date/time string to a JavaScript + * Date object. + * + * @param {String} isoDateTimeVal An ISO-8601 formatted date/time string. + * + *

Accepted formats: + * + *

    + *
  • YYYY-MM-DD HH:MM:SS + *
  • YYYYMMDD HHMMSS + *
  • YYYY-MM-DD HHMMSS + *
  • YYYYMMDD HH:MM:SS + *
+ * + * @returns {Date} The corresponding Date object. + * + * @throws Error on a badly formatted date/time string or on a invalid date. + */ +jsworld.parseIsoDateTime = function(isoDateTimeVal) { + + if (typeof isoDateTimeVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "YYYY-MM-DD HH:MM:SS" format + var matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/); + + // If unsuccessful, try to match "YYYYMMDD HHMMSS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)(\d\d)(\d\d)[T ](\d\d)(\d\d)(\d\d)/); + + // ... try to match "YYYY-MM-DD HHMMSS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d)(\d\d)(\d\d)/); + + // ... try to match "YYYYMMDD HH:MM:SS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date/time string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var year = parseInt(matches[1], 10); + var month = parseInt(matches[2], 10); + var day = parseInt(matches[3], 10); + + var hour = parseInt(matches[4], 10); + var mins = parseInt(matches[5], 10); + var secs = parseInt(matches[6], 10); + + // Simple value range check, leap years not checked + // Note: the originial ISO time spec for leap hours (24:00:00) and seconds (00:00:60) is not supported + if (month < 1 || month > 12 || + day < 1 || day > 31 || + hour < 0 || hour > 23 || + mins < 0 || mins > 59 || + secs < 0 || secs > 59 ) + + throw "Error: Invalid ISO-8601 date/time value"; + + var d = new Date(year, month - 1, day, hour, mins, secs); + + // Check if the input date was valid + // (JS Date does automatic forward correction) + if (d.getDate() != day || d.getMonth() +1 != month) + throw "Error: Invalid date"; + + return d; +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted date string to a JavaScript + * Date object. + * + * @param {String} isoDateVal An ISO-8601 formatted date string. + * + *

Accepted formats: + * + *

    + *
  • YYYY-MM-DD + *
  • YYYYMMDD + *
+ * + * @returns {Date} The corresponding Date object. + * + * @throws Error on a badly formatted date string or on a invalid date. + */ +jsworld.parseIsoDate = function(isoDateVal) { + + if (typeof isoDateVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "YYYY-MM-DD" format + var matches = isoDateVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/); + + // If unsuccessful, try to match "YYYYMMDD" format + if (matches === null) + matches = isoDateVal.match(/^(\d\d\d\d)(\d\d)(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var year = parseInt(matches[1], 10); + var month = parseInt(matches[2], 10); + var day = parseInt(matches[3], 10); + + // Simple value range check, leap years not checked + if (month < 1 || month > 12 || + day < 1 || day > 31 ) + + throw "Error: Invalid ISO-8601 date value"; + + var d = new Date(year, month - 1, day); + + // Check if the input date was valid + // (JS Date does automatic forward correction) + if (d.getDate() != day || d.getMonth() +1 != month) + throw "Error: Invalid date"; + + return d; +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted time string to a JavaScript + * Date object. + * + * @param {String} isoTimeVal An ISO-8601 formatted time string. + * + *

Accepted formats: + * + *

    + *
  • HH:MM:SS + *
  • HHMMSS + *
+ * + * @returns {Date} The corresponding Date object, with year, month and day set + * to zero. + * + * @throws Error on a badly formatted time string. + */ +jsworld.parseIsoTime = function(isoTimeVal) { + + if (typeof isoTimeVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "HH:MM:SS" format + var matches = isoTimeVal.match(/^(\d\d):(\d\d):(\d\d)/); + + // If unsuccessful, try to match "HHMMSS" format + if (matches === null) + matches = isoTimeVal.match(/^(\d\d)(\d\d)(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date/time string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var hour = parseInt(matches[1], 10); + var mins = parseInt(matches[2], 10); + var secs = parseInt(matches[3], 10); + + // Simple value range check, leap years not checked + if (hour < 0 || hour > 23 || + mins < 0 || mins > 59 || + secs < 0 || secs > 59 ) + + throw "Error: Invalid ISO-8601 time value"; + + return new Date(0, 0, 0, hour, mins, secs); +}; + + +/** + * @private + * + * @description Trims leading and trailing whitespace from a string. + * + *

Used non-regexp the method from http://blog.stevenlevithan.com/archives/faster-trim-javascript + * + * @param {String} str The string to trim. + * + * @returns {String} The trimmed string. + */ +jsworld._trim = function(str) { + + var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000'; + + for (var i = 0; i < str.length; i++) { + + if (whitespace.indexOf(str.charAt(i)) === -1) { + str = str.substring(i); + break; + } + } + + for (i = str.length - 1; i >= 0; i--) { + if (whitespace.indexOf(str.charAt(i)) === -1) { + str = str.substring(0, i + 1); + break; + } + } + + return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''; +}; + + + +/** + * @private + * + * @description Returns true if the argument represents a decimal number. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents a decimal number, + * otherwise false. + */ +jsworld._isNumber = function(arg) { + + if (typeof arg == "number") + return true; + + if (typeof arg != "string") + return false; + + // ensure string + var s = arg + ""; + + return (/^-?(\d+|\d*\.\d+)$/).test(s); +}; + + +/** + * @private + * + * @description Returns true if the argument represents a decimal integer. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents an integer, otherwise + * false. + */ +jsworld._isInteger = function(arg) { + + if (typeof arg != "number" && typeof arg != "string") + return false; + + // convert to string + var s = arg + ""; + + return (/^-?\d+$/).test(s); +}; + + +/** + * @private + * + * @description Returns true if the argument represents a decimal float. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents a float, otherwise false. + */ +jsworld._isFloat = function(arg) { + + if (typeof arg != "number" && typeof arg != "string") + return false; + + // convert to string + var s = arg + ""; + + return (/^-?\.\d+?$/).test(s); +}; + + +/** + * @private + * + * @description Checks if the specified formatting option is contained + * within the options string. + * + * @param {String} option The option to search for. + * @param {String} optionsString The options string. + * + * @returns {Boolean} true if the flag is found, else false + */ +jsworld._hasOption = function(option, optionsString) { + + if (typeof option != "string" || typeof optionsString != "string") + return false; + + if (optionsString.indexOf(option) != -1) + return true; + else + return false; +}; + + +/** + * @private + * + * @description String replacement function. + * + * @param {String} s The string to work on. + * @param {String} target The string to search for. + * @param {String} replacement The replacement. + * + * @returns {String} The new string. + */ +jsworld._stringReplaceAll = function(s, target, replacement) { + + var out; + + if (target.length == 1 && replacement.length == 1) { + // simple char/char case somewhat faster + out = ""; + + for (var i = 0; i < s.length; i++) { + + if (s.charAt(i) == target.charAt(0)) + out = out + replacement.charAt(0); + else + out = out + s.charAt(i); + } + + return out; + } + else { + // longer target and replacement strings + out = s; + + var index = out.indexOf(target); + + while (index != -1) { + + out = out.replace(target, replacement); + + index = out.indexOf(target); + } + + return out; + } +}; + + +/** + * @private + * + * @description Tests if a string starts with the specified substring. + * + * @param {String} testedString The string to test. + * @param {String} sub The string to match. + * + * @returns {Boolean} true if the test succeeds. + */ +jsworld._stringStartsWith = function (testedString, sub) { + + if (testedString.length < sub.length) + return false; + + for (var i = 0; i < sub.length; i++) { + if (testedString.charAt(i) != sub.charAt(i)) + return false; + } + + return true; +}; + + +/** + * @private + * + * @description Gets the requested precision from an options string. + * + *

Example: ".3" returns 3 decimal places precision. + * + * @param {String} optionsString The options string. + * + * @returns {integer Number} The requested precision, -1 if not specified. + */ +jsworld._getPrecision = function (optionsString) { + + if (typeof optionsString != "string") + return -1; + + var m = optionsString.match(/\.(\d)/); + if (m) + return parseInt(m[1], 10); + else + return -1; +}; + + +/** + * @private + * + * @description Takes a decimal numeric amount (optionally as string) and + * returns its integer and fractional parts packed into an object. + * + * @param {Number|String} amount The amount, e.g. "123.45" or "-56.78" + * + * @returns {object} Parsed amount object with properties: + * {String} integer : the integer part + * {String} fraction : the fraction part + */ +jsworld._splitNumber = function (amount) { + + if (typeof amount == "number") + amount = amount + ""; + + var obj = {}; + + // remove negative sign + if (amount.charAt(0) == "-") + amount = amount.substring(1); + + // split amount into integer and decimal parts + var amountParts = amount.split("."); + if (!amountParts[1]) + amountParts[1] = ""; // we need "" instead of null + + obj.integer = amountParts[0]; + obj.fraction = amountParts[1]; + + return obj; +}; + + +/** + * @private + * + * @description Formats the integer part using the specified grouping + * and thousands separator. + * + * @param {String} intPart The integer part of the amount, as string. + * @param {String} grouping The grouping definition. + * @param {String} thousandsSep The thousands separator. + * + * @returns {String} The formatted integer part. + */ +jsworld._formatIntegerPart = function (intPart, grouping, thousandsSep) { + + // empty separator string? no grouping? + // -> return immediately with no formatting! + if (thousandsSep == "" || grouping == "-1") + return intPart; + + // turn the semicolon-separated string of integers into an array + var groupSizes = grouping.split(";"); + + // the formatted output string + var out = ""; + + // the intPart string position to process next, + // start at string end, e.g. "10000000 0) { + + // get next group size (if any, otherwise keep last) + if (groupSizes.length > 0) + size = parseInt(groupSizes.shift(), 10); + + // int parse error? + if (isNaN(size)) + throw "Error: Invalid grouping"; + + // size is -1? -> no more grouping, so just copy string remainder + if (size == -1) { + out = intPart.substring(0, pos) + out; + break; + } + + pos -= size; // move to next sep. char. position + + // position underrun? -> just copy string remainder + if (pos < 1) { + out = intPart.substring(0, pos + size) + out; + break; + } + + // extract group and apply sep. char. + out = thousandsSep + intPart.substring(pos, pos + size) + out; + } + + return out; +}; + + +/** + * @private + * + * @description Formats the fractional part to the specified decimal + * precision. + * + * @param {String} fracPart The fractional part of the amount + * @param {integer Number} precision The desired decimal precision + * + * @returns {String} The formatted fractional part. + */ +jsworld._formatFractionPart = function (fracPart, precision) { + + // append zeroes up to precision if necessary + for (var i=0; fracPart.length < precision; i++) + fracPart = fracPart + "0"; + + return fracPart; +}; + + +/** + * @private + * + * @desription Converts a number to string and pad it with leading zeroes if the + * string is shorter than length. + * + * @param {integer Number} number The number value subjected to selective padding. + * @param {integer Number} length If the number has fewer digits than this length + * apply padding. + * + * @returns {String} The formatted string. + */ +jsworld._zeroPad = function(number, length) { + + // ensure string + var s = number + ""; + + while (s.length < length) + s = "0" + s; + + return s; +}; + + +/** + * @private + * @description Converts a number to string and pads it with leading spaces if + * the string is shorter than length. + * + * @param {integer Number} number The number value subjected to selective padding. + * @param {integer Number} length If the number has fewer digits than this length + * apply padding. + * + * @returns {String} The formatted string. + */ +jsworld._spacePad = function(number, length) { + + // ensure string + var s = number + ""; + + while (s.length < length) + s = " " + s; + + return s; +}; + + + +/** + * @class + * Represents a POSIX-style locale with its numeric, monetary and date/time + * properties. Also provides a set of locale helper methods. + * + *

The locale properties follow the POSIX standards: + * + *

+ * + * @public + * @constructor + * @description Creates a new locale object (POSIX-style) with the specified + * properties. + * + * @param {object} properties An object containing the raw locale properties: + * + * @param {String} properties.decimal_point + * + * A string containing the symbol that shall be used as the decimal + * delimiter (radix character) in numeric, non-monetary formatted + * quantities. This property cannot be omitted and cannot be set to the + * empty string. + * + * + * @param {String} properties.thousands_sep + * + * A string containing the symbol that shall be used as a separator for + * groups of digits to the left of the decimal delimiter in numeric, + * non-monetary formatted monetary quantities. + * + * + * @param {String} properties.grouping + * + * Defines the size of each group of digits in formatted non-monetary + * quantities. The operand is a sequence of integers separated by + * semicolons. Each integer specifies the number of digits in each group, + * with the initial integer defining the size of the group immediately + * preceding the decimal delimiter, and the following integers defining + * the preceding groups. If the last integer is not -1, then the size of + * the previous group (if any) shall be repeatedly used for the + * remainder of the digits. If the last integer is -1, then no further + * grouping shall be performed. + * + * + * @param {String} properties.int_curr_symbol + * + * The first three letters signify the ISO-4217 currency code, + * the fourth letter is the international symbol separation character + * (normally a space). + * + * + * @param {String} properties.currency_symbol + * + * The local shorthand currency symbol, e.g. "$" for the en_US locale + * + * + * @param {String} properties.mon_decimal_point + * + * The symbol to be used as the decimal delimiter (radix character) + * + * + * @param {String} properties.mon_thousands_sep + * + * The symbol to be used as a separator for groups of digits to the + * left of the decimal delimiter. + * + * + * @param {String} properties.mon_grouping + * + * A string that defines the size of each group of digits. The + * operand is a sequence of integers separated by semicolons (";"). + * Each integer specifies the number of digits in each group, with the + * initial integer defining the size of the group preceding the + * decimal delimiter, and the following integers defining the + * preceding groups. If the last integer is not -1, then the size of + * the previous group (if any) must be repeatedly used for the + * remainder of the digits. If the last integer is -1, then no + * further grouping is to be performed. + * + * + * @param {String} properties.positive_sign + * + * The string to indicate a non-negative monetary amount. + * + * + * @param {String} properties.negative_sign + * + * The string to indicate a negative monetary amount. + * + * + * @param {integer Number} properties.frac_digits + * + * An integer representing the number of fractional digits (those to + * the right of the decimal delimiter) to be written in a formatted + * monetary quantity using currency_symbol. + * + * + * @param {integer Number} properties.int_frac_digits + * + * An integer representing the number of fractional digits (those to + * the right of the decimal delimiter) to be written in a formatted + * monetary quantity using int_curr_symbol. + * + * + * @param {integer Number} properties.p_cs_precedes + * + * An integer set to 1 if the currency_symbol precedes the value for a + * monetary quantity with a non-negative value, and set to 0 if the + * symbol succeeds the value. + * + * + * @param {integer Number} properties.n_cs_precedes + * + * An integer set to 1 if the currency_symbol precedes the value for a + * monetary quantity with a negative value, and set to 0 if the symbol + * succeeds the value. + * + * + * @param {integer Number} properties.p_sep_by_space + * + * Set to a value indicating the separation of the currency_symbol, + * the sign string, and the value for a non-negative formatted monetary + * quantity: + * + *

0 No space separates the currency symbol and value.

+ * + *

1 If the currency symbol and sign string are adjacent, a space + * separates them from the value; otherwise, a space separates + * the currency symbol from the value.

+ * + *

2 If the currency symbol and sign string are adjacent, a space + * separates them; otherwise, a space separates the sign string + * from the value.

+ * + * + * @param {integer Number} properties.n_sep_by_space + * + * Set to a value indicating the separation of the currency_symbol, + * the sign string, and the value for a negative formatted monetary + * quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.p_sign_posn + * + * An integer set to a value indicating the positioning of the + * positive_sign for a monetary quantity with a non-negative value: + * + *

0 Parentheses enclose the quantity and the currency_symbol.

+ * + *

1 The sign string precedes the quantity and the currency_symbol.

+ * + *

2 The sign string succeeds the quantity and the currency_symbol.

+ * + *

3 The sign string precedes the currency_symbol.

+ * + *

4 The sign string succeeds the currency_symbol.

+ * + * + * @param {integer Number} properties.n_sign_posn + * + * An integer set to a value indicating the positioning of the + * negative_sign for a negative formatted monetary quantity. Rules same + * as for p_sign_posn. + * + * + * @param {integer Number} properties.int_p_cs_precedes + * + * An integer set to 1 if the int_curr_symbol precedes the value for a + * monetary quantity with a non-negative value, and set to 0 if the + * symbol succeeds the value. + * + * + * @param {integer Number} properties.int_n_cs_precedes + * + * An integer set to 1 if the int_curr_symbol precedes the value for a + * monetary quantity with a negative value, and set to 0 if the symbol + * succeeds the value. + * + * + * @param {integer Number} properties.int_p_sep_by_space + * + * Set to a value indicating the separation of the int_curr_symbol, + * the sign string, and the value for a non-negative internationally + * formatted monetary quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.int_n_sep_by_space + * + * Set to a value indicating the separation of the int_curr_symbol, + * the sign string, and the value for a negative internationally + * formatted monetary quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.int_p_sign_posn + * + * An integer set to a value indicating the positioning of the + * positive_sign for a positive monetary quantity formatted with the + * international format. Rules same as for p_sign_posn. + * + * + * @param {integer Number} properties.int_n_sign_posn + * + * An integer set to a value indicating the positioning of the + * negative_sign for a negative monetary quantity formatted with the + * international format. Rules same as for p_sign_posn. + * + * + * @param {String[] | String} properties.abday + * + * The abbreviated weekday names, corresponding to the %a conversion + * specification. The property must be either an array of 7 strings or + * a string consisting of 7 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the abbreviated name + * of the day corresponding to Sunday, the second the abbreviated name + * of the day corresponding to Monday, and so on. + * + * + * @param {String[] | String} properties.day + * + * The full weekday names, corresponding to the %A conversion + * specification. The property must be either an array of 7 strings or + * a string consisting of 7 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the full name of the + * day corresponding to Sunday, the second the full name of the day + * corresponding to Monday, and so on. + * + * + * @param {String[] | String} properties.abmon + * + * The abbreviated month names, corresponding to the %b conversion + * specification. The property must be either an array of 12 strings or + * a string consisting of 12 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the abbreviated name + * of the first month of the year (January), the second the abbreviated + * name of the second month, and so on. + * + * + * @param {String[] | String} properties.mon + * + * The full month names, corresponding to the %B conversion + * specification. The property must be either an array of 12 strings or + * a string consisting of 12 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the full name of the + * first month of the year (January), the second the full name of the second + * month, and so on. + * + * + * @param {String} properties.d_fmt + * + * The appropriate date representation. The string may contain any + * combination of characters and conversion specifications (%). + * + * + * @param {String} properties.t_fmt + * + * The appropriate time representation. The string may contain any + * combination of characters and conversion specifications (%). + * + * + * @param {String} properties.d_t_fmt + * + * The appropriate date and time representation. The string may contain + * any combination of characters and conversion specifications (%). + * + * + * @param {String[] | String} properties.am_pm + * + * The appropriate representation of the ante-meridiem and post-meridiem + * strings, corresponding to the %p conversion specification. The property + * must be either an array of 2 strings or a string consisting of 2 + * semicolon-separated substrings, each surrounded by double-quotes. + * The first string must represent the ante-meridiem designation, the + * last string the post-meridiem designation. + * + * + * @throws @throws Error on a undefined or invalid locale property. + */ +jsworld.Locale = function(properties) { + + + /** + * @private + * + * @description Identifies the class for internal library purposes. + */ + this._className = "jsworld.Locale"; + + + /** + * @private + * + * @description Parses a day or month name definition list, which + * could be a ready JS array, e.g. ["Mon", "Tue", "Wed"...] or + * it could be a string formatted according to the classic POSIX + * definition e.g. "Mon";"Tue";"Wed";... + * + * @param {String[] | String} namesAn array or string defining + * the week/month names. + * @param {integer Number} expectedItems The number of expected list + * items, e.g. 7 for weekdays, 12 for months. + * + * @returns {String[]} The parsed (and checked) items. + * + * @throws Error on missing definition, unexpected item count or + * missing double-quotes. + */ + this._parseList = function(names, expectedItems) { + + var array = []; + + if (names == null) { + throw "Names not defined"; + } + else if (typeof names == "object") { + // we got a ready array + array = names; + } + else if (typeof names == "string") { + // we got the names in the classic POSIX form, do parse + array = names.split(";", expectedItems); + + for (var i = 0; i < array.length; i++) { + // check for and strip double quotes + if (array[i][0] == "\"" && array[i][array[i].length - 1] == "\"") + array[i] = array[i].slice(1, -1); + else + throw "Missing double quotes"; + } + } + else { + throw "Names must be an array or a string"; + } + + if (array.length != expectedItems) + throw "Expected " + expectedItems + " items, got " + array.length; + + return array; + }; + + + /** + * @private + * + * @description Validates a date/time format string, such as "H:%M:%S". + * Checks that the argument is of type "string" and is not empty. + * + * @param {String} formatString The format string. + * + * @returns {String} The validated string. + * + * @throws Error on null or empty string. + */ + this._validateFormatString = function(formatString) { + + if (typeof formatString == "string" && formatString.length > 0) + return formatString; + else + throw "Empty or no string"; + }; + + + // LC_NUMERIC + + if (properties == null || typeof properties != "object") + throw "Error: Invalid/missing locale properties"; + + + if (typeof properties.decimal_point != "string") + throw "Error: Invalid/missing decimal_point property"; + + this.decimal_point = properties.decimal_point; + + + if (typeof properties.thousands_sep != "string") + throw "Error: Invalid/missing thousands_sep property"; + + this.thousands_sep = properties.thousands_sep; + + + if (typeof properties.grouping != "string") + throw "Error: Invalid/missing grouping property"; + + this.grouping = properties.grouping; + + + // LC_MONETARY + + if (typeof properties.int_curr_symbol != "string") + throw "Error: Invalid/missing int_curr_symbol property"; + + if (! /[A-Za-z]{3}.?/.test(properties.int_curr_symbol)) + throw "Error: Invalid int_curr_symbol property"; + + this.int_curr_symbol = properties.int_curr_symbol; + + + if (typeof properties.currency_symbol != "string") + throw "Error: Invalid/missing currency_symbol property"; + + this.currency_symbol = properties.currency_symbol; + + + if (typeof properties.frac_digits != "number" && properties.frac_digits < 0) + throw "Error: Invalid/missing frac_digits property"; + + this.frac_digits = properties.frac_digits; + + + // may be empty string/null for currencies with no fractional part + if (properties.mon_decimal_point === null || properties.mon_decimal_point == "") { + + if (this.frac_digits > 0) + throw "Error: Undefined mon_decimal_point property"; + else + properties.mon_decimal_point = ""; + } + + if (typeof properties.mon_decimal_point != "string") + throw "Error: Invalid/missing mon_decimal_point property"; + + this.mon_decimal_point = properties.mon_decimal_point; + + + if (typeof properties.mon_thousands_sep != "string") + throw "Error: Invalid/missing mon_thousands_sep property"; + + this.mon_thousands_sep = properties.mon_thousands_sep; + + + if (typeof properties.mon_grouping != "string") + throw "Error: Invalid/missing mon_grouping property"; + + this.mon_grouping = properties.mon_grouping; + + + if (typeof properties.positive_sign != "string") + throw "Error: Invalid/missing positive_sign property"; + + this.positive_sign = properties.positive_sign; + + + if (typeof properties.negative_sign != "string") + throw "Error: Invalid/missing negative_sign property"; + + this.negative_sign = properties.negative_sign; + + + + if (properties.p_cs_precedes !== 0 && properties.p_cs_precedes !== 1) + throw "Error: Invalid/missing p_cs_precedes property, must be 0 or 1"; + + this.p_cs_precedes = properties.p_cs_precedes; + + + if (properties.n_cs_precedes !== 0 && properties.n_cs_precedes !== 1) + throw "Error: Invalid/missing n_cs_precedes, must be 0 or 1"; + + this.n_cs_precedes = properties.n_cs_precedes; + + + if (properties.p_sep_by_space !== 0 && + properties.p_sep_by_space !== 1 && + properties.p_sep_by_space !== 2) + throw "Error: Invalid/missing p_sep_by_space property, must be 0, 1 or 2"; + + this.p_sep_by_space = properties.p_sep_by_space; + + + if (properties.n_sep_by_space !== 0 && + properties.n_sep_by_space !== 1 && + properties.n_sep_by_space !== 2) + throw "Error: Invalid/missing n_sep_by_space property, must be 0, 1, or 2"; + + this.n_sep_by_space = properties.n_sep_by_space; + + + if (properties.p_sign_posn !== 0 && + properties.p_sign_posn !== 1 && + properties.p_sign_posn !== 2 && + properties.p_sign_posn !== 3 && + properties.p_sign_posn !== 4) + throw "Error: Invalid/missing p_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.p_sign_posn = properties.p_sign_posn; + + + if (properties.n_sign_posn !== 0 && + properties.n_sign_posn !== 1 && + properties.n_sign_posn !== 2 && + properties.n_sign_posn !== 3 && + properties.n_sign_posn !== 4) + throw "Error: Invalid/missing n_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.n_sign_posn = properties.n_sign_posn; + + + if (typeof properties.int_frac_digits != "number" && properties.int_frac_digits < 0) + throw "Error: Invalid/missing int_frac_digits property"; + + this.int_frac_digits = properties.int_frac_digits; + + + if (properties.int_p_cs_precedes !== 0 && properties.int_p_cs_precedes !== 1) + throw "Error: Invalid/missing int_p_cs_precedes property, must be 0 or 1"; + + this.int_p_cs_precedes = properties.int_p_cs_precedes; + + + if (properties.int_n_cs_precedes !== 0 && properties.int_n_cs_precedes !== 1) + throw "Error: Invalid/missing int_n_cs_precedes property, must be 0 or 1"; + + this.int_n_cs_precedes = properties.int_n_cs_precedes; + + + if (properties.int_p_sep_by_space !== 0 && + properties.int_p_sep_by_space !== 1 && + properties.int_p_sep_by_space !== 2) + throw "Error: Invalid/missing int_p_sep_by_spacev, must be 0, 1 or 2"; + + this.int_p_sep_by_space = properties.int_p_sep_by_space; + + + if (properties.int_n_sep_by_space !== 0 && + properties.int_n_sep_by_space !== 1 && + properties.int_n_sep_by_space !== 2) + throw "Error: Invalid/missing int_n_sep_by_space property, must be 0, 1, or 2"; + + this.int_n_sep_by_space = properties.int_n_sep_by_space; + + + if (properties.int_p_sign_posn !== 0 && + properties.int_p_sign_posn !== 1 && + properties.int_p_sign_posn !== 2 && + properties.int_p_sign_posn !== 3 && + properties.int_p_sign_posn !== 4) + throw "Error: Invalid/missing int_p_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.int_p_sign_posn = properties.int_p_sign_posn; + + + if (properties.int_n_sign_posn !== 0 && + properties.int_n_sign_posn !== 1 && + properties.int_n_sign_posn !== 2 && + properties.int_n_sign_posn !== 3 && + properties.int_n_sign_posn !== 4) + throw "Error: Invalid/missing int_n_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.int_n_sign_posn = properties.int_n_sign_posn; + + + // LC_TIME + + if (properties == null || typeof properties != "object") + throw "Error: Invalid/missing time locale properties"; + + + // parse the supported POSIX LC_TIME properties + + // abday + try { + this.abday = this._parseList(properties.abday, 7); + } + catch (error) { + throw "Error: Invalid abday property: " + error; + } + + // day + try { + this.day = this._parseList(properties.day, 7); + } + catch (error) { + throw "Error: Invalid day property: " + error; + } + + // abmon + try { + this.abmon = this._parseList(properties.abmon, 12); + } catch (error) { + throw "Error: Invalid abmon property: " + error; + } + + // mon + try { + this.mon = this._parseList(properties.mon, 12); + } catch (error) { + throw "Error: Invalid mon property: " + error; + } + + // d_fmt + try { + this.d_fmt = this._validateFormatString(properties.d_fmt); + } catch (error) { + throw "Error: Invalid d_fmt property: " + error; + } + + // t_fmt + try { + this.t_fmt = this._validateFormatString(properties.t_fmt); + } catch (error) { + throw "Error: Invalid t_fmt property: " + error; + } + + // d_t_fmt + try { + this.d_t_fmt = this._validateFormatString(properties.d_t_fmt); + } catch (error) { + throw "Error: Invalid d_t_fmt property: " + error; + } + + // am_pm + try { + var am_pm_strings = this._parseList(properties.am_pm, 2); + this.am = am_pm_strings[0]; + this.pm = am_pm_strings[1]; + } catch (error) { + // ignore empty/null string errors + this.am = ""; + this.pm = ""; + } + + + /** + * @public + * + * @description Returns the abbreviated name of the specified weekday. + * + * @param {integer Number} [weekdayNum] An integer between 0 and 6. Zero + * corresponds to Sunday, one to Monday, etc. If omitted the + * method will return an array of all abbreviated weekday + * names. + * + * @returns {String | String[]} The abbreviated name of the specified weekday + * or an array of all abbreviated weekday names. + * + * @throws Error on invalid argument. + */ + this.getAbbreviatedWeekdayName = function(weekdayNum) { + + if (typeof weekdayNum == "undefined" || weekdayNum === null) + return this.abday; + + if (! jsworld._isInteger(weekdayNum) || weekdayNum < 0 || weekdayNum > 6) + throw "Error: Invalid weekday argument, must be an integer [0..6]"; + + return this.abday[weekdayNum]; + }; + + + /** + * @public + * + * @description Returns the name of the specified weekday. + * + * @param {integer Number} [weekdayNum] An integer between 0 and 6. Zero + * corresponds to Sunday, one to Monday, etc. If omitted the + * method will return an array of all weekday names. + * + * @returns {String | String[]} The name of the specified weekday or an + * array of all weekday names. + * + * @throws Error on invalid argument. + */ + this.getWeekdayName = function(weekdayNum) { + + if (typeof weekdayNum == "undefined" || weekdayNum === null) + return this.day; + + if (! jsworld._isInteger(weekdayNum) || weekdayNum < 0 || weekdayNum > 6) + throw "Error: Invalid weekday argument, must be an integer [0..6]"; + + return this.day[weekdayNum]; + }; + + + /** + * @public + * + * @description Returns the abbreviated name of the specified month. + * + * @param {integer Number} [monthNum] An integer between 0 and 11. Zero + * corresponds to January, one to February, etc. If omitted the + * method will return an array of all abbreviated month names. + * + * @returns {String | String[]} The abbreviated name of the specified month + * or an array of all abbreviated month names. + * + * @throws Error on invalid argument. + */ + this.getAbbreviatedMonthName = function(monthNum) { + + if (typeof monthNum == "undefined" || monthNum === null) + return this.abmon; + + if (! jsworld._isInteger(monthNum) || monthNum < 0 || monthNum > 11) + throw "Error: Invalid month argument, must be an integer [0..11]"; + + return this.abmon[monthNum]; + }; + + + /** + * @public + * + * @description Returns the name of the specified month. + * + * @param {integer Number} [monthNum] An integer between 0 and 11. Zero + * corresponds to January, one to February, etc. If omitted the + * method will return an array of all month names. + * + * @returns {String | String[]} The name of the specified month or an array + * of all month names. + * + * @throws Error on invalid argument. + */ + this.getMonthName = function(monthNum) { + + if (typeof monthNum == "undefined" || monthNum === null) + return this.mon; + + if (! jsworld._isInteger(monthNum) || monthNum < 0 || monthNum > 11) + throw "Error: Invalid month argument, must be an integer [0..11]"; + + return this.mon[monthNum]; + }; + + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) character for + * numeric quantities. + * + * @returns {String} The radix character. + */ + this.getDecimalPoint = function() { + + return this.decimal_point; + }; + + + /** + * @public + * + * @description Gets the local shorthand currency symbol. + * + * @returns {String} The currency symbol. + */ + this.getCurrencySymbol = function() { + + return this.currency_symbol; + }; + + + /** + * @public + * + * @description Gets the internaltion currency symbol (ISO-4217 code). + * + * @returns {String} The international currency symbol. + */ + this.getIntCurrencySymbol = function() { + + return this.int_curr_symbol.substring(0,3); + }; + + + /** + * @public + * + * @description Gets the position of the local (shorthand) currency + * symbol relative to the amount. Assumes a non-negative amount. + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.currencySymbolPrecedes = function() { + + if (this.p_cs_precedes == 1) + return true; + else + return false; + }; + + + /** + * @public + * + * @description Gets the position of the international (ISO-4217 code) + * currency symbol relative to the amount. Assumes a non-negative + * amount. + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.intCurrencySymbolPrecedes = function() { + + if (this.int_p_cs_precedes == 1) + return true; + else + return false; + + }; + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) for monetary + * quantities. + * + * @returns {String} The radix character. + */ + this.getMonetaryDecimalPoint = function() { + + return this.mon_decimal_point; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits for local + * (shorthand) symbol formatting. + * + * @returns {integer Number} The number of fractional digits. + */ + this.getFractionalDigits = function() { + + return this.frac_digits; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits for + * international (ISO-4217 code) formatting. + * + * @returns {integer Number} The number of fractional digits. + */ + this.getIntFractionalDigits = function() { + + return this.int_frac_digits; + }; +}; + + + +/** + * @class + * Class for localised formatting of numbers. + * + *

See: + * POSIX LC_NUMERIC. + * + * + * @public + * @constructor + * @description Creates a new numeric formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_NUMERIC formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.NumericFormatter = function(locale) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance"; + + this.lc = locale; + + + /** + * @public + * + * @description Formats a decimal numeric value according to the preset + * locale. + * + * @param {Number|String} number The number to format. + * @param {String} [options] Options to modify the formatted output: + *

    + *
  • "^" suppress grouping + *
  • "+" force positive sign for positive amounts + *
  • "~" suppress positive/negative sign + *
  • ".n" specify decimal precision 'n' + *
+ * + * @returns {String} The formatted number. + * + * @throws "Error: Invalid input" on bad input. + */ + this.format = function(number, options) { + + if (typeof number == "string") + number = jsworld._trim(number); + + if (! jsworld._isNumber(number)) + throw "Error: The input is not a number"; + + var floatAmount = parseFloat(number, 10); + + // get the required precision + var reqPrecision = jsworld._getPrecision(options); + + // round to required precision + if (reqPrecision != -1) + floatAmount = Math.round(floatAmount * Math.pow(10, reqPrecision)) / Math.pow(10, reqPrecision); + + + // convert the float number to string and parse into + // object with properties integer and fraction + var parsedAmount = jsworld._splitNumber(String(floatAmount)); + + // format integer part with grouping chars + var formattedIntegerPart; + + if (floatAmount === 0) + formattedIntegerPart = "0"; + else + formattedIntegerPart = jsworld._hasOption("^", options) ? + parsedAmount.integer : + jsworld._formatIntegerPart(parsedAmount.integer, + this.lc.grouping, + this.lc.thousands_sep); + + // format the fractional part + var formattedFractionPart = + reqPrecision != -1 ? + jsworld._formatFractionPart(parsedAmount.fraction, reqPrecision) : + parsedAmount.fraction; + + + // join the integer and fraction parts using the decimal_point property + var formattedAmount = + formattedFractionPart.length ? + formattedIntegerPart + this.lc.decimal_point + formattedFractionPart : + formattedIntegerPart; + + // prepend sign? + if (jsworld._hasOption("~", options) || floatAmount === 0) { + // suppress both '+' and '-' signs, i.e. return abs value + return formattedAmount; + } + else { + if (jsworld._hasOption("+", options) || floatAmount < 0) { + if (floatAmount > 0) + // force '+' sign for positive amounts + return "+" + formattedAmount; + else if (floatAmount < 0) + // prepend '-' sign + return "-" + formattedAmount; + else + // zero case + return formattedAmount; + } + else { + // positive amount with no '+' sign + return formattedAmount; + } + } + }; +}; + + +/** + * @class + * Class for localised formatting of dates and times. + * + *

See: + * POSIX LC_TIME. + * + * @public + * @constructor + * @description Creates a new date/time formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_TIME formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.DateTimeFormatter = function(locale) { + + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance."; + + this.lc = locale; + + + /** + * @public + * + * @description Formats a date according to the preset locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted date, e.g. "2010-31-03" + * or "2010-03-31 23:59:59". + * + * @returns {String} The formatted date + * + * @throws Error on invalid date argument + */ + this.formatDate = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 date string + try { + d = jsworld.parseIsoDate(date); + } catch (error) { + // try full ISO-8601 date/time string + d = jsworld.parseIsoDateTime(date); + } + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.d_fmt); + }; + + + /** + * @public + * + * @description Formats a time according to the preset locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted time, e.g. "23:59:59" + * or "2010-03-31 23:59:59". + * + * @returns {String} The formatted time. + * + * @throws Error on invalid date argument. + */ + this.formatTime = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 time string + try { + d = jsworld.parseIsoTime(date); + } catch (error) { + // try full ISO-8601 date/time string + d = jsworld.parseIsoDateTime(date); + } + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.t_fmt); + }; + + + /** + * @public + * + * @description Formats a date/time value according to the preset + * locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted date/time, e.g. + * "2010-03-31 23:59:59". + * + * @returns {String} The formatted time. + * + * @throws Error on invalid argument. + */ + this.formatDateTime = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 format + d = jsworld.parseIsoDateTime(date); + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.d_t_fmt); + }; + + + /** + * @private + * + * @description Apples formatting to the Date object according to the + * format string. + * + * @param {Date} d A valid Date instance. + * @param {String} s The formatting string with '%' placeholders. + * + * @returns {String} The formatted string. + */ + this._applyFormatting = function(d, s) { + + s = s.replace(/%%/g, '%'); + s = s.replace(/%a/g, this.lc.abday[d.getDay()]); + s = s.replace(/%A/g, this.lc.day[d.getDay()]); + s = s.replace(/%b/g, this.lc.abmon[d.getMonth()]); + s = s.replace(/%B/g, this.lc.mon[d.getMonth()]); + s = s.replace(/%d/g, jsworld._zeroPad(d.getDate(), 2)); + s = s.replace(/%e/g, jsworld._spacePad(d.getDate(), 2)); + s = s.replace(/%F/g, d.getFullYear() + + "-" + + jsworld._zeroPad(d.getMonth()+1, 2) + + "-" + + jsworld._zeroPad(d.getDate(), 2)); + s = s.replace(/%h/g, this.lc.abmon[d.getMonth()]); // same as %b + s = s.replace(/%H/g, jsworld._zeroPad(d.getHours(), 2)); + s = s.replace(/%I/g, jsworld._zeroPad(this._hours12(d.getHours()), 2)); + s = s.replace(/%k/g, d.getHours()); + s = s.replace(/%l/g, this._hours12(d.getHours())); + s = s.replace(/%m/g, jsworld._zeroPad(d.getMonth()+1, 2)); + s = s.replace(/%n/g, "\n"); + s = s.replace(/%M/g, jsworld._zeroPad(d.getMinutes(), 2)); + s = s.replace(/%p/g, this._getAmPm(d.getHours())); + s = s.replace(/%P/g, this._getAmPm(d.getHours()).toLocaleLowerCase()); // safe? + s = s.replace(/%R/g, jsworld._zeroPad(d.getHours(), 2) + + ":" + + jsworld._zeroPad(d.getMinutes(), 2)); + s = s.replace(/%S/g, jsworld._zeroPad(d.getSeconds(), 2)); + s = s.replace(/%T/g, jsworld._zeroPad(d.getHours(), 2) + + ":" + + jsworld._zeroPad(d.getMinutes(), 2) + + ":" + + jsworld._zeroPad(d.getSeconds(), 2)); + s = s.replace(/%w/g, this.lc.day[d.getDay()]); + s = s.replace(/%y/g, new String(d.getFullYear()).substring(2)); + s = s.replace(/%Y/g, d.getFullYear()); + + s = s.replace(/%Z/g, ""); // to do: ignored until a reliable TMZ method found + + s = s.replace(/%[a-zA-Z]/g, ""); // ignore all other % sequences + + return s; + }; + + + /** + * @private + * + * @description Does 24 to 12 hour conversion. + * + * @param {integer Number} hour24 Hour [0..23]. + * + * @returns {integer Number} Corresponding hour [1..12]. + */ + this._hours12 = function(hour24) { + + if (hour24 === 0) + return 12; // 00h is 12AM + + else if (hour24 > 12) + return hour24 - 12; // 1PM to 11PM + + else + return hour24; // 1AM to 12PM + }; + + + /** + * @private + * + * @description Gets the appropriate localised AM or PM string depending + * on the day hour. Special cases: midnight is 12AM, noon is 12PM. + * + * @param {integer Number} hour24 Hour [0..23]. + * + * @returns {String} The corresponding localised AM or PM string. + */ + this._getAmPm = function(hour24) { + + if (hour24 < 12) + return this.lc.am; + else + return this.lc.pm; + }; +}; + + + +/** + * @class Class for localised formatting of currency amounts. + * + *

See: + * POSIX LC_MONETARY. + * + * @public + * @constructor + * @description Creates a new monetary formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_MONETARY formatting properties. + * @param {String} [currencyCode] Set the currency explicitly by + * passing its international ISO-4217 code, e.g. "USD", "EUR", "GBP". + * Use this optional parameter to override the default local currency + * @param {String} [altIntSymbol] Non-local currencies are formatted + * with their international ISO-4217 code to prevent ambiguity. + * Use this optional argument to force a different symbol, such as the + * currency's shorthand sign. This is mostly useful when the shorthand + * sign is both internationally recognised and identifies the currency + * uniquely (e.g. the Euro sign). + * + * @throws Error on constructor failure. + */ +jsworld.MonetaryFormatter = function(locale, currencyCode, altIntSymbol) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance"; + + this.lc = locale; + + /** + * @private + * @description Lookup table to determine the fraction digits for a + * specific currency; most currencies subdivide at 1/100 (2 fractional + * digits), so we store only those that deviate from the default. + * + *

The data is from Unicode's CLDR version 1.7.0. The two currencies + * with non-decimal subunits (MGA and MRO) are marked as having no + * fractional digits as well as all currencies that have no subunits + * in circulation. + * + *

It is "hard-wired" for referential convenience and is only looked + * up when an overriding currencyCode parameter is supplied. + */ + this.currencyFractionDigits = { + "AFN" : 0, "ALL" : 0, "AMD" : 0, "BHD" : 3, "BIF" : 0, + "BYR" : 0, "CLF" : 0, "CLP" : 0, "COP" : 0, "CRC" : 0, + "DJF" : 0, "GNF" : 0, "GYD" : 0, "HUF" : 0, "IDR" : 0, + "IQD" : 0, "IRR" : 0, "ISK" : 0, "JOD" : 3, "JPY" : 0, + "KMF" : 0, "KRW" : 0, "KWD" : 3, "LAK" : 0, "LBP" : 0, + "LYD" : 3, "MGA" : 0, "MMK" : 0, "MNT" : 0, "MRO" : 0, + "MUR" : 0, "OMR" : 3, "PKR" : 0, "PYG" : 0, "RSD" : 0, + "RWF" : 0, "SLL" : 0, "SOS" : 0, "STD" : 0, "SYP" : 0, + "TND" : 3, "TWD" : 0, "TZS" : 0, "UGX" : 0, "UZS" : 0, + "VND" : 0, "VUV" : 0, "XAF" : 0, "XOF" : 0, "XPF" : 0, + "YER" : 0, "ZMK" : 0 + }; + + + // optional currencyCode argument? + if (typeof currencyCode == "string") { + // user wanted to override the local currency + this.currencyCode = currencyCode.toUpperCase(); + + // must override the frac digits too, for some + // currencies have 0, 2 or 3! + var numDigits = this.currencyFractionDigits[this.currencyCode]; + if (typeof numDigits != "number") + numDigits = 2; // default for most currencies + this.lc.frac_digits = numDigits; + this.lc.int_frac_digits = numDigits; + } + else { + // use local currency + this.currencyCode = this.lc.int_curr_symbol.substring(0,3).toUpperCase(); + } + + // extract intl. currency separator + this.intSep = this.lc.int_curr_symbol.charAt(3); + + // flag local or intl. sign formatting? + if (this.currencyCode == this.lc.int_curr_symbol.substring(0,3)) { + // currency matches the local one? -> + // formatting with local symbol and parameters + this.internationalFormatting = false; + this.curSym = this.lc.currency_symbol; + } + else { + // currency doesn't match the local -> + + // do we have an overriding currency symbol? + if (typeof altIntSymbol == "string") { + // -> force formatting with local parameters, using alt symbol + this.curSym = altIntSymbol; + this.internationalFormatting = false; + } + else { + // -> force formatting with intl. sign and parameters + this.internationalFormatting = true; + } + } + + + /** + * @public + * + * @description Gets the currency symbol used in formatting. + * + * @returns {String} The currency symbol. + */ + this.getCurrencySymbol = function() { + + return this.curSym; + }; + + + /** + * @public + * + * @description Gets the position of the currency symbol relative to + * the amount. Assumes a non-negative amount and local formatting. + * + * @param {String} intFlag Optional flag to force international + * formatting by passing the string "i". + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.currencySymbolPrecedes = function(intFlag) { + + if (typeof intFlag == "string" && intFlag == "i") { + // international formatting was forced + if (this.lc.int_p_cs_precedes == 1) + return true; + else + return false; + + } + else { + // check whether local formatting is on or off + if (this.internationalFormatting) { + if (this.lc.int_p_cs_precedes == 1) + return true; + else + return false; + } + else { + if (this.lc.p_cs_precedes == 1) + return true; + else + return false; + } + } + }; + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) used in formatting. + * + * @returns {String} The radix character. + */ + this.getDecimalPoint = function() { + + return this.lc.mon_decimal_point; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits. Assumes local + * formatting. + * + * @param {String} intFlag Optional flag to force international + * formatting by passing the string "i". + * + * @returns {integer Number} The number of fractional digits. + */ + this.getFractionalDigits = function(intFlag) { + + if (typeof intFlag == "string" && intFlag == "i") { + // international formatting was forced + return this.lc.int_frac_digits; + } + else { + // check whether local formatting is on or off + if (this.internationalFormatting) + return this.lc.int_frac_digits; + else + return this.lc.frac_digits; + } + }; + + + /** + * @public + * + * @description Formats a monetary amount according to the preset + * locale. + * + *

+	 * For local currencies the native shorthand symbol will be used for
+	 * formatting.
+	 * Example:
+	 *        locale is en_US
+	 *        currency is USD
+	 *        -> the "$" symbol will be used, e.g. $123.45
+	 *        
+	 * For non-local currencies the international ISO-4217 code will be
+	 * used for formatting.
+	 * Example:
+	 *       locale is en_US (which has USD as currency)
+	 *       currency is EUR
+	 *       -> the ISO three-letter code will be used, e.g. EUR 123.45
+	 *
+	 * If the currency is non-local, but an alternative currency symbol was
+	 * provided, this will be used instead.
+	 * Example
+	 *       locale is en_US (which has USD as currency)
+	 *       currency is EUR
+	 *       an alternative symbol is provided - "€"
+	 *       -> the alternative symbol will be used, e.g. €123.45
+	 * 
+ * + * @param {Number|String} amount The amount to format as currency. + * @param {String} [options] Options to modify the formatted output: + *
    + *
  • "^" suppress grouping + *
  • "!" suppress the currency symbol + *
  • "~" suppress the currency symbol and the sign (positive or negative) + *
  • "i" force international sign (ISO-4217 code) formatting + *
  • ".n" specify decimal precision + * + * @returns The formatted currency amount as string. + * + * @throws "Error: Invalid amount" on bad amount. + */ + this.format = function(amount, options) { + + // if the amount is passed as string, check that it parses to a float + var floatAmount; + + if (typeof amount == "string") { + amount = jsworld._trim(amount); + floatAmount = parseFloat(amount); + + if (typeof floatAmount != "number" || isNaN(floatAmount)) + throw "Error: Amount string not a number"; + } + else if (typeof amount == "number") { + floatAmount = amount; + } + else { + throw "Error: Amount not a number"; + } + + // get the required precision, ".n" option arg overrides default locale config + var reqPrecision = jsworld._getPrecision(options); + + if (reqPrecision == -1) { + if (this.internationalFormatting || jsworld._hasOption("i", options)) + reqPrecision = this.lc.int_frac_digits; + else + reqPrecision = this.lc.frac_digits; + } + + // round + floatAmount = Math.round(floatAmount * Math.pow(10, reqPrecision)) / Math.pow(10, reqPrecision); + + + // convert the float amount to string and parse into + // object with properties integer and fraction + var parsedAmount = jsworld._splitNumber(String(floatAmount)); + + // format integer part with grouping chars + var formattedIntegerPart; + + if (floatAmount === 0) + formattedIntegerPart = "0"; + else + formattedIntegerPart = jsworld._hasOption("^", options) ? + parsedAmount.integer : + jsworld._formatIntegerPart(parsedAmount.integer, + this.lc.mon_grouping, + this.lc.mon_thousands_sep); + + + // format the fractional part + var formattedFractionPart; + + if (reqPrecision == -1) { + // pad fraction with trailing zeros accoring to default locale [int_]frac_digits + if (this.internationalFormatting || jsworld._hasOption("i", options)) + formattedFractionPart = + jsworld._formatFractionPart(parsedAmount.fraction, this.lc.int_frac_digits); + else + formattedFractionPart = + jsworld._formatFractionPart(parsedAmount.fraction, this.lc.frac_digits); + } + else { + // pad fraction with trailing zeros according to optional format parameter + formattedFractionPart = + jsworld._formatFractionPart(parsedAmount.fraction, reqPrecision); + } + + + // join integer and decimal parts using the mon_decimal_point property + var quantity; + + if (this.lc.frac_digits > 0 || formattedFractionPart.length) + quantity = formattedIntegerPart + this.lc.mon_decimal_point + formattedFractionPart; + else + quantity = formattedIntegerPart; + + + // do final formatting with sign and symbol + if (jsworld._hasOption("~", options)) { + return quantity; + } + else { + var suppressSymbol = jsworld._hasOption("!", options) ? true : false; + + var sign = floatAmount < 0 ? "-" : "+"; + + if (this.internationalFormatting || jsworld._hasOption("i", options)) { + + // format with ISO-4217 code (suppressed or not) + if (suppressSymbol) + return this._formatAsInternationalCurrencyWithNoSym(sign, quantity); + else + return this._formatAsInternationalCurrency(sign, quantity); + } + else { + // format with local currency code (suppressed or not) + if (suppressSymbol) + return this._formatAsLocalCurrencyWithNoSym(sign, quantity); + else + return this._formatAsLocalCurrency(sign, quantity); + } + } + }; + + + /** + * @private + * + * @description Assembles the final string with sign, separator and symbol as local + * currency. + * + * @param {String} sign The amount sign: "+" or "-". + * @param {String} q The formatted quantity (unsigned). + * + * @returns {String} The final formatted string. + */ + this._formatAsLocalCurrency = function (sign, q) { + + // assemble final formatted amount by going over all possible value combinations of: + // sign {+,-} , sign position {0,1,2,3,4} , separator {0,1,2} , symbol position {0,1} + if (sign == "+") { + + // parentheses + if (this.lc.p_sign_posn === 0 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return "(" + q + this.curSym + ")"; + } + else if (this.lc.p_sign_posn === 0 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return "(" + this.curSym + q + ")"; + } + else if (this.lc.p_sign_posn === 0 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return "(" + q + " " + this.curSym + ")"; + } + else if (this.lc.p_sign_posn === 0 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return "(" + this.curSym + " " + q + ")"; + } + + // sign before q + sym + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return this.lc.positive_sign + q + this.curSym; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + this.curSym + q; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return this.lc.positive_sign + q + " " + this.curSym; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + this.curSym + " " + q; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 0) { + return this.lc.positive_sign + " " + q + this.curSym; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + " " + this.curSym + q; + } + + // sign after q + sym + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return q + this.curSym + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return this.curSym + q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return q + " " + this.curSym + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return this.curSym + " " + q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 0) { + return q + this.curSym + " " + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 1) { + return this.curSym + q + " " + this.lc.positive_sign; + } + + // sign before sym + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return q + this.lc.positive_sign + this.curSym; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + this.curSym + q; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return q + " " + this.lc.positive_sign + this.curSym; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + this.curSym + " " + q; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 0) { + return q + this.lc.positive_sign + " " + this.curSym; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + " " + this.curSym + q; + } + + // sign after symbol + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return q + this.curSym + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return this.curSym + this.lc.positive_sign + q; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return q + " " + this.curSym + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return this.curSym + this.lc.positive_sign + " " + q; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 0) { + return q + this.curSym + " " + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 1) { + return this.curSym + " " + this.lc.positive_sign + q; + } + + } + else if (sign == "-") { + + // parentheses enclose q + sym + if (this.lc.n_sign_posn === 0 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return "(" + q + this.curSym + ")"; + } + else if (this.lc.n_sign_posn === 0 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return "(" + this.curSym + q + ")"; + } + else if (this.lc.n_sign_posn === 0 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return "(" + q + " " + this.curSym + ")"; + } + else if (this.lc.n_sign_posn === 0 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return "(" + this.curSym + " " + q + ")"; + } + + // sign before q + sym + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return this.lc.negative_sign + q + this.curSym; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + this.curSym + q; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return this.lc.negative_sign + q + " " + this.curSym; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + this.curSym + " " + q; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 0) { + return this.lc.negative_sign + " " + q + this.curSym; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + " " + this.curSym + q; + } + + // sign after q + sym + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return q + this.curSym + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return this.curSym + q + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return q + " " + this.curSym + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return this.curSym + " " + q + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 0) { + return q + this.curSym + " " + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 1) { + return this.curSym + q + " " + this.lc.negative_sign; + } + + // sign before sym + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return q + this.lc.negative_sign + this.curSym; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + this.curSym + q; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return q + " " + this.lc.negative_sign + this.curSym; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + this.curSym + " " + q; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 0) { + return q + this.lc.negative_sign + " " + this.curSym; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + " " + this.curSym + q; + } + + // sign after symbol + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return q + this.curSym + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return this.curSym + this.lc.negative_sign + q; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return q + " " + this.curSym + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return this.curSym + this.lc.negative_sign + " " + q; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 0) { + return q + this.curSym + " " + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 1) { + return this.curSym + " " + this.lc.negative_sign + q; + } + } + + // throw error if we fall through + throw "Error: Invalid POSIX LC MONETARY definition"; + }; + + + /** + * @private + * + * @description Assembles the final string with sign, separator and ISO-4217 + * currency code. + * + * @param {String} sign The amount sign: "+" or "-". + * @param {String} q The formatted quantity (unsigned). + * + * @returns {String} The final formatted string. + */ + this._formatAsInternationalCurrency = function (sign, q) { + + // assemble the final formatted amount by going over all possible value combinations of: + // sign {+,-} , sign position {0,1,2,3,4} , separator {0,1,2} , symbol position {0,1} + + if (sign == "+") { + + // parentheses + if (this.lc.int_p_sign_posn === 0 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return "(" + q + this.currencyCode + ")"; + } + else if (this.lc.int_p_sign_posn === 0 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return "(" + this.currencyCode + q + ")"; + } + else if (this.lc.int_p_sign_posn === 0 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return "(" + q + this.intSep + this.currencyCode + ")"; + } + else if (this.lc.int_p_sign_posn === 0 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return "(" + this.currencyCode + this.intSep + q + ")"; + } + + // sign before q + sym + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return this.lc.positive_sign + q + this.currencyCode; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.currencyCode + q; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return this.lc.positive_sign + q + this.intSep + this.currencyCode; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.currencyCode + this.intSep + q; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 0) { + return this.lc.positive_sign + this.intSep + q + this.currencyCode; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.intSep + this.currencyCode + q; + } + + // sign after q + sym + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return q + this.currencyCode + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return this.currencyCode + q + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return q + this.intSep + this.currencyCode + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return this.currencyCode + this.intSep + q + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 0) { + return q + this.currencyCode + this.intSep + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 1) { + return this.currencyCode + q + this.intSep + this.lc.positive_sign; + } + + // sign before sym + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return q + this.lc.positive_sign + this.currencyCode; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.currencyCode + q; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return q + this.intSep + this.lc.positive_sign + this.currencyCode; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.currencyCode + this.intSep + q; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 0) { + return q + this.lc.positive_sign + this.intSep + this.currencyCode; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.intSep + this.currencyCode + q; + } + + // sign after symbol + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return q + this.currencyCode + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return this.currencyCode + this.lc.positive_sign + q; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return q + this.intSep + this.currencyCode + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return this.currencyCode + this.lc.positive_sign + this.intSep + q; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 0) { + return q + this.currencyCode + this.intSep + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 1) { + return this.currencyCode + this.intSep + this.lc.positive_sign + q; + } + + } + else if (sign == "-") { + + // parentheses enclose q + sym + if (this.lc.int_n_sign_posn === 0 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return "(" + q + this.currencyCode + ")"; + } + else if (this.lc.int_n_sign_posn === 0 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return "(" + this.currencyCode + q + ")"; + } + else if (this.lc.int_n_sign_posn === 0 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return "(" + q + this.intSep + this.currencyCode + ")"; + } + else if (this.lc.int_n_sign_posn === 0 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return "(" + this.currencyCode + this.intSep + q + ")"; + } + + // sign before q + sym + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return this.lc.negative_sign + q + this.currencyCode; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.currencyCode + q; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return this.lc.negative_sign + q + this.intSep + this.currencyCode; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.currencyCode + this.intSep + q; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 0) { + return this.lc.negative_sign + this.intSep + q + this.currencyCode; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.intSep + this.currencyCode + q; + } + + // sign after q + sym + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return q + this.currencyCode + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return this.currencyCode + q + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return q + this.intSep + this.currencyCode + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return this.currencyCode + this.intSep + q + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 0) { + return q + this.currencyCode + this.intSep + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 1) { + return this.currencyCode + q + this.intSep + this.lc.negative_sign; + } + + // sign before sym + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return q + this.lc.negative_sign + this.currencyCode; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.currencyCode + q; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return q + this.intSep + this.lc.negative_sign + this.currencyCode; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.currencyCode + this.intSep + q; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 0) { + return q + this.lc.negative_sign + this.intSep + this.currencyCode; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.intSep + this.currencyCode + q; + } + + // sign after symbol + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return q + this.currencyCode + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return this.currencyCode + this.lc.negative_sign + q; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return q + this.intSep + this.currencyCode + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return this.currencyCode + this.lc.negative_sign + this.intSep + q; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 0) { + return q + this.currencyCode + this.intSep + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 1) { + return this.currencyCode + this.intSep + this.lc.negative_sign + q; + } + } + + // throw error if we fall through + throw "Error: Invalid POSIX LC MONETARY definition"; + }; + + + /** + * @private + * + * @description Assembles the final string with sign and separator, but suppress the + * local currency symbol. + * + * @param {String} sign The amount sign: "+" or "-". + * @param {String} q The formatted quantity (unsigned). + * + * @returns {String} The final formatted string + */ + this._formatAsLocalCurrencyWithNoSym = function (sign, q) { + + // assemble the final formatted amount by going over all possible value combinations of: + // sign {+,-} , sign position {0,1,2,3,4} , separator {0,1,2} , symbol position {0,1} + + if (sign == "+") { + + // parentheses + if (this.lc.p_sign_posn === 0) { + return "(" + q + ")"; + } + + // sign before q + sym + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return this.lc.positive_sign + q; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return this.lc.positive_sign + q; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 0) { + return this.lc.positive_sign + " " + q; + } + else if (this.lc.p_sign_posn === 1 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + " " + q; + } + + // sign after q + sym + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return q + " " + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 2 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 1) { + return q + " " + this.lc.positive_sign; + } + + // sign before sym + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return q + " " + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + " " + q; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 3 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + " " + q; + } + + // sign after symbol + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 0 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 0) { + return q + " " + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 1 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + " " + q; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 0) { + return q + " " + this.lc.positive_sign; + } + else if (this.lc.p_sign_posn === 4 && this.lc.p_sep_by_space === 2 && this.lc.p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + + } + else if (sign == "-") { + + // parentheses enclose q + sym + if (this.lc.n_sign_posn === 0) { + return "(" + q + ")"; + } + + // sign before q + sym + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return this.lc.negative_sign + q; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + q; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return this.lc.negative_sign + q; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + " " + q; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 0) { + return this.lc.negative_sign + " " + q; + } + else if (this.lc.n_sign_posn === 1 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + " " + q; + } + + // sign after q + sym + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return q + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return q + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return q + " " + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return q + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 0) { + return q + " " + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 2 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 1) { + return q + " " + this.lc.negative_sign; + } + + // sign before sym + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return q + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + q; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return q + " " + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + " " + q; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 0) { + return q + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 3 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + " " + q; + } + + // sign after symbol + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 0) { + return q + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 0 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + q; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 0) { + return q + " " + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 1 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + " " + q; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 0) { + return q + " " + this.lc.negative_sign; + } + else if (this.lc.n_sign_posn === 4 && this.lc.n_sep_by_space === 2 && this.lc.n_cs_precedes === 1) { + return this.lc.negative_sign + q; + } + } + + // throw error if we fall through + throw "Error: Invalid POSIX LC MONETARY definition"; + }; + + + /** + * @private + * + * @description Assembles the final string with sign and separator, but suppress + * the ISO-4217 currency code. + * + * @param {String} sign The amount sign: "+" or "-". + * @param {String} q The formatted quantity (unsigned). + * + * @returns {String} The final formatted string. + */ + this._formatAsInternationalCurrencyWithNoSym = function (sign, q) { + + // assemble the final formatted amount by going over all possible value combinations of: + // sign {+,-} , sign position {0,1,2,3,4} , separator {0,1,2} , symbol position {0,1} + + if (sign == "+") { + + // parentheses + if (this.lc.int_p_sign_posn === 0) { + return "(" + q + ")"; + } + + // sign before q + sym + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return this.lc.positive_sign + q; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return this.lc.positive_sign + q; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.intSep + q; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 0) { + return this.lc.positive_sign + this.intSep + q; + } + else if (this.lc.int_p_sign_posn === 1 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.intSep + q; + } + + // sign after q + sym + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return q + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return q + this.intSep + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return q + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 0) { + return q + this.intSep + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 2 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 1) { + return q + this.intSep + this.lc.positive_sign; + } + + // sign before sym + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return q + this.intSep + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.intSep + q; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 3 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.intSep + q; + } + + // sign after symbol + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 0) { + return q + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 0 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 0) { + return q + this.intSep + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 1 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + this.intSep + q; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 0) { + return q + this.intSep + this.lc.positive_sign; + } + else if (this.lc.int_p_sign_posn === 4 && this.lc.int_p_sep_by_space === 2 && this.lc.int_p_cs_precedes === 1) { + return this.lc.positive_sign + q; + } + + } + else if (sign == "-") { + + // parentheses enclose q + sym + if (this.lc.int_n_sign_posn === 0) { + return "(" + q + ")"; + } + + // sign before q + sym + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return this.lc.negative_sign + q; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + q; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return this.lc.negative_sign + q; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.intSep + q; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 0) { + return this.lc.negative_sign + this.intSep + q; + } + else if (this.lc.int_n_sign_posn === 1 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.intSep + q; + } + + // sign after q + sym + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return q + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return q + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return q + this.intSep + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return q + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 0) { + return q + this.intSep + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 2 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 1) { + return q + this.intSep + this.lc.negative_sign; + } + + // sign before sym + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return q + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + q; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return q + this.intSep + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.intSep + q; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 0) { + return q + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 3 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.intSep + q; + } + + // sign after symbol + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 0) { + return q + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 0 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + q; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 0) { + return q + this.intSep + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 1 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + this.intSep + q; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 0) { + return q + this.intSep + this.lc.negative_sign; + } + else if (this.lc.int_n_sign_posn === 4 && this.lc.int_n_sep_by_space === 2 && this.lc.int_n_cs_precedes === 1) { + return this.lc.negative_sign + q; + } + } + + // throw error if we fall through + throw "Error: Invalid POSIX LC_MONETARY definition"; + }; +}; + + +/** + * @class + * Class for parsing localised number strings. + * + * @public + * @constructor + * @description Creates a new numeric parser for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_NUMERIC formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.NumericParser = function(locale) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance"; + + this.lc = locale; + + + /** + * @public + * + * @description Parses a numeric string formatted according to the + * preset locale. Leading and trailing whitespace is ignored; the number + * may also be formatted without thousands separators. + * + * @param {String} formattedNumber The formatted number. + * + * @returns {Number} The parsed number. + * + * @throws Error on a parse exception. + */ + this.parse = function(formattedNumber) { + + if (typeof formattedNumber != "string") + throw "Parse error: Argument must be a string"; + + // trim whitespace + var s = jsworld._trim(formattedNumber); + + // remove any thousand separator symbols + s = jsworld._stringReplaceAll(formattedNumber, this.lc.thousands_sep, ""); + + // replace any local decimal point symbols with the symbol used + // in JavaScript "." + s = jsworld._stringReplaceAll(s, this.lc.decimal_point, "."); + + // test if the string represents a number + if (jsworld._isNumber(s)) + return parseFloat(s, 10); + else + throw "Parse error: Invalid number string"; + }; +}; + + +/** + * @class + * Class for parsing localised date and time strings. + * + * @public + * @constructor + * @description Creates a new date/time parser for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_TIME formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.DateTimeParser = function(locale) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance."; + + this.lc = locale; + + + /** + * @public + * + * @description Parses a time string formatted according to the + * POSIX LC_TIME t_fmt property of the preset locale. + * + * @param {String} formattedTime The formatted time. + * + * @returns {String} The parsed time in ISO-8601 format (HH:MM:SS), e.g. + * "23:59:59". + * + * @throws Error on a parse exception. + */ + this.parseTime = function(formattedTime) { + + if (typeof formattedTime != "string") + throw "Parse error: Argument must be a string"; + + var dt = this._extractTokens(this.lc.t_fmt, formattedTime); + + var timeDefined = false; + + if (dt.hour !== null && dt.minute !== null && dt.second !== null) { + timeDefined = true; + } + else if (dt.hourAmPm !== null && dt.am !== null && dt.minute !== null && dt.second !== null) { + if (dt.am) { + // AM [12(midnight), 1 .. 11] + if (dt.hourAmPm == 12) + dt.hour = 0; + else + dt.hour = parseInt(dt.hourAmPm, 10); + } + else { + // PM [12(noon), 1 .. 11] + if (dt.hourAmPm == 12) + dt.hour = 12; + else + dt.hour = parseInt(dt.hourAmPm, 10) + 12; + } + timeDefined = true; + } + + if (timeDefined) + return jsworld._zeroPad(dt.hour, 2) + + ":" + + jsworld._zeroPad(dt.minute, 2) + + ":" + + jsworld._zeroPad(dt.second, 2); + else + throw "Parse error: Invalid/ambiguous time string"; + }; + + + /** + * @public + * + * @description Parses a date string formatted according to the + * POSIX LC_TIME d_fmt property of the preset locale. + * + * @param {String} formattedDate The formatted date, must be valid. + * + * @returns {String} The parsed date in ISO-8601 format (YYYY-MM-DD), + * e.g. "2010-03-31". + * + * @throws Error on a parse exception. + */ + this.parseDate = function(formattedDate) { + + if (typeof formattedDate != "string") + throw "Parse error: Argument must be a string"; + + var dt = this._extractTokens(this.lc.d_fmt, formattedDate); + + var dateDefined = false; + + if (dt.year !== null && dt.month !== null && dt.day !== null) { + dateDefined = true; + } + + if (dateDefined) + return jsworld._zeroPad(dt.year, 4) + + "-" + + jsworld._zeroPad(dt.month, 2) + + "-" + + jsworld._zeroPad(dt.day, 2); + else + throw "Parse error: Invalid date string"; + }; + + + /** + * @public + * + * @description Parses a date/time string formatted according to the + * POSIX LC_TIME d_t_fmt property of the preset locale. + * + * @param {String} formattedDateTime The formatted date/time, must be + * valid. + * + * @returns {String} The parsed date/time in ISO-8601 format + * (YYYY-MM-DD HH:MM:SS), e.g. "2010-03-31 23:59:59". + * + * @throws Error on a parse exception. + */ + this.parseDateTime = function(formattedDateTime) { + + if (typeof formattedDateTime != "string") + throw "Parse error: Argument must be a string"; + + var dt = this._extractTokens(this.lc.d_t_fmt, formattedDateTime); + + var timeDefined = false; + var dateDefined = false; + + if (dt.hour !== null && dt.minute !== null && dt.second !== null) { + timeDefined = true; + } + else if (dt.hourAmPm !== null && dt.am !== null && dt.minute !== null && dt.second !== null) { + if (dt.am) { + // AM [12(midnight), 1 .. 11] + if (dt.hourAmPm == 12) + dt.hour = 0; + else + dt.hour = parseInt(dt.hourAmPm, 10); + } + else { + // PM [12(noon), 1 .. 11] + if (dt.hourAmPm == 12) + dt.hour = 12; + else + dt.hour = parseInt(dt.hourAmPm, 10) + 12; + } + timeDefined = true; + } + + if (dt.year !== null && dt.month !== null && dt.day !== null) { + dateDefined = true; + } + + if (dateDefined && timeDefined) + return jsworld._zeroPad(dt.year, 4) + + "-" + + jsworld._zeroPad(dt.month, 2) + + "-" + + jsworld._zeroPad(dt.day, 2) + + " " + + jsworld._zeroPad(dt.hour, 2) + + ":" + + jsworld._zeroPad(dt.minute, 2) + + ":" + + jsworld._zeroPad(dt.second, 2); + else + throw "Parse error: Invalid/ambiguous date/time string"; + }; + + + /** + * @private + * + * @description Parses a string according to the specified format + * specification. + * + * @param {String} fmtSpec The format specification, e.g. "%I:%M:%S %p". + * @param {String} s The string to parse. + * + * @returns {object} An object with set properties year, month, day, + * hour, minute and second if the corresponding values are + * found in the parsed string. + * + * @throws Error on a parse exception. + */ + this._extractTokens = function(fmtSpec, s) { + + // the return object containing the parsed date/time properties + var dt = { + // for date and date/time strings + "year" : null, + "month" : null, + "day" : null, + + // for time and date/time strings + "hour" : null, + "hourAmPm" : null, + "am" : null, + "minute" : null, + "second" : null, + + // used internally only + "weekday" : null + }; + + + // extract and process each token in the date/time spec + while (fmtSpec.length > 0) { + + // Do we have a valid "%\w" placeholder in stream? + if (fmtSpec.charAt(0) == "%" && fmtSpec.charAt(1) != "") { + + // get placeholder + var placeholder = fmtSpec.substring(0,2); + + if (placeholder == "%%") { + // escaped '%'' + s = s.substring(1); + } + else if (placeholder == "%a") { + // abbreviated weekday name + for (var i = 0; i < this.lc.abday.length; i++) { + + if (jsworld._stringStartsWith(s, this.lc.abday[i])) { + dt.weekday = i; + s = s.substring(this.lc.abday[i].length); + break; + } + } + + if (dt.weekday === null) + throw "Parse error: Unrecognised abbreviated weekday name (%a)"; + } + else if (placeholder == "%A") { + // weekday name + for (var i = 0; i < this.lc.day.length; i++) { + + if (jsworld._stringStartsWith(s, this.lc.day[i])) { + dt.weekday = i; + s = s.substring(this.lc.day[i].length); + break; + } + } + + if (dt.weekday === null) + throw "Parse error: Unrecognised weekday name (%A)"; + } + else if (placeholder == "%b" || placeholder == "%h") { + // abbreviated month name + for (var i = 0; i < this.lc.abmon.length; i++) { + + if (jsworld._stringStartsWith(s, this.lc.abmon[i])) { + dt.month = i + 1; + s = s.substring(this.lc.abmon[i].length); + break; + } + } + + if (dt.month === null) + throw "Parse error: Unrecognised abbreviated month name (%b)"; + } + else if (placeholder == "%B") { + // month name + for (var i = 0; i < this.lc.mon.length; i++) { + + if (jsworld._stringStartsWith(s, this.lc.mon[i])) { + dt.month = i + 1; + s = s.substring(this.lc.mon[i].length); + break; + } + } + + if (dt.month === null) + throw "Parse error: Unrecognised month name (%B)"; + } + else if (placeholder == "%d") { + // day of the month [01..31] + if (/^0[1-9]|[1-2][0-9]|3[0-1]/.test(s)) { + dt.day = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised day of the month (%d)"; + } + else if (placeholder == "%e") { + // day of the month [1..31] + + // Note: if %e is leading in fmt string -> space padded! + + var day = s.match(/^\s?(\d{1,2})/); + dt.day = parseInt(day, 10); + + if (isNaN(dt.day) || dt.day < 1 || dt.day > 31) + throw "Parse error: Unrecognised day of the month (%e)"; + + s = s.substring(day.length); + } + else if (placeholder == "%F") { + // equivalent to %Y-%m-%d (ISO-8601 date format) + + // year [nnnn] + if (/^\d\d\d\d/.test(s)) { + dt.year = parseInt(s.substring(0,4), 10); + s = s.substring(4); + } + else { + throw "Parse error: Unrecognised date (%F)"; + } + + // - + if (jsworld._stringStartsWith(s, "-")) + s = s.substring(1); + else + throw "Parse error: Unrecognised date (%F)"; + + // month [01..12] + if (/^0[1-9]|1[0-2]/.test(s)) { + dt.month = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised date (%F)"; + + // - + if (jsworld._stringStartsWith(s, "-")) + s = s.substring(1); + else + throw "Parse error: Unrecognised date (%F)"; + + // day of the month [01..31] + if (/^0[1-9]|[1-2][0-9]|3[0-1]/.test(s)) { + dt.day = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised date (%F)"; + } + else if (placeholder == "%H") { + // hour [00..23] + if (/^[0-1][0-9]|2[0-3]/.test(s)) { + dt.hour = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised hour (%H)"; + } + else if (placeholder == "%I") { + // hour [01..12] + if (/^0[1-9]|1[0-2]/.test(s)) { + dt.hourAmPm = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised hour (%I)"; + } + else if (placeholder == "%k") { + // hour [0..23] + var h = s.match(/^(\d{1,2})/); + dt.hour = parseInt(h, 10); + + if (isNaN(dt.hour) || dt.hour < 0 || dt.hour > 23) + throw "Parse error: Unrecognised hour (%k)"; + + s = s.substring(h.length); + } + else if (placeholder == "%l") { + // hour AM/PM [1..12] + var h = s.match(/^(\d{1,2})/); + dt.hourAmPm = parseInt(h, 10); + + if (isNaN(dt.hourAmPm) || dt.hourAmPm < 1 || dt.hourAmPm > 12) + throw "Parse error: Unrecognised hour (%l)"; + + s = s.substring(h.length); + } + else if (placeholder == "%m") { + // month [01..12] + if (/^0[1-9]|1[0-2]/.test(s)) { + dt.month = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised month (%m)"; + } + else if (placeholder == "%M") { + // minute [00..59] + if (/^[0-5][0-9]/.test(s)) { + dt.minute = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised minute (%M)"; + } + else if (placeholder == "%n") { + // new line + + if (s.charAt(0) == "\n") + s = s.substring(1); + else + throw "Parse error: Unrecognised new line (%n)"; + } + else if (placeholder == "%p") { + // locale's equivalent of AM/PM + if (jsworld._stringStartsWith(s, this.lc.am)) { + dt.am = true; + s = s.substring(this.lc.am.length); + } + else if (jsworld._stringStartsWith(s, this.lc.pm)) { + dt.am = false; + s = s.substring(this.lc.pm.length); + } + else + throw "Parse error: Unrecognised AM/PM value (%p)"; + } + else if (placeholder == "%P") { + // same as %p but forced lower case + if (jsworld._stringStartsWith(s, this.lc.am.toLowerCase())) { + dt.am = true; + s = s.substring(this.lc.am.length); + } + else if (jsworld._stringStartsWith(s, this.lc.pm.toLowerCase())) { + dt.am = false; + s = s.substring(this.lc.pm.length); + } + else + throw "Parse error: Unrecognised AM/PM value (%P)"; + } + else if (placeholder == "%R") { + // same as %H:%M + + // hour [00..23] + if (/^[0-1][0-9]|2[0-3]/.test(s)) { + dt.hour = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised time (%R)"; + + // : + if (jsworld._stringStartsWith(s, ":")) + s = s.substring(1); + else + throw "Parse error: Unrecognised time (%R)"; + + // minute [00..59] + if (/^[0-5][0-9]/.test(s)) { + dt.minute = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised time (%R)"; + + } + else if (placeholder == "%S") { + // second [00..59] + if (/^[0-5][0-9]/.test(s)) { + dt.second = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised second (%S)"; + } + else if (placeholder == "%T") { + // same as %H:%M:%S + + // hour [00..23] + if (/^[0-1][0-9]|2[0-3]/.test(s)) { + dt.hour = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised time (%T)"; + + // : + if (jsworld._stringStartsWith(s, ":")) + s = s.substring(1); + else + throw "Parse error: Unrecognised time (%T)"; + + // minute [00..59] + if (/^[0-5][0-9]/.test(s)) { + dt.minute = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised time (%T)"; + + // : + if (jsworld._stringStartsWith(s, ":")) + s = s.substring(1); + else + throw "Parse error: Unrecognised time (%T)"; + + // second [00..59] + if (/^[0-5][0-9]/.test(s)) { + dt.second = parseInt(s.substring(0,2), 10); + s = s.substring(2); + } + else + throw "Parse error: Unrecognised time (%T)"; + } + else if (placeholder == "%w") { + // weekday [0..6] + if (/^\d/.test(s)) { + dt.weekday = parseInt(s.substring(0,1), 10); + s = s.substring(1); + } + else + throw "Parse error: Unrecognised weekday number (%w)"; + } + else if (placeholder == "%y") { + // year [00..99] + if (/^\d\d/.test(s)) { + var year2digits = parseInt(s.substring(0,2), 10); + + // this conversion to year[nnnn] is arbitrary!!! + if (year2digits > 50) + dt.year = 1900 + year2digits; + else + dt.year = 2000 + year2digits; + + s = s.substring(2); + } + else + throw "Parse error: Unrecognised year (%y)"; + } + else if (placeholder == "%Y") { + // year [nnnn] + if (/^\d\d\d\d/.test(s)) { + dt.year = parseInt(s.substring(0,4), 10); + s = s.substring(4); + } + else + throw "Parse error: Unrecognised year (%Y)"; + } + + else if (placeholder == "%Z") { + // time-zone place holder is not supported + + if (fmtSpec.length === 0) + break; // ignore rest of fmt spec + } + + // remove the spec placeholder that was just parsed + fmtSpec = fmtSpec.substring(2); + } + else { + // If we don't have a placeholder, the chars + // at pos. 0 of format spec and parsed string must match + + // Note: Space chars treated 1:1 ! + + if (fmtSpec.charAt(0) != s.charAt(0)) + throw "Parse error: Unexpected symbol \"" + s.charAt(0) + "\" in date/time string"; + + fmtSpec = fmtSpec.substring(1); + s = s.substring(1); + } + } + + // parsing finished, return composite date/time object + return dt; + }; +}; + + +/** + * @class + * Class for parsing localised currency amount strings. + * + * @public + * @constructor + * @description Creates a new monetary parser for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_MONETARY formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.MonetaryParser = function(locale) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance"; + + + this.lc = locale; + + + /** + * @public + * + * @description Parses a currency amount string formatted according to + * the preset locale. Leading and trailing whitespace is ignored; the + * amount may also be formatted without thousands separators. Both + * the local (shorthand) symbol and the ISO 4217 code are accepted to + * designate the currency in the formatted amount. + * + * @param {String} formattedCurrency The formatted currency amount. + * + * @returns {Number} The parsed amount. + * + * @throws Error on a parse exception. + */ + this.parse = function(formattedCurrency) { + + if (typeof formattedCurrency != "string") + throw "Parse error: Argument must be a string"; + + // Detect the format type and remove the currency symbol + var symbolType = this._detectCurrencySymbolType(formattedCurrency); + + var formatType, s; + + if (symbolType == "local") { + formatType = "local"; + s = formattedCurrency.replace(this.lc.getCurrencySymbol(), ""); + } + else if (symbolType == "int") { + formatType = "int"; + s = formattedCurrency.replace(this.lc.getIntCurrencySymbol(), ""); + } + else if (symbolType == "none") { + formatType = "local"; // assume local + s = formattedCurrency; + } + else + throw "Parse error: Internal assert failure"; + + // Remove any thousands separators + s = jsworld._stringReplaceAll(s, this.lc.mon_thousands_sep, ""); + + // Replace any local radix char with JavaScript's "." + s = s.replace(this.lc.mon_decimal_point, "."); + + // Remove all whitespaces + s = s.replace(/\s*/g, ""); + + // Remove any local non-negative sign + s = this._removeLocalNonNegativeSign(s, formatType); + + // Replace any local minus sign with JavaScript's "-" and put + // it in front of the amount if necessary + // (special parentheses rule checked too) + s = this._normaliseNegativeSign(s, formatType); + + // Finally, we should be left with a bare parsable decimal number + if (jsworld._isNumber(s)) + return parseFloat(s, 10); + else + throw "Parse error: Invalid currency amount string"; + }; + + + /** + * @private + * + * @description Tries to detect the symbol type used in the specified + * formatted currency string: local(shorthand), + * international (ISO-4217 code) or none. + * + * @param {String} formattedCurrency The the formatted currency string. + * + * @return {String} With possible values "local", "int" or "none". + */ + this._detectCurrencySymbolType = function(formattedCurrency) { + + // Check for whichever sign (int/local) is longer first + // to cover cases such as MOP/MOP$ and ZAR/R + + if (this.lc.getCurrencySymbol().length > this.lc.getIntCurrencySymbol().length) { + + if (formattedCurrency.indexOf(this.lc.getCurrencySymbol()) != -1) + return "local"; + else if (formattedCurrency.indexOf(this.lc.getIntCurrencySymbol()) != -1) + return "int"; + else + return "none"; + } + else { + if (formattedCurrency.indexOf(this.lc.getIntCurrencySymbol()) != -1) + return "int"; + else if (formattedCurrency.indexOf(this.lc.getCurrencySymbol()) != -1) + return "local"; + else + return "none"; + } + }; + + + /** + * @private + * + * @description Removes a local non-negative sign in a formatted + * currency string if it is found. This is done according to the + * locale properties p_sign_posn and int_p_sign_posn. + * + * @param {String} s The input string. + * @param {String} formatType With possible values "local" or "int". + * + * @returns {String} The processed string. + */ + this._removeLocalNonNegativeSign = function(s, formatType) { + + s = s.replace(this.lc.positive_sign, ""); + + // check for enclosing parentheses rule + if (((formatType == "local" && this.lc.p_sign_posn === 0) || + (formatType == "int" && this.lc.int_p_sign_posn === 0) ) && + /\(\d+\.?\d*\)/.test(s)) { + s = s.replace("(", ""); + s = s.replace(")", ""); + } + + return s; + }; + + + /** + * @private + * + * @description Replaces a local negative sign with the standard + * JavaScript minus ("-") sign placed in the correct position + * (preceding the amount). This is done according to the locale + * properties for negative sign symbol and relative position. + * + * @param {String} s The input string. + * @param {String} formatType With possible values "local" or "int". + * + * @returns {String} The processed string. + */ + this._normaliseNegativeSign = function(s, formatType) { + + // replace local negative symbol with JavaScript's "-" + s = s.replace(this.lc.negative_sign, "-"); + + // check for enclosing parentheses rule and replace them + // with negative sign before the amount + if ((formatType == "local" && this.lc.n_sign_posn === 0) || + (formatType == "int" && this.lc.int_n_sign_posn === 0) ) { + + if (/^\(\d+\.?\d*\)$/.test(s)) { + + s = s.replace("(", ""); + s = s.replace(")", ""); + return "-" + s; + } + } + + // check for rule negative sign succeeding the amount + if (formatType == "local" && this.lc.n_sign_posn == 2 || + formatType == "int" && this.lc.int_n_sign_posn == 2 ) { + + if (/^\d+\.?\d*-$/.test(s)) { + s = s.replace("-", ""); + return "-" + s; + } + } + + // check for rule cur. sym. succeeds and sign adjacent + if (formatType == "local" && this.lc.n_cs_precedes === 0 && this.lc.n_sign_posn == 3 || + formatType == "local" && this.lc.n_cs_precedes === 0 && this.lc.n_sign_posn == 4 || + formatType == "int" && this.lc.int_n_cs_precedes === 0 && this.lc.int_n_sign_posn == 3 || + formatType == "int" && this.lc.int_n_cs_precedes === 0 && this.lc.int_n_sign_posn == 4 ) { + + if (/^\d+\.?\d*-$/.test(s)) { + s = s.replace("-", ""); + return "-" + s; + } + } + + return s; + }; +}; + +// end-of-file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs2.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs2.js new file mode 100644 index 00000000..4e9f9672 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs2.js @@ -0,0 +1,166 @@ +jsworld.Locale = function(properties) { + + // LC_NUMERIC + + + this.frac_digits = properties.frac_digits; + + + // may be empty string/null for currencies with no fractional part + if (properties.mon_decimal_point === null || properties.mon_decimal_point == "") { + + if (this.frac_digits > 0) + throw "Error: Undefined mon_decimal_point property"; + else + properties.mon_decimal_point = ""; + } + + if (typeof properties.mon_decimal_point != "string") + throw "Error: Invalid/missing mon_decimal_point property"; + + this.mon_decimal_point = properties.mon_decimal_point; + + + if (typeof properties.mon_thousands_sep != "string") + throw "Error: Invalid/missing mon_thousands_sep property"; + + this.mon_thousands_sep = properties.mon_thousands_sep; + + + if (typeof properties.mon_grouping != "string") + throw "Error: Invalid/missing mon_grouping property"; + + this.mon_grouping = properties.mon_grouping; + + + if (typeof properties.positive_sign != "string") + throw "Error: Invalid/missing positive_sign property"; + + this.positive_sign = properties.positive_sign; + + + if (typeof properties.negative_sign != "string") + throw "Error: Invalid/missing negative_sign property"; + + this.negative_sign = properties.negative_sign; + + + if (properties.p_cs_precedes !== 0 && properties.p_cs_precedes !== 1) + throw "Error: Invalid/missing p_cs_precedes property, must be 0 or 1"; + + this.p_cs_precedes = properties.p_cs_precedes; + + + if (properties.n_cs_precedes !== 0 && properties.n_cs_precedes !== 1) + throw "Error: Invalid/missing n_cs_precedes, must be 0 or 1"; + + this.n_cs_precedes = properties.n_cs_precedes; + + + if (properties.p_sep_by_space !== 0 && + properties.p_sep_by_space !== 1 && + properties.p_sep_by_space !== 2) + throw "Error: Invalid/missing p_sep_by_space property, must be 0, 1 or 2"; + + this.p_sep_by_space = properties.p_sep_by_space; + + + if (properties.n_sep_by_space !== 0 && + properties.n_sep_by_space !== 1 && + properties.n_sep_by_space !== 2) + throw "Error: Invalid/missing n_sep_by_space property, must be 0, 1, or 2"; + + this.n_sep_by_space = properties.n_sep_by_space; + + + if (properties.p_sign_posn !== 0 && + properties.p_sign_posn !== 1 && + properties.p_sign_posn !== 2 && + properties.p_sign_posn !== 3 && + properties.p_sign_posn !== 4) + throw "Error: Invalid/missing p_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.p_sign_posn = properties.p_sign_posn; + + + if (properties.n_sign_posn !== 0 && + properties.n_sign_posn !== 1 && + properties.n_sign_posn !== 2 && + properties.n_sign_posn !== 3 && + properties.n_sign_posn !== 4) + throw "Error: Invalid/missing n_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.n_sign_posn = properties.n_sign_posn; + + + if (typeof properties.int_frac_digits != "number" && properties.int_frac_digits < 0) + throw "Error: Invalid/missing int_frac_digits property"; + + this.int_frac_digits = properties.int_frac_digits; + + + if (properties.int_p_cs_precedes !== 0 && properties.int_p_cs_precedes !== 1) + throw "Error: Invalid/missing int_p_cs_precedes property, must be 0 or 1"; + + this.int_p_cs_precedes = properties.int_p_cs_precedes; + + + if (properties.int_n_cs_precedes !== 0 && properties.int_n_cs_precedes !== 1) + throw "Error: Invalid/missing int_n_cs_precedes property, must be 0 or 1"; + + this.int_n_cs_precedes = properties.int_n_cs_precedes; + + + if (properties.int_p_sep_by_space !== 0 && + properties.int_p_sep_by_space !== 1 && + properties.int_p_sep_by_space !== 2) + throw "Error: Invalid/missing int_p_sep_by_spacev, must be 0, 1 or 2"; + + this.int_p_sep_by_space = properties.int_p_sep_by_space; + + + if (properties.int_n_sep_by_space !== 0 && + properties.int_n_sep_by_space !== 1 && + properties.int_n_sep_by_space !== 2) + throw "Error: Invalid/missing int_n_sep_by_space property, must be 0, 1, or 2"; + + this.int_n_sep_by_space = properties.int_n_sep_by_space; + + + if (properties.int_p_sign_posn !== 0 && + properties.int_p_sign_posn !== 1 && + properties.int_p_sign_posn !== 2 && + properties.int_p_sign_posn !== 3 && + properties.int_p_sign_posn !== 4) + throw "Error: Invalid/missing int_p_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.int_p_sign_posn = properties.int_p_sign_posn; + + + if (properties.int_n_sign_posn !== 0 && + properties.int_n_sign_posn !== 1 && + properties.int_n_sign_posn !== 2 && + properties.int_n_sign_posn !== 3 && + properties.int_n_sign_posn !== 4) + throw "Error: Invalid/missing int_n_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.int_n_sign_posn = properties.int_n_sign_posn; + + + // LC_TIME + + if (properties == null || typeof properties != "object") + throw "Error: Invalid/missing time locale properties"; + + + // parse the supported POSIX LC_TIME properties + + // abday + try { + this.abday = this._parseList(properties.abday, 7); + } + catch (error) { + throw "Error: Invalid abday property: " + error; + } + +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/uglify-js.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/uglify-js.js new file mode 100644 index 00000000..4305e232 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/uglify-js.js @@ -0,0 +1,17 @@ +//convienence function(src, [options]); +function uglify(orig_code, options){ + options || (options = {}); + var jsp = uglify.parser; + var pro = uglify.uglify; + + var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST + ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names + ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations + var final_code = pro.gen_code(ast, options.gen_options); // compressed code here + return final_code; +}; + +uglify.parser = require("./lib/parse-js"); +uglify.uglify = require("./lib/process"); + +module.exports = uglify \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.npmignore b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.npmignore new file mode 100644 index 00000000..82337939 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.npmignore @@ -0,0 +1,6 @@ +npm-debug.log +node_modules +.*.swp +.lock-* +build + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.travis.yml b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.travis.yml new file mode 100644 index 00000000..08e4dad6 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +npm_args: --ws:native +node_js: + - "0.6" + - "0.8" + - "0.10" diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/History.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/History.md new file mode 100644 index 00000000..63cf0ea6 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/History.md @@ -0,0 +1,312 @@ +v0.4.31 - September 23th, 2013 +===================== + +* Component support + +v0.4.30 - August 30th, 2013 +===================== + +* BufferedAmount could be undefined, default to 0 [TooTallNate] +* Support protocols as second argument and options as third [TooTallNate] +* Proper browserify shim [mcollina] +* Broadcasting example in README [stefanocudini] + +v0.4.29 - August 23th, 2013 +===================== +* Small clean up of the Node 0.11 support by using NAN from the NPM registry [kkoopa] +* Support for custom `Agent`'s through the options. [gramakri] & [TooTallNate] +* Support for custom headers through the options [3rd-Eden] +* Added a `gypfile` flag to the package.json for compiled module discovery [wolfeidau] + +v0.4.28 - August 16th, 2013 +===================== +* Node 0.11 support. [kkoopa] +* Authorization headers are sent when basic auth is used in the url [jcrugzz] +* Origin header will now include the port number [Jason Plum] +* Race condition fixed where data was received before the readyState was updated. [saschagehlich] + +v0.4.27 - June 27th, 2013 +===================== +* Frames are no longer masked in `wscat`. [slaskis] +* Don't retrain reference to large slab buffers. [jmatthewsr-msi] +* Don't use Buffer.byteLength for ArrayBuffer's. [Anthony Pesch] +* Fix browser field in package.json. [shtylman] +* Client-side certificate support & documentation improvements. [Lukas Berns] +* WebSocket readyState's is added to the prototype for spec compatiblity. [BallBearing] +* Use Object.defineProperty. [arlolra] +* Autodetect ArrayBuffers as binary when sending. [BallBearing] +* Check instanceof Buffer for binary data. [arlolra] +* Emit the close event before destroying the internal socket. [3rd-Eden] +* Don't setup multiply timeouts for one connection. [AndreasMadsen] +* Allow support for binding to ethereal port. [wpreul] +* Fix broken terminate reference. [3rd-Eden] +* Misc node 0.10 test fixes and documentation improvements. [3rd-Eden] +* Ensure ssl options are propagated to request. [einaros] +* Add 'Host' and 'Origin' to request header. [Lars-Magnus Skog] +* Subprotocol support. [kanaka] +* Honor ArrayBufferView's byteOffset when sending. [Anthony Pesch] +* Added target attribute for events. [arlolra] + +v0.4.26 - Skipped +===================== + +v0.4.25 - December 17th, 2012 +===================== +* Removed install.js. [shtylman] +* Added browser field to package.json. [shtylman] +* Support overwriting host header. [Raynos] +* Emit 'listening' also with custom http server. [sebiq] + +v0.4.24 - December 6th, 2012 +===================== +* Yet another intermediate release, to not delay minor features any longer. +* Native support installation issues further circumvented. [einaros] + +v0.4.23 - November 19th, 2012 +===================== +* Service release - last before major upgrade. +* Changes default host from 127.0.0.1 to 0.0.0.0. [einaros] + +v0.4.22 - October 3rd, 2012 +===================== +* clear failsafe cleanup timeout once cleanup is called [AndreasMadsen] +* added w3c compatible CloseEvent for onclose / addEventListener("close", ...). [einaros] +* fix the sub protocol header handler [sonnyp] +* fix unhandled exception if socket closes and 'error' is emitted [jmatthewsr-ms] + +v0.4.21 - July 14th, 2012 +===================== +* Emit error if server reponds with anything other than status code 101. [einaros] +* Added 'headers' event to server. [rauchg] +* path.exists moved to fs.exists. [blakmatrix] + +v0.4.20 - June 26th, 2012 +===================== +* node v0.8.0 compatibility release. + +v0.4.19 - June 19th, 2012 +===================== +* Change sender to merge buffers for relatively small payloads, may improve perf in some cases [einaros] +* Avoid EventEmitter for Receiver classes. As above this may improve perf. [einaros] +* Renamed fallback files from the somewhat misleading '*Windows'. [einaros] + +v0.4.18 - June 14th 2012 +===================== +* Fixed incorrect md5 digest encoding in Hixie handshake [nicokaiser] +* Added example of use with Express 3 [einaros] +* Change installation procedure to not require --ws:native to build native extensions. They will now build if a compiler is available. [einaros] + +v0.4.17 - June 13th 2012 +===================== +* Improve error handling during connection handshaking [einaros] +* Ensure that errors are caught also after connection teardown [nicokaiser] +* Update 'mocha' version to 1.1.0. [einaros] +* Stop showing 'undefined' for some error logs. [tricknotes] +* Update 'should' version to 0.6.3 [tricknotes] + +v0.4.16 - June 1st 2012 +===================== +* Build fix for Windows. [einaros] + +v0.4.15 - May 20th 2012 +===================== +* Enable fauxe streaming for hixie tansport. [einaros] +* Allow hixie sender to deal with buffers. [einaros/pigne] +* Allow error code 1011. [einaros] +* Fix framing for empty packets (empty pings and pongs might break). [einaros] +* Improve error and close handling, to avoid connections lingering in CLOSING state. [einaros] + +v0.4.14 - Apr 30th 2012 +===================== +* use node-gyp instead of node-waf [TooTallNate] +* remove old windows compatibility makefile, and silently fall back to native modules [einaros] +* ensure connection status [nicokaiser] +* websocket client updated to use port 443 by default for wss:// connections [einaros] +* support unix sockets [kschzt] + +v0.4.13 - Apr 12th 2012 +===================== + +* circumvent node 0.6+ related memory leak caused by Object.defineProperty [nicokaiser] +* improved error handling, improving stability in massive load use cases [nicokaiser] + +v0.4.12 - Mar 30th 2012 +===================== + +* various memory leak / possible memory leak cleanups [einaros] +* api documentation [nicokaiser] +* add option to disable client tracking [nicokaiser] + +v0.4.11 - Mar 24th 2012 +===================== + +* node v0.7 compatibillity release +* gyp support [TooTallNate] +* commander dependency update [jwueller] +* loadbalancer support [nicokaiser] + +v0.4.10 - Mar 22th 2012 +===================== + +* Final hixie close frame fixes. [nicokaiser] + +v0.4.9 - Mar 21st 2012 +===================== + +* Various hixie bugfixes (such as proper close frame handling). [einaros] + +v0.4.8 - Feb 29th 2012 +===================== + +* Allow verifyClient to run asynchronously [karlsequin] +* Various bugfixes and cleanups. [einaros] + +v0.4.7 - Feb 21st 2012 +===================== + +* Exposed bytesReceived from websocket client object, which makes it possible to implement bandwidth sampling. [einaros] +* Updated browser based file upload example to include and output per websocket channel bandwidth sampling. [einaros] +* Changed build scripts to check which architecture is currently in use. Required after the node.js changes to have prebuilt packages target ia32 by default. [einaros] + +v0.4.6 - Feb 9th 2012 +===================== + +* Added browser based file upload example. [einaros] +* Added server-to-browser status push example. [einaros] +* Exposed pause() and resume() on WebSocket object, to enable client stream shaping. [einaros] + +v0.4.5 - Feb 7th 2012 +===================== + +* Corrected regression bug in handling of connections with the initial frame delivered across both http upgrade head and a standalone packet. This would lead to a race condition, which in some cases could cause message corruption. [einaros] + +v0.4.4 - Feb 6th 2012 +===================== + +* Pass original request object to verifyClient, for cookie or authentication verifications. [einaros] +* Implemented addEventListener and slightly improved the emulation API by adding a MessageEvent with a readonly data attribute. [aslakhellesoy] +* Rewrite parts of hybi receiver to avoid stack overflows for large amounts of packets bundled in the same buffer / packet. [einaros] + +v0.4.3 - Feb 4th 2012 +===================== + +* Prioritized update: Corrected issue which would cause sockets to stay open longer than necessary, and resource leakage because of this. [einaros] + +v0.4.2 - Feb 4th 2012 +===================== + +* Breaking change: WebSocketServer's verifyOrigin option has been renamed to verifyClient. [einaros] +* verifyClient now receives { origin: 'origin header', secure: true/false }, where 'secure' will be true for ssl connections. [einaros] +* Split benchmark, in preparation for more thorough case. [einaros] +* Introduced hixie-76 draft support for server, since Safari (iPhone / iPad / OS X) and Opera still aren't updated to use Hybi. [einaros] +* Expose 'supports' object from WebSocket, to indicate e.g. the underlying transport's support for binary data. [einaros] +* Test and code cleanups. [einaros] + +v0.4.1 - Jan 25th 2012 +===================== + +* Use readline in wscat [tricknotes] +* Refactor _state away, in favor of the new _readyState [tricknotes] +* travis-ci integration [einaros] +* Fixed race condition in testsuite, causing a few tests to fail (without actually indicating errors) on travis [einaros] +* Expose pong event [paddybyers] +* Enabled running of WebSocketServer in noServer-mode, meaning that upgrades are passed in manually. [einaros] +* Reworked connection procedure for WebSocketServer, and cleaned up tests. [einaros] + +v0.4.0 - Jan 2nd 2012 +===================== + +* Windows compatibility [einaros] +* Windows compatible test script [einaros] + +v0.3.9 - Jan 1st 2012 +====================== + +* Improved protocol framing performance [einaros] +* WSS support [kazuyukitanimura] +* WSS tests [einaros] +* readyState exposed [justinlatimer, tricknotes] +* url property exposed [justinlatimer] +* Removed old 'state' property [einaros] +* Test cleanups [einaros] + +v0.3.8 - Dec 27th 2011 +====================== + +* Made it possible to listen on specific paths, which is especially good to have for precreated http servers [einaros] +* Extensive WebSocket / WebSocketServer cleanup, including changing all internal properties to unconfigurable, unenumerable properties [einaros] +* Receiver modifications to ensure even better performance with fragmented sends [einaros] +* Fixed issue in sender.js, which would cause SlowBuffer instances (such as returned from the crypto library's randomBytes) to be copied (and thus be dead slow) [einaros] +* Removed redundant buffer copy in sender.js, which should improve server performance [einaros] + +v0.3.7 - Dec 25nd 2011 +====================== + +* Added a browser based API which uses EventEmitters internally [3rd-Eden] +* Expose request information from upgrade event for websocket server clients [mmalecki] + +v0.3.6 - Dec 19th 2011 +====================== + +* Added option to let WebSocket.Server use an already existing http server [mmalecki] +* Migrating various option structures to use options.js module [einaros] +* Added a few more tests, options and handshake verifications to ensure that faulty connections are dealt with [einaros] +* Code cleanups in Sender and Receiver, to ensure even faster parsing [einaros] + +v0.3.5 - Dec 13th 2011 +====================== + +* Optimized Sender.js, Receiver.js and bufferutil.cc: + * Apply loop-unrolling-like small block copies rather than use node.js Buffer#copy() (which is slow). + * Mask blocks of data using combination of 32bit xor and loop-unrolling, instead of single bytes. + * Keep pre-made send buffer for small transfers. +* Leak fixes and code cleanups. + +v0.3.3 - Dec 12th 2011 +====================== + +* Compile fix for Linux. +* Rewrote parts of WebSocket.js, to avoid try/catch and thus avoid optimizer bailouts. + +v0.3.2 - Dec 11th 2011 +====================== + +* Further performance updates, including the additions of a native BufferUtil module, which deals with several of the cpu intensive WebSocket operations. + +v0.3.1 - Dec 8th 2011 +====================== + +* Service release, fixing broken tests. + +v0.3.0 - Dec 8th 2011 +====================== + +* Node.js v0.4.x compatibility. +* Code cleanups and efficiency improvements. +* WebSocket server added, although this will still mainly be a client library. +* WebSocket server certified to pass the Autobahn test suite. +* Protocol improvements and corrections - such as handling (redundant) masks for empty fragments. +* 'wscat' command line utility added, which can act as either client or server. + +v0.2.6 - Dec 3rd 2011 +====================== + +* Renamed to 'ws'. Big woop, right -- but easy-websocket really just doesn't cut it anymore! + +v0.2.5 - Dec 3rd 2011 +====================== + + * Rewrote much of the WebSocket parser, to ensure high speed for highly fragmented messages. + * Added a BufferPool, as a start to more efficiently deal with allocations for WebSocket connections. More work to come, in that area. + * Updated the Autobahn report, at http://einaros.github.com/easy-websocket, with comparisons against WebSocket-Node 1.0.2 and Chrome 16. + +v0.2.0 - Nov 25th 2011 +====================== + + * Major rework to make sure all the Autobahn test cases pass. Also updated the internal tests to cover more corner cases. + +v0.1.2 - Nov 14th 2011 +====================== + + * Back and forth, back and forth: now settled on keeping the api (event names, methods) closer to the websocket browser api. This will stick now. + * Started keeping this history record. Better late than never, right? diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/Makefile b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/Makefile new file mode 100644 index 00000000..151aa2ba --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/Makefile @@ -0,0 +1,40 @@ +ALL_TESTS = $(shell find test/ -name '*.test.js') +ALL_INTEGRATION = $(shell find test/ -name '*.integration.js') + +all: + node-gyp configure build + +clean: + node-gyp clean + +run-tests: + @./node_modules/.bin/mocha \ + -t 2000 \ + -s 2400 \ + $(TESTFLAGS) \ + $(TESTS) + +run-integrationtests: + @./node_modules/.bin/mocha \ + -t 5000 \ + -s 6000 \ + $(TESTFLAGS) \ + $(TESTS) + +test: + @$(MAKE) NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests + +integrationtest: + @$(MAKE) NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_PATH=lib TESTS="$(ALL_INTEGRATION)" run-integrationtests + +benchmark: + @node bench/sender.benchmark.js + @node bench/parser.benchmark.js + +autobahn: + @NODE_PATH=lib node test/autobahn.js + +autobahn-server: + @NODE_PATH=lib node test/autobahn-server.js + +.PHONY: test diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/README.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/README.md new file mode 100644 index 00000000..e6646e76 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/README.md @@ -0,0 +1,171 @@ +[![Build Status](https://secure.travis-ci.org/einaros/ws.png)](http://travis-ci.org/einaros/ws) + +# ws: a node.js websocket library # + +`ws` is a simple to use websocket implementation, up-to-date against RFC-6455, and [probably the fastest WebSocket library for node.js](http://web.archive.org/web/20130314230536/http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs). + +Passes the quite extensive Autobahn test suite. See http://einaros.github.com/ws for the full reports. + +Comes with a command line utility, `wscat`, which can either act as a server (--listen), or client (--connect); Use it to debug simple websocket services. + +## Protocol support ## + +* **Hixie draft 76** (Old and deprecated, but still in use by Safari and Opera. Added to ws version 0.4.2, but server only. Can be disabled by setting the `disableHixie` option to true.) +* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`, or argument `-p 8` for wscat) +* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`, or argument `-p 13` for wscat) + +_See the echo.websocket.org example below for how to use the `protocolVersion` option._ + +## Usage ## + +### Installing ### + +`npm install ws` + +### Sending and receiving text data ### + +```js +var WebSocket = require('ws'); +var ws = new WebSocket('ws://www.host.com/path'); +ws.on('open', function() { + ws.send('something'); +}); +ws.on('message', function(data, flags) { + // flags.binary will be set if a binary data is received + // flags.masked will be set if the data was masked +}); +``` + +### Sending binary data ### + +```js +var WebSocket = require('ws'); +var ws = new WebSocket('ws://www.host.com/path'); +ws.on('open', function() { + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.send(array, {binary: true, mask: true}); +}); +``` + +Setting `mask`, as done for the send options above, will cause the data to be masked according to the websocket protocol. The same option applies for text data. + +### Server example ### + +```js +var WebSocketServer = require('ws').Server + , wss = new WebSocketServer({port: 8080}); +wss.on('connection', function(ws) { + ws.on('message', function(message) { + console.log('received: %s', message); + }); + ws.send('something'); +}); +``` + +### Server sending broadcast data ### + +```js +var WebSocketServer = require('ws').Server + , wss = new WebSocketServer({port: 8080}); + +wss.broadcast = function(data) { + for(var i in this.clients) + this.clients[i].send(data); +}; +``` + +### Error handling best practices ### + +```js +// If the WebSocket is closed before the following send is attempted +ws.send('something'); + +// Errors (both immediate and async write errors) can be detected in an optional callback. +// The callback is also the only way of being notified that data has actually been sent. +ws.send('something', function(error) { + // if error is null, the send has been completed, + // otherwise the error object will indicate what failed. +}); + +// Immediate errors can also be handled with try/catch-blocks, but **note** +// that since sends are inherently asynchronous, socket write failures will *not* +// be captured when this technique is used. +try { + ws.send('something'); +} +catch (e) { + // handle error +} +``` + +### echo.websocket.org demo ### + +```js +var WebSocket = require('ws'); +var ws = new WebSocket('ws://echo.websocket.org/', {protocolVersion: 8, origin: 'http://websocket.org'}); +ws.on('open', function() { + console.log('connected'); + ws.send(Date.now().toString(), {mask: true}); +}); +ws.on('close', function() { + console.log('disconnected'); +}); +ws.on('message', function(data, flags) { + console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags); + setTimeout(function() { + ws.send(Date.now().toString(), {mask: true}); + }, 500); +}); +``` + +### wscat against echo.websocket.org ### + + $ npm install -g ws + $ wscat -c ws://echo.websocket.org -p 8 + connected (press CTRL+C to quit) + > hi there + < hi there + > are you a happy parrot? + < are you a happy parrot? + +### Other examples ### + +For a full example with a browser client communicating with a ws server, see the examples folder. + +Note that the usage together with Express 3.0 is quite different from Express 2.x. The difference is expressed in the two different serverstats-examples. + +Otherwise, see the test cases. + +### Running the tests ### + +`make test` + +## API Docs ## + +See the doc/ directory for Node.js-like docs for the ws classes. + +## License ## + +(The MIT License) + +Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/parser.benchmark.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/parser.benchmark.js new file mode 100644 index 00000000..ff5f737c --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/parser.benchmark.js @@ -0,0 +1,115 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +/** + * Benchmark dependencies. + */ + +var benchmark = require('benchmark') + , Receiver = require('../').Receiver + , suite = new benchmark.Suite('Receiver'); +require('tinycolor'); +require('./util'); + +/** + * Setup receiver. + */ + +suite.on('start', function () { + receiver = new Receiver(); +}); + +suite.on('cycle', function () { + receiver = new Receiver(); +}); + +/** + * Benchmarks. + */ + +var pingMessage = 'Hello' + , pingPacket1 = getBufferFromHexString('89 ' + (pack(2, 0x80 | pingMessage.length)) + + ' 34 83 a8 68 '+ getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68'))); +suite.add('ping message', function () { + receiver.add(pingPacket1); +}); + +var pingPacket2 = getBufferFromHexString('89 00') +suite.add('ping with no data', function () { + receiver.add(pingPacket2); +}); + +var closePacket = getBufferFromHexString('88 00'); +suite.add('close message', function () { + receiver.add(closePacket); + receiver.endPacket(); +}); + +var maskedTextPacket = getBufferFromHexString('81 93 34 83 a8 68 01 b9 92 52 4f a1 c6 09 59 e6 8a 52 16 e6 cb 00 5b a1 d5'); +suite.add('masked text message', function () { + receiver.add(maskedTextPacket); +}); + +binaryDataPacket = (function() { + var length = 125 + , message = new Buffer(length) + for (var i = 0; i < length; ++i) message[i] = i % 10; + return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + + getHexStringFromBuffer(mask(message), '34 83 a8 68')); +})(); +suite.add('binary data (125 bytes)', function () { + try { + receiver.add(binaryDataPacket); + + } + catch(e) {console.log(e)} +}); + +binaryDataPacket2 = (function() { + var length = 65535 + , message = new Buffer(length) + for (var i = 0; i < length; ++i) message[i] = i % 10; + return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + + getHexStringFromBuffer(mask(message), '34 83 a8 68')); +})(); +suite.add('binary data (65535 bytes)', function () { + receiver.add(binaryDataPacket2); +}); + +binaryDataPacket3 = (function() { + var length = 200*1024 + , message = new Buffer(length) + for (var i = 0; i < length; ++i) message[i] = i % 10; + return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + + getHexStringFromBuffer(mask(message), '34 83 a8 68')); +})(); +suite.add('binary data (200 kB)', function () { + receiver.add(binaryDataPacket3); +}); + +/** + * Output progress. + */ + +suite.on('cycle', function (bench, details) { + console.log('\n ' + suite.name.grey, details.name.white.bold); + console.log(' ' + [ + details.hz.toFixed(2).cyan + ' ops/sec'.grey + , details.count.toString().white + ' times executed'.grey + , 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey + , + ].join(', '.grey)); +}); + +/** + * Run/export benchmarks. + */ + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/sender.benchmark.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/sender.benchmark.js new file mode 100644 index 00000000..20c171a5 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/sender.benchmark.js @@ -0,0 +1,66 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +/** + * Benchmark dependencies. + */ + +var benchmark = require('benchmark') + , Sender = require('../').Sender + , suite = new benchmark.Suite('Sender'); +require('tinycolor'); +require('./util'); + +/** + * Setup sender. + */ + +suite.on('start', function () { + sender = new Sender(); + sender._socket = { write: function() {} }; +}); + +suite.on('cycle', function () { + sender = new Sender(); + sender._socket = { write: function() {} }; +}); + +/** + * Benchmarks + */ + +framePacket = new Buffer(200*1024); +framePacket.fill(99); +suite.add('frameAndSend, unmasked (200 kB)', function () { + sender.frameAndSend(0x2, framePacket, true, false); +}); +suite.add('frameAndSend, masked (200 kB)', function () { + sender.frameAndSend(0x2, framePacket, true, true); +}); + +/** + * Output progress. + */ + +suite.on('cycle', function (bench, details) { + console.log('\n ' + suite.name.grey, details.name.white.bold); + console.log(' ' + [ + details.hz.toFixed(2).cyan + ' ops/sec'.grey + , details.count.toString().white + ' times executed'.grey + , 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey + , + ].join(', '.grey)); +}); + +/** + * Run/export benchmarks. + */ + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/speed.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/speed.js new file mode 100644 index 00000000..3ce64146 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/speed.js @@ -0,0 +1,105 @@ +var cluster = require('cluster') + , WebSocket = require('../') + , WebSocketServer = WebSocket.Server + , crypto = require('crypto') + , util = require('util') + , ansi = require('ansi'); +require('tinycolor'); + +function roundPrec(num, prec) { + var mul = Math.pow(10, prec); + return Math.round(num * mul) / mul; +} + +function humanSize(bytes) { + if (bytes >= 1048576) return roundPrec(bytes / 1048576, 2) + ' MB'; + if (bytes >= 1024) return roundPrec(bytes / 1024, 2) + ' kB'; + return roundPrec(bytes, 2) + ' B'; +} + +function generateRandomData(size) { + var buffer = new Buffer(size); + for (var i = 0; i < size; ++i) { + buffer[i] = ~~(Math.random() * 127); + } + return buffer; +} + +if (cluster.isMaster) { + var wss = new WebSocketServer({port: 8181}, function() { + cluster.fork(); + }); + wss.on('connection', function(ws) { + ws.on('message', function(data, flags) { + ws.send(data, {binary: flags&&flags.binary}); + }); + ws.on('close', function() {}); + }); + cluster.on('death', function(worker) { + wss.close(); + }); +} +else { + var cursor = ansi(process.stdout); + + var configs = [ + [true, 10000, 64], + [true, 5000, 16*1024], + [true, 1000, 128*1024], + [true, 100, 1024*1024], + [true, 1, 500*1024*1024], + [false, 10000, 64], + [false, 5000, 16*1024], + [false, 1000, 128*1024], + [false, 100, 1024*1024], + ]; + + var largest = configs[0][1]; + for (var i = 0, l = configs.length; i < l; ++i) { + if (configs[i][2] > largest) largest = configs[i][2]; + } + + console.log('Generating %s of test data ...', humanSize(largest)); + var randomBytes = generateRandomData(largest); + + function roundtrip(useBinary, roundtrips, size, cb) { + var data = randomBytes.slice(0, size); + var prefix = util.format('Running %d roundtrips of %s %s data', roundtrips, humanSize(size), useBinary ? 'binary' : 'text'); + console.log(prefix); + var client = new WebSocket('ws://localhost:' + '8181'); + var dt; + var roundtrip = 0; + function send() { + client.send(data, {binary: useBinary}); + } + client.on('error', function(e) { + console.error(e); + process.exit(); + }); + client.on('open', function() { + dt = Date.now(); + send(); + }); + client.on('message', function(data, flags) { + if (++roundtrip == roundtrips) { + var elapsed = Date.now() - dt; + cursor.up(); + console.log('%s:\t%ss\t%s' + , useBinary ? prefix.green : prefix.cyan + , roundPrec(elapsed / 1000, 1).toString().green.bold + , (humanSize((size * roundtrips) / elapsed * 1000) + '/s').blue.bold); + client.close(); + cb(); + return; + } + process.nextTick(send); + }); + } + + (function run() { + if (configs.length == 0) process.exit(); + var config = configs.shift(); + config.push(run); + roundtrip.apply(null, config); + })(); +} \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/util.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/util.js new file mode 100644 index 00000000..5f012819 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/util.js @@ -0,0 +1,105 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +/** + * Returns a Buffer from a "ff 00 ff"-type hex string. + */ + +getBufferFromHexString = function(byteStr) { + var bytes = byteStr.split(' '); + var buf = new Buffer(bytes.length); + for (var i = 0; i < bytes.length; ++i) { + buf[i] = parseInt(bytes[i], 16); + } + return buf; +} + +/** + * Returns a hex string from a Buffer. + */ + +getHexStringFromBuffer = function(data) { + var s = ''; + for (var i = 0; i < data.length; ++i) { + s += padl(data[i].toString(16), 2, '0') + ' '; + } + return s.trim(); +} + +/** + * Splits a buffer in two parts. + */ + +splitBuffer = function(buffer) { + var b1 = new Buffer(Math.ceil(buffer.length / 2)); + buffer.copy(b1, 0, 0, b1.length); + var b2 = new Buffer(Math.floor(buffer.length / 2)); + buffer.copy(b2, 0, b1.length, b1.length + b2.length); + return [b1, b2]; +} + +/** + * Performs hybi07+ type masking on a hex string or buffer. + */ + +mask = function(buf, maskString) { + if (typeof buf == 'string') buf = new Buffer(buf); + var mask = getBufferFromHexString(maskString || '34 83 a8 68'); + for (var i = 0; i < buf.length; ++i) { + buf[i] ^= mask[i % 4]; + } + return buf; +} + +/** + * Returns a hex string representing the length of a message + */ + +getHybiLengthAsHexString = function(len, masked) { + if (len < 126) { + var buf = new Buffer(1); + buf[0] = (masked ? 0x80 : 0) | len; + } + else if (len < 65536) { + var buf = new Buffer(3); + buf[0] = (masked ? 0x80 : 0) | 126; + getBufferFromHexString(pack(4, len)).copy(buf, 1); + } + else { + var buf = new Buffer(9); + buf[0] = (masked ? 0x80 : 0) | 127; + getBufferFromHexString(pack(16, len)).copy(buf, 1); + } + return getHexStringFromBuffer(buf); +} + +/** + * Unpacks a Buffer into a number. + */ + +unpack = function(buffer) { + var n = 0; + for (var i = 0; i < buffer.length; ++i) { + n = (i == 0) ? buffer[i] : (n * 256) + buffer[i]; + } + return n; +} + +/** + * Returns a hex string, representing a specific byte count 'length', from a number. + */ + +pack = function(length, number) { + return padl(number.toString(16), length, '0').replace(/([0-9a-f][0-9a-f])/gi, '$1 ').trim(); +} + +/** + * Left pads the string 's' to a total length of 'n' with char 'c'. + */ + +padl = function(s, n, c) { + return new Array(1 + n - s.length).join(c) + s; +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bin/wscat b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bin/wscat new file mode 100755 index 00000000..0ec894df --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bin/wscat @@ -0,0 +1,190 @@ +#!/usr/bin/env node + +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var WebSocket = require('../') + , fs = require('fs') + , program = require('commander') + , util = require('util') + , events = require('events') + , readline = require('readline'); + +/** + * InputReader - processes console input + */ + +function Console() { + this.stdin = process.stdin; + this.stdout = process.stdout; + + this.readlineInterface = readline.createInterface(this.stdin, this.stdout); + + var self = this; + this.readlineInterface.on('line', function(data) { + self.emit('line', data); + }); + this.readlineInterface.on('close', function() { + self.emit('close'); + }); + + this._resetInput = function() { + self.clear(); + } +} +util.inherits(Console, events.EventEmitter); + +Console.Colors = { + Red: '\033[31m', + Green: '\033[32m', + Yellow: '\033[33m', + Blue: '\033[34m', + Default: '\033[39m' +}; + +Console.prototype.prompt = function() { + this.readlineInterface.prompt(); +} + +Console.prototype.print = function(msg, color) { + this.clear(); + color = color || Console.Colors.Default; + this.stdout.write(color + msg + Console.Colors.Default + '\n'); + this.prompt(); +} + +Console.prototype.clear = function() { + this.stdout.write('\033[2K\033[E'); +} + +Console.prototype.pause = function() { + this.stdin.on('keypress', this._resetInput); +} + +Console.prototype.resume = function() { + this.stdin.removeListener('keypress', this._resetInput); +} + +/** + * The actual application + */ + +var version = JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version; +program + .version(version) + .usage('[options] ') + .option('-l, --listen ', 'listen on port') + .option('-c, --connect ', 'connect to a websocket server') + .option('-p, --protocol ', 'optional protocol version') + .option('-o, --origin ', 'optional origin') + .option('--host ', 'optional host') + .option('-s, --subprotocol ', 'optional subprotocol') + .parse(process.argv); + +if (program.listen && program.connect) { + console.error('\033[33merror: use either --listen or --connect\033[39m'); + process.exit(-1); +} +else if (program.listen) { + var wsConsole = new Console(); + wsConsole.pause(); + var options = {}; + if (program.protocol) options.protocolVersion = program.protocol; + if (program.origin) options.origin = program.origin; + if (program.subprotocol) options.protocol = program.subprotocol; + var ws = null; + var wss = new WebSocket.Server({port: program.listen}, function() { + wsConsole.print('listening on port ' + program.listen + ' (press CTRL+C to quit)', Console.Colors.Green); + wsConsole.clear(); + }); + wsConsole.on('close', function() { + if (ws) { + try { + ws.close(); + } + catch (e) {} + } + process.exit(0); + }); + wsConsole.on('line', function(data) { + if (ws) { + ws.send(data, {mask: false}); + wsConsole.prompt(); + } + }); + wss.on('connection', function(newClient) { + if (ws) { + // limit to one client + newClient.terminate(); + return; + }; + ws = newClient; + wsConsole.resume(); + wsConsole.prompt(); + wsConsole.print('client connected', Console.Colors.Green); + ws.on('close', function() { + wsConsole.print('disconnected', Console.Colors.Green); + wsConsole.clear(); + wsConsole.pause(); + ws = null; + }); + ws.on('error', function(code, description) { + wsConsole.print('error: ' + code + (description ? ' ' + description : ''), Console.Colors.Yellow); + }); + ws.on('message', function(data, flags) { + wsConsole.print('< ' + data, Console.Colors.Blue); + }); + }); + wss.on('error', function(error) { + wsConsole.print('error: ' + error.toString(), Console.Colors.Yellow); + process.exit(-1); + }); +} +else if (program.connect) { + var wsConsole = new Console(); + var options = {}; + if (program.protocol) options.protocolVersion = program.protocol; + if (program.origin) options.origin = program.origin; + if (program.subprotocol) options.protocol = program.subprotocol; + if (program.host) options.host = program.host; + var ws = new WebSocket(program.connect, options); + ws.on('open', function() { + wsConsole.print('connected (press CTRL+C to quit)', Console.Colors.Green); + wsConsole.on('line', function(data) { + ws.send(data, {mask: true}); + wsConsole.prompt(); + }); + }); + ws.on('close', function() { + wsConsole.print('disconnected', Console.Colors.Green); + wsConsole.clear(); + process.exit(); + }); + ws.on('error', function(code, description) { + wsConsole.print('error: ' + code + (description ? ' ' + description : ''), Console.Colors.Yellow); + process.exit(-1); + }); + ws.on('message', function(data, flags) { + wsConsole.print('< ' + data, Console.Colors.Blue); + }); + wsConsole.on('close', function() { + if (ws) { + try { + ws.close(); + } + catch(e) {} + process.exit(); + } + }); +} +else { + console.error('\033[33merror: use either --listen or --connect\033[39m'); + process.exit(-1); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/binding.gyp b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/binding.gyp new file mode 100644 index 00000000..c9b4d1a4 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/binding.gyp @@ -0,0 +1,16 @@ +{ + 'targets': [ + { + 'target_name': 'validation', + 'include_dirs': ["> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef + +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_objc = CXX($(TOOLSET)) $@ +cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< + +quiet_cmd_objcxx = CXX($(TOOLSET)) $@ +cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# Commands for precompiled header files. +quiet_cmd_pch_c = CXX($(TOOLSET)) $@ +cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ +cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_m = CXX($(TOOLSET)) $@ +cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< +quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ +cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# gyp-mac-tool is written next to the root Makefile by gyp. +# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd +# already. +quiet_cmd_mac_tool = MACTOOL $(4) $< +cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" + +quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ +cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) + +quiet_cmd_infoplist = INFOPLIST $@ +cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" + +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = rm -rf "$@" && cp -af "$<" "$@" + +quiet_cmd_alink = LIBTOOL-STATIC $@ +cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^) + +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) + +# TODO(thakis): Find out and document the difference between shared_library and +# loadable_module on mac. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) + +# TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass +# -bundle -single_module here (for osmesa.so). +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) + + +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' + +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain ? instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds until one fails. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + E=$$?;\ + if [ $$E -ne 0 ]; then\ + break;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for +# spaces already and dirx strips the ? characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word 2,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "all" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: all +all: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +TOOLSET := target +# Suffix rules, putting all outputs into $(obj). +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + + +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,bufferutil.target.mk)))),) + include bufferutil.target.mk +endif +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,validation.target.mk)))),) + include validation.target.mk +endif + +quiet_cmd_regen_makefile = ACTION Regenerating $@ +cmd_regen_makefile = /usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -I/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/config.gypi -I/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/izhukov/.node-gyp/0.10.22/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/izhukov/.node-gyp/0.10.22" "-Dmodule_root_dir=/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws" binding.gyp +Makefile: $(srcdir)/../../../../../../../../../../.node-gyp/0.10.22/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../../../../../../../usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi + $(call do_cmd,regen_makefile) + +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/bufferutil.node.d b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/bufferutil.node.d new file mode 100644 index 00000000..8b191311 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/bufferutil.node.d @@ -0,0 +1 @@ +cmd_Release/bufferutil.node := ./gyp-mac-tool flock ./Release/linker.lock c++ -shared -Wl,-search_paths_first -mmacosx-version-min=10.5 -arch x86_64 -L./Release -install_name @rpath/bufferutil.node -o Release/bufferutil.node Release/obj.target/bufferutil/src/bufferutil.o -undefined dynamic_lookup diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d new file mode 100644 index 00000000..96b92036 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d @@ -0,0 +1,23 @@ +cmd_Release/obj.target/bufferutil/src/bufferutil.o := c++ '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/izhukov/.node-gyp/0.10.22/src -I/Users/izhukov/.node-gyp/0.10.22/deps/uv/include -I/Users/izhukov/.node-gyp/0.10.22/deps/v8/include -I/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan -Os -gdwarf-2 -mmacosx-version-min=10.5 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -fno-rtti -fno-exceptions -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d.raw -c -o Release/obj.target/bufferutil/src/bufferutil.o ../src/bufferutil.cc +Release/obj.target/bufferutil/src/bufferutil.o: ../src/bufferutil.cc \ + /Users/izhukov/.node-gyp/0.10.22/deps/v8/include/v8.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/v8/include/v8stdint.h \ + /Users/izhukov/.node-gyp/0.10.22/src/node.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/uv-unix.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/ngx-queue.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/uv-darwin.h \ + /Users/izhukov/.node-gyp/0.10.22/src/node_object_wrap.h \ + /Users/izhukov/.node-gyp/0.10.22/src/node_buffer.h \ + /Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/nan.h +../src/bufferutil.cc: +/Users/izhukov/.node-gyp/0.10.22/deps/v8/include/v8.h: +/Users/izhukov/.node-gyp/0.10.22/deps/v8/include/v8stdint.h: +/Users/izhukov/.node-gyp/0.10.22/src/node.h: +/Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv.h: +/Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/uv-unix.h: +/Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/ngx-queue.h: +/Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/uv-darwin.h: +/Users/izhukov/.node-gyp/0.10.22/src/node_object_wrap.h: +/Users/izhukov/.node-gyp/0.10.22/src/node_buffer.h: +/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/nan.h: diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/validation/src/validation.o.d b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/validation/src/validation.o.d new file mode 100644 index 00000000..e327f957 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/validation/src/validation.o.d @@ -0,0 +1,23 @@ +cmd_Release/obj.target/validation/src/validation.o := c++ '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/izhukov/.node-gyp/0.10.22/src -I/Users/izhukov/.node-gyp/0.10.22/deps/uv/include -I/Users/izhukov/.node-gyp/0.10.22/deps/v8/include -I/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan -Os -gdwarf-2 -mmacosx-version-min=10.5 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -fno-rtti -fno-exceptions -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/validation/src/validation.o.d.raw -c -o Release/obj.target/validation/src/validation.o ../src/validation.cc +Release/obj.target/validation/src/validation.o: ../src/validation.cc \ + /Users/izhukov/.node-gyp/0.10.22/deps/v8/include/v8.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/v8/include/v8stdint.h \ + /Users/izhukov/.node-gyp/0.10.22/src/node.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/uv-unix.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/ngx-queue.h \ + /Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/uv-darwin.h \ + /Users/izhukov/.node-gyp/0.10.22/src/node_object_wrap.h \ + /Users/izhukov/.node-gyp/0.10.22/src/node_buffer.h \ + /Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/nan.h +../src/validation.cc: +/Users/izhukov/.node-gyp/0.10.22/deps/v8/include/v8.h: +/Users/izhukov/.node-gyp/0.10.22/deps/v8/include/v8stdint.h: +/Users/izhukov/.node-gyp/0.10.22/src/node.h: +/Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv.h: +/Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/uv-unix.h: +/Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/ngx-queue.h: +/Users/izhukov/.node-gyp/0.10.22/deps/uv/include/uv-private/uv-darwin.h: +/Users/izhukov/.node-gyp/0.10.22/src/node_object_wrap.h: +/Users/izhukov/.node-gyp/0.10.22/src/node_buffer.h: +/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/nan.h: diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/validation.node.d b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/validation.node.d new file mode 100644 index 00000000..869c91e2 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/validation.node.d @@ -0,0 +1 @@ +cmd_Release/validation.node := ./gyp-mac-tool flock ./Release/linker.lock c++ -shared -Wl,-search_paths_first -mmacosx-version-min=10.5 -arch x86_64 -L./Release -install_name @rpath/validation.node -o Release/validation.node Release/obj.target/validation/src/validation.o -undefined dynamic_lookup diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/bufferutil.node b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/bufferutil.node new file mode 100755 index 0000000000000000000000000000000000000000..192474d8a8907281525dab374cb43344fa7ee303 GIT binary patch literal 18372 zcmeHPe{|HLc~O3D@rZ8VHb9B)g+S;oK(;Z$-s;xF_I8a!LO6aH_4dEOq}@+ zzZ4ofq=zBIVz-`U)w+7Np0!(bv)1iW*J6N3(9aE2z47#fya;6q(C4Iuo1#%_b(7L zqrq^yRGSdLIp35G53oIjS$w>0RO)&>ye=4S)q~--h`{6h+dWHa?qCB7Gn_zl-RRKU zqW&&JHreCXaG9(h;6W0mH8NSE@NC6cbiKyi+KQCvYTM95c-r{l4yjj$Sf6Wu6+Jx@JpRridxy zp-Uttzu09_LH7X?q07ixUlr~4n;j)B@wPT28aIQX;&7xDYlxN!$*yv0+C89ee@oMj z=4;yd;2V%B)pPzjs2{lqd9w6)rKa78#tzUt5`r^-1wxk%_4ALhza8?u;ri(5rH`%l zhu;5$=BN-^n=%aw(=>D~=9FaR5_W-`s+GiJ(UMTGg>uYn4P1F;@q%J3xnK*LktXP6 z{}{E7ae9p#Vy4kmy!fnoS}&H)c)j*OK#vtWt!mm|!aDiwLfnc#uV74Z%%n^NG7-o` zAQOR11TqoGL?9D^KV1aejkW!ky?H#Hb~mQy{swPo)Bj9M&wUll3UBgv?&d~s;#iS4 zdAhbgey}!qGSze*-n)};ralBEd;{UcP|>aK+t%#cA#_%{o83)9&zDR?Z;<3>kzC)R zUKn0@X6E`P&ta#?%UkD8p(vwH$(1u zdeu(lQ!m3+=u=SC6QvS<7wpGh_1?suLT@t9+ZW68Cidrflf$X!sT;-=6bIqtK4P;3 zdt@|}Dw2&2-sFGyl3#k0C*^3CLC}{R#%M$w-@+d>Wcp=L*r_E+j0|@2FeMnuND&l9 ztzkCjVK%+}n+~LsP)XcXsBO;m_EqP-KPB}!+sYSR>?gNQqiW0G^esm)F2cjqP2d#N z9Gj<+nl~|c3aWcp^^l-qS_fJ6ISL74zfm@kmB+a0QMRfB*Cs#n?s+c@uJ;}`zb+O- z-?h$#TazE9_j@Z3ML+iT=WO*Q-p%$U(hl=dl-cpTZOgJsy;<+)0%gUgZCmCj^*Xkl zUz(RXjXz4T^bVjmZ*qTXCm;vI(GaPHdt8`}#Z-;0HzD!>ONei(~Tz-lS)M zT16bsBb17>6#ZcZrzv(OSek}wag7iz2F4;F>sgzpvHo%NP|3PJAuvP&*`op}2+U-G zS)lIZeiFzT6*vlkli1Co1$7$KoqVA-`EKe2SnB;3V!GZ<4G58awSC3_HUEa2A4YRc z^0?Q51^sTS54APPkv$_>&cnSgnlt-vN;^-u`>rovIFMZUQ*U~I<;&6I-t=B?fBp_k z?ccZ)zsq(fzHpd-jxsx*@7}gDtL&z%tqqu7)MUjkM2(~DCdbwWhkM&4WfyKOOwB+a znB`qO%THs&fM@xqg5_CW?Or3VYE0$diy5t0AxObJAaW`f!<4#8+&q&my6$Kuby#yJ zHp`h@LNj?t*dI>)R(45qau6&<=>vp;@HWxp86ZVmEOmWtdA`KZsrU0zKR^p^NED^- zflYdz=p8hJ9_I%hCvHve)+9enH45e7)IEZVHP8)q%b*!0+g0E(d&J%>t2fpKP7u6^ z6#D80Zs=cFiIrcQ{5aKxsyfF>clw2zYrCF^{xJ0hHfk(ky9a1LJS|>JH-X#G z);qXacMjI|o-p&Ms$6uBn@V!n3F+5TRaDV;7jB|6I$u!BzCY899M14|M;E z=(plmvimPVo?SxMXBWx#FB0puzv3y`{1G)TrRI7xvv>5AV-Nc`9ZZE`*Vnfs&)fT- z<`i%5U_2jOd?|5@--kEnd#}xlyTp=+H;~XB6noOb4BbZKInURZiy@^O^00yqrv8E) zRgX!y)GvIg_@;DeJGr!$T>5u8ps;NITtv4ZLCx!^`61bSqip^!+1yRd>#2DYn#KKS z&B!faX>9cTIGw5`z2uwXsjz0`25$2vPkH;+V~}a{ymVFJnvv(}_R_zoLz>?#&0k68 zSCRS4tv1E9K(i`kKx@ljyt%Ks5c3&MA4pagnp0(8`*`-A6pyzzQY)zknoxQ^tr=M$ zJKQUJswj{hJ`3_}J9YS^Z2kw?{Gpi5f~TmtgPQM^&0A#iE3)}fY7SC!1kEBEA_m^R zDK2s%F^H#fw(`Cr^>c_~(#okOwHtsK@o3%0fZ{VH)k|o&8YajHc~1`xx9q!7_I*9| zO&eONPf+ko90WTy6MIR0bS4IY(sLijT_`>GpG5hDD4!DLfGD39x+n zC(7NTq$h5A?p{$2iE_Uv4~X(5QT|et^tOX=HzAegkM41xhd!jrh$`4V}J?64s;Z`uR^S{%054`L};$=ozlV5J^1mRy zL-Ic-ezoNPmG}n9{|oUol7EtTm*js;{8f^FjQAqSKT7;XlK&y`d6K6$fsxNY6~5h1 z{BgF8K|_KO}j2rjP89{GG&ak$e~N z>m?r~J|uaA_}eA#C%#GYYl!zs{$}DAN`3|LrINpi_&JiVBYvjjeZ=QW-b1`5c{lN& zev(cX7nj7M0qdT3AfS!yfNSw^mp|62$-;=X8`@&AJ-!0l<65l|ZZ|u$k`*x{8Y>BI z?1*hJzNj75a9z7ATj*x?Vih77&f7xQ#=n;T$L)}WiPX+*>R(2}4LYORjM!|1T+x}s8T zrQz?a_J=|({y-;r6gP?%Eh>W9tFL2g+H8TMMq5mm60l!y_@gz3-|RpiE5c~gW>4(g zQbpZBR2UKcE{DoyIdn1PF>R}9+{rZh@P*rqHV>H+QQVLzIUM*mTg!6L*TgDRP=1j9 zPC=?dCcS)o^Q@BJRB|tcD!x)ond#87b~?12#o1bRORknh_X1q;j#Hqed75K2UUl*J zl;hBpvDE=}az3wN$UeGT%aZdoFC`;>cgzDKSjkzM+})$y^k+XG%Cn_ZH72zij@ z=v$0PN^VI)SS7h3@!$~Q3h{ZM*C$nw7ukb92h z&Nhzikb9WrCL4!VIH;$;jZbDwOT}OAns&?Aqyuw!L4V2hGcT6)kIa_zAXD{yyoWwO zB5h~7lj)C`4lsR==>ev{W_pzAF{Y=O=HSw#RLFD|(|JtiGp%A;%XAgfR;Jxd?`FD{ z=?|Db!t@EIyO<6!J;?NRrYWYMG8G>v;b%U7-=E1;IFACmFXNK>?q7yG6s1a=ysXWX znFwSekcmJh0+|S8B9MtdCIXoVWFnA>Kqdm22>kCN;DtIiG;$l5(gzK~w=?Zv+Rb!5 z(;lWrU#fFWO{_@QKl)T$C;jDileo{&pf7uOtEt(>Wi4p zV_M48#k7j4muUmjRZMSZN_%%XhzFf*$G_Yj#yc;+D0lu#jvhz->sc>lznb;1mA=~dRQgs-`Wt7EcbaxR>nj`wKGS&AzNoTi#bi(I*FDMh6ef8Z z&td8eN$FcL>A%POeIK*F!b)GR_Az}cCjC!Ye`=15hr&u7)h4z@f6_dU>Qwq>21zHaZ zD}8IcsDCRa{mraTrzS{WVWn@47wIefBghxAZ$$phhF`Q{ve!xlr?=34Ik5U&)@jC9 z@%`iieEpv8=o!7AEMctf4_%Da^>aUCbv^86tghD-W3@iMV64{L*YGip`cvz7C1bT7 zVvN=GLLWUzUd{I~V->&OGFJ0J2ct+{&F>6+=^?D{PYJ@)dNj4~eLrKh|4m<}r(^Qe z?{(Q z$N}V5WCOVkxgEI!If#4*awl>KxeGar96|0zz7si$97Cq>g>mGy$aH*WJ@N+RjmY%f ziSA+aoLz~0EAndOO~{*(@u^7bLB0{W0r@6mdVyJiyaxF;Lq@Em(;w~fkFSbF0-c6g9E?m-eRUudgvIf#>tZ-G5Dc}J z@CgFTp@HH+;Q!pK$lW9OUF(< zI7@wy4f;dDjfSVbY^`g7R~$X?)i;*v3*={gkH>>wDUR1GuQ%3tmMnv@+ftnzGi5WJbO#LuDyfP8eJ{PM=KH zRw0hFOx9XcHff7;VM1>;!jG}@M7q2U(IA?dt;4Op71H>n-?=IDU1m ze#kC=POZ0LmFuBMq%+<(~C5?edx8Yju zUsoN9#0*bELw%#}3i3HNbt4k1-L6!vE=7C8XvnBxzPy*I2Sb??Pmzhoh=}#>3y)Lq1o;U#X0rSmtV9a`dZV== zit8q72920!y*%{kjz;|(=yd4>SIVL0xkI_j{*|L=&m^l)EH>SF4R^A^ZQ?&cX^G># z%4TFfnLf8i^7O35uSW5os#M}Vu~Gad93H%=jb4H-b@`mZ#RXCm3twFg^Tm(}pVi^Y z6^L6~Fl@B48_N*a3K6pf literal 0 HcmV?d00001 diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/linker.lock b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/linker.lock new file mode 100644 index 00000000..e69de29b diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/bufferutil/src/bufferutil.o b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/bufferutil/src/bufferutil.o new file mode 100644 index 0000000000000000000000000000000000000000..c6615bb27763b3ec2bb8927eddd373526698b922 GIT binary patch literal 81384 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 Kfx(J$a{eDm2h^JY literal 0 HcmV?d00001 diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/validation/src/validation.o b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/validation/src/validation.o new file mode 100644 index 0000000000000000000000000000000000000000..62b54ecee6ec088912d352bfa75e16356f115ee2 GIT binary patch literal 78072 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 literal 0 HcmV?d00001 diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/binding.Makefile b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/binding.Makefile new file mode 100644 index 00000000..a69b3d2c --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/binding.Makefile @@ -0,0 +1,6 @@ +# This file is generated by gyp; do not edit. + +export builddir_name ?= build/./. +.PHONY: all +all: + $(MAKE) bufferutil validation diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/bufferutil.target.mk b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/bufferutil.target.mk new file mode 100644 index 00000000..9d47e6e9 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/bufferutil.target.mk @@ -0,0 +1,158 @@ +# This file is generated by gyp; do not edit. + +TOOLSET := target +TARGET := bufferutil +DEFS_Debug := \ + '-D_DARWIN_USE_64_BIT_INODE=1' \ + '-D_LARGEFILE_SOURCE' \ + '-D_FILE_OFFSET_BITS=64' \ + '-DBUILDING_NODE_EXTENSION' \ + '-DDEBUG' \ + '-D_DEBUG' + +# Flags passed to all source files. +CFLAGS_Debug := \ + -O0 \ + -gdwarf-2 \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -Wall \ + -Wendif-labels \ + -W \ + -Wno-unused-parameter + +# Flags passed to only C files. +CFLAGS_C_Debug := \ + -fno-strict-aliasing + +# Flags passed to only C++ files. +CFLAGS_CC_Debug := \ + -fno-rtti \ + -fno-exceptions \ + -fno-threadsafe-statics \ + -fno-strict-aliasing + +# Flags passed to only ObjC files. +CFLAGS_OBJC_Debug := + +# Flags passed to only ObjC++ files. +CFLAGS_OBJCC_Debug := + +INCS_Debug := \ + -I/Users/izhukov/.node-gyp/0.10.22/src \ + -I/Users/izhukov/.node-gyp/0.10.22/deps/uv/include \ + -I/Users/izhukov/.node-gyp/0.10.22/deps/v8/include \ + -I/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan + +DEFS_Release := \ + '-D_DARWIN_USE_64_BIT_INODE=1' \ + '-D_LARGEFILE_SOURCE' \ + '-D_FILE_OFFSET_BITS=64' \ + '-DBUILDING_NODE_EXTENSION' + +# Flags passed to all source files. +CFLAGS_Release := \ + -Os \ + -gdwarf-2 \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -Wall \ + -Wendif-labels \ + -W \ + -Wno-unused-parameter + +# Flags passed to only C files. +CFLAGS_C_Release := \ + -fno-strict-aliasing + +# Flags passed to only C++ files. +CFLAGS_CC_Release := \ + -fno-rtti \ + -fno-exceptions \ + -fno-threadsafe-statics \ + -fno-strict-aliasing + +# Flags passed to only ObjC files. +CFLAGS_OBJC_Release := + +# Flags passed to only ObjC++ files. +CFLAGS_OBJCC_Release := + +INCS_Release := \ + -I/Users/izhukov/.node-gyp/0.10.22/src \ + -I/Users/izhukov/.node-gyp/0.10.22/deps/uv/include \ + -I/Users/izhukov/.node-gyp/0.10.22/deps/v8/include \ + -I/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan + +OBJS := \ + $(obj).target/$(TARGET)/src/bufferutil.o + +# Add to the list of files we specially track dependencies for. +all_deps += $(OBJS) + +# CFLAGS et al overrides must be target-local. +# See "Target-specific Variable Values" in the GNU Make manual. +$(OBJS): TOOLSET := $(TOOLSET) +$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) +$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) +$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE)) +$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE)) + +# Suffix rules, putting all outputs into $(obj). + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# Try building from generated source, too. + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# End of this set of suffix rules +### Rules for final target. +LDFLAGS_Debug := \ + -Wl,-search_paths_first \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -L$(builddir) \ + -install_name @rpath/bufferutil.node + +LIBTOOLFLAGS_Debug := \ + -Wl,-search_paths_first + +LDFLAGS_Release := \ + -Wl,-search_paths_first \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -L$(builddir) \ + -install_name @rpath/bufferutil.node + +LIBTOOLFLAGS_Release := \ + -Wl,-search_paths_first + +LIBS := \ + -undefined dynamic_lookup + +$(builddir)/bufferutil.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) +$(builddir)/bufferutil.node: LIBS := $(LIBS) +$(builddir)/bufferutil.node: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE)) +$(builddir)/bufferutil.node: TOOLSET := $(TOOLSET) +$(builddir)/bufferutil.node: $(OBJS) FORCE_DO_CMD + $(call do_cmd,solink_module) + +all_deps += $(builddir)/bufferutil.node +# Add target alias +.PHONY: bufferutil +bufferutil: $(builddir)/bufferutil.node + +# Short alias for building this executable. +.PHONY: bufferutil.node +bufferutil.node: $(builddir)/bufferutil.node + +# Add executable to "all" target. +.PHONY: all +all: $(builddir)/bufferutil.node + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/config.gypi b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/config.gypi new file mode 100644 index 00000000..ebe1f41a --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/config.gypi @@ -0,0 +1,112 @@ +# Do not edit. File was generated by node-gyp's "configure" step +{ + "target_defaults": { + "cflags": [], + "default_configuration": "Release", + "defines": [], + "include_dirs": [], + "libraries": [] + }, + "variables": { + "clang": 1, + "host_arch": "x64", + "node_install_npm": "true", + "node_prefix": "", + "node_shared_cares": "false", + "node_shared_http_parser": "false", + "node_shared_libuv": "false", + "node_shared_openssl": "false", + "node_shared_v8": "false", + "node_shared_zlib": "false", + "node_tag": "", + "node_unsafe_optimizations": 0, + "node_use_dtrace": "true", + "node_use_etw": "false", + "node_use_openssl": "true", + "node_use_perfctr": "false", + "python": "/usr/bin/python", + "target_arch": "x64", + "v8_enable_gdbjit": 0, + "v8_no_strict_aliasing": 1, + "v8_use_snapshot": "false", + "nodedir": "/Users/izhukov/.node-gyp/0.10.22", + "copy_dev_lib": "true", + "standalone_static_library": 1, + "save_dev": "true", + "browser": "", + "viewer": "man", + "rollback": "true", + "usage": "", + "globalignorefile": "/usr/local/etc/npmignore", + "init_author_url": "", + "shell": "/bin/bash", + "parseable": "", + "shrinkwrap": "true", + "userignorefile": "/Users/izhukov/.npmignore", + "cache_max": "null", + "init_author_email": "", + "sign_git_tag": "", + "ignore": "", + "long": "", + "registry": "https://registry.npmjs.org/", + "fetch_retries": "2", + "npat": "", + "message": "%s", + "versions": "", + "globalconfig": "/usr/local/etc/npmrc", + "always_auth": "", + "cache_lock_retries": "10", + "fetch_retry_mintimeout": "10000", + "proprietary_attribs": "true", + "coverage": "", + "json": "", + "pre": "", + "description": "true", + "engine_strict": "", + "https_proxy": "", + "init_module": "/Users/izhukov/.npm-init.js", + "userconfig": "/Users/izhukov/.npmrc", + "npaturl": "http://npat.npmjs.org/", + "node_version": "v0.10.22", + "user": "", + "editor": "vi", + "save": "", + "tag": "latest", + "global": "", + "optional": "true", + "username": "", + "bin_links": "true", + "force": "", + "searchopts": "", + "depth": "null", + "rebuild_bundle": "true", + "searchsort": "name", + "unicode": "true", + "yes": "", + "fetch_retry_maxtimeout": "60000", + "strict_ssl": "true", + "dev": "", + "fetch_retry_factor": "10", + "group": "20", + "cache_lock_stale": "60000", + "version": "", + "cache_min": "10", + "cache": "/Users/izhukov/.npm", + "searchexclude": "", + "color": "true", + "save_optional": "", + "user_agent": "node/v0.10.22 darwin x64", + "cache_lock_wait": "10000", + "production": "", + "save_bundle": "", + "init_version": "0.0.0", + "umask": "18", + "git": "git", + "init_author_name": "", + "onload_script": "", + "tmp": "/var/folders/2l/8552b3mn10jdp069ksjlh5000000gn/T/", + "unsafe_perm": "true", + "link": "", + "prefix": "/usr/local" + } +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/gyp-mac-tool b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/gyp-mac-tool new file mode 100755 index 00000000..2f5e141f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/gyp-mac-tool @@ -0,0 +1,224 @@ +#!/usr/bin/env python +# Generated by gyp. Do not edit. +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Utility functions to perform Xcode-style build steps. + +These functions are executed via gyp-mac-tool when using the Makefile generator. +""" + +import fcntl +import os +import plistlib +import re +import shutil +import string +import subprocess +import sys + + +def main(args): + executor = MacTool() + exit_code = executor.Dispatch(args) + if exit_code is not None: + sys.exit(exit_code) + + +class MacTool(object): + """This class performs all the Mac tooling steps. The methods can either be + executed directly, or dispatched from an argument list.""" + + def Dispatch(self, args): + """Dispatches a string command to a method.""" + if len(args) < 1: + raise Exception("Not enough arguments") + + method = "Exec%s" % self._CommandifyName(args[0]) + return getattr(self, method)(*args[1:]) + + def _CommandifyName(self, name_string): + """Transforms a tool name like copy-info-plist to CopyInfoPlist""" + return name_string.title().replace('-', '') + + def ExecCopyBundleResource(self, source, dest): + """Copies a resource file to the bundle/Resources directory, performing any + necessary compilation on each resource.""" + extension = os.path.splitext(source)[1].lower() + if os.path.isdir(source): + # Copy tree. + if os.path.exists(dest): + shutil.rmtree(dest) + shutil.copytree(source, dest) + elif extension == '.xib': + return self._CopyXIBFile(source, dest) + elif extension == '.strings': + self._CopyStringsFile(source, dest) + else: + shutil.copyfile(source, dest) + + def _CopyXIBFile(self, source, dest): + """Compiles a XIB file with ibtool into a binary plist in the bundle.""" + tools_dir = os.environ.get('DEVELOPER_BIN_DIR', '/usr/bin') + args = [os.path.join(tools_dir, 'ibtool'), '--errors', '--warnings', + '--notices', '--output-format', 'human-readable-text', '--compile', + dest, source] + ibtool_section_re = re.compile(r'/\*.*\*/') + ibtool_re = re.compile(r'.*note:.*is clipping its content') + ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE) + current_section_header = None + for line in ibtoolout.stdout: + if ibtool_section_re.match(line): + current_section_header = line + elif not ibtool_re.match(line): + if current_section_header: + sys.stdout.write(current_section_header) + current_section_header = None + sys.stdout.write(line) + return ibtoolout.returncode + + def _CopyStringsFile(self, source, dest): + """Copies a .strings file using iconv to reconvert the input into UTF-16.""" + input_code = self._DetectInputEncoding(source) or "UTF-8" + + # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call + # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints + # CFPropertyListCreateFromXMLData(): Old-style plist parser: missing + # semicolon in dictionary. + # on invalid files. Do the same kind of validation. + import CoreFoundation + s = open(source).read() + d = CoreFoundation.CFDataCreate(None, s, len(s)) + _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None) + if error: + return + + fp = open(dest, 'w') + args = ['/usr/bin/iconv', '--from-code', input_code, '--to-code', + 'UTF-16', source] + subprocess.call(args, stdout=fp) + fp.close() + + def _DetectInputEncoding(self, file_name): + """Reads the first few bytes from file_name and tries to guess the text + encoding. Returns None as a guess if it can't detect it.""" + fp = open(file_name, 'rb') + try: + header = fp.read(3) + except e: + fp.close() + return None + fp.close() + if header.startswith("\xFE\xFF"): + return "UTF-16BE" + elif header.startswith("\xFF\xFE"): + return "UTF-16LE" + elif header.startswith("\xEF\xBB\xBF"): + return "UTF-8" + else: + return None + + def ExecCopyInfoPlist(self, source, dest): + """Copies the |source| Info.plist to the destination directory |dest|.""" + # Read the source Info.plist into memory. + fd = open(source, 'r') + lines = fd.read() + fd.close() + + # Go through all the environment variables and replace them as variables in + # the file. + for key in os.environ: + if key.startswith('_'): + continue + evar = '${%s}' % key + lines = string.replace(lines, evar, os.environ[key]) + + # Write out the file with variables replaced. + fd = open(dest, 'w') + fd.write(lines) + fd.close() + + # Now write out PkgInfo file now that the Info.plist file has been + # "compiled". + self._WritePkgInfo(dest) + + def _WritePkgInfo(self, info_plist): + """This writes the PkgInfo file from the data stored in Info.plist.""" + plist = plistlib.readPlist(info_plist) + if not plist: + return + + # Only create PkgInfo for executable types. + package_type = plist['CFBundlePackageType'] + if package_type != 'APPL': + return + + # The format of PkgInfo is eight characters, representing the bundle type + # and bundle signature, each four characters. If that is missing, four + # '?' characters are used instead. + signature_code = plist.get('CFBundleSignature', '????') + if len(signature_code) != 4: # Wrong length resets everything, too. + signature_code = '?' * 4 + + dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') + fp = open(dest, 'w') + fp.write('%s%s' % (package_type, signature_code)) + fp.close() + + def ExecFlock(self, lockfile, *cmd_list): + """Emulates the most basic behavior of Linux's flock(1).""" + # Rely on exception handling to report errors. + fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666) + fcntl.flock(fd, fcntl.LOCK_EX) + return subprocess.call(cmd_list) + + def ExecFilterLibtool(self, *cmd_list): + """Calls libtool and filters out 'libtool: file: foo.o has no symbols'.""" + libtool_re = re.compile(r'^libtool: file: .* has no symbols$') + libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE) + _, err = libtoolout.communicate() + for line in err.splitlines(): + if not libtool_re.match(line): + print >>sys.stderr, line + return libtoolout.returncode + + def ExecPackageFramework(self, framework, version): + """Takes a path to Something.framework and the Current version of that and + sets up all the symlinks.""" + # Find the name of the binary based on the part before the ".framework". + binary = os.path.basename(framework).split('.')[0] + + CURRENT = 'Current' + RESOURCES = 'Resources' + VERSIONS = 'Versions' + + if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)): + # Binary-less frameworks don't seem to contain symlinks (see e.g. + # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle). + return + + # Move into the framework directory to set the symlinks correctly. + pwd = os.getcwd() + os.chdir(framework) + + # Set up the Current version. + self._Relink(version, os.path.join(VERSIONS, CURRENT)) + + # Set up the root symlinks. + self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary) + self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES) + + # Back to where we were before! + os.chdir(pwd) + + def _Relink(self, dest, link): + """Creates a symlink to |dest| named |link|. If |link| already exists, + it is overwritten.""" + if os.path.lexists(link): + os.remove(link) + os.symlink(dest, link) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/validation.target.mk b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/validation.target.mk new file mode 100644 index 00000000..13ecfeba --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/validation.target.mk @@ -0,0 +1,158 @@ +# This file is generated by gyp; do not edit. + +TOOLSET := target +TARGET := validation +DEFS_Debug := \ + '-D_DARWIN_USE_64_BIT_INODE=1' \ + '-D_LARGEFILE_SOURCE' \ + '-D_FILE_OFFSET_BITS=64' \ + '-DBUILDING_NODE_EXTENSION' \ + '-DDEBUG' \ + '-D_DEBUG' + +# Flags passed to all source files. +CFLAGS_Debug := \ + -O0 \ + -gdwarf-2 \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -Wall \ + -Wendif-labels \ + -W \ + -Wno-unused-parameter + +# Flags passed to only C files. +CFLAGS_C_Debug := \ + -fno-strict-aliasing + +# Flags passed to only C++ files. +CFLAGS_CC_Debug := \ + -fno-rtti \ + -fno-exceptions \ + -fno-threadsafe-statics \ + -fno-strict-aliasing + +# Flags passed to only ObjC files. +CFLAGS_OBJC_Debug := + +# Flags passed to only ObjC++ files. +CFLAGS_OBJCC_Debug := + +INCS_Debug := \ + -I/Users/izhukov/.node-gyp/0.10.22/src \ + -I/Users/izhukov/.node-gyp/0.10.22/deps/uv/include \ + -I/Users/izhukov/.node-gyp/0.10.22/deps/v8/include \ + -I/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan + +DEFS_Release := \ + '-D_DARWIN_USE_64_BIT_INODE=1' \ + '-D_LARGEFILE_SOURCE' \ + '-D_FILE_OFFSET_BITS=64' \ + '-DBUILDING_NODE_EXTENSION' + +# Flags passed to all source files. +CFLAGS_Release := \ + -Os \ + -gdwarf-2 \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -Wall \ + -Wendif-labels \ + -W \ + -Wno-unused-parameter + +# Flags passed to only C files. +CFLAGS_C_Release := \ + -fno-strict-aliasing + +# Flags passed to only C++ files. +CFLAGS_CC_Release := \ + -fno-rtti \ + -fno-exceptions \ + -fno-threadsafe-statics \ + -fno-strict-aliasing + +# Flags passed to only ObjC files. +CFLAGS_OBJC_Release := + +# Flags passed to only ObjC++ files. +CFLAGS_OBJCC_Release := + +INCS_Release := \ + -I/Users/izhukov/.node-gyp/0.10.22/src \ + -I/Users/izhukov/.node-gyp/0.10.22/deps/uv/include \ + -I/Users/izhukov/.node-gyp/0.10.22/deps/v8/include \ + -I/Users/izhukov/Documents/webogram/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan + +OBJS := \ + $(obj).target/$(TARGET)/src/validation.o + +# Add to the list of files we specially track dependencies for. +all_deps += $(OBJS) + +# CFLAGS et al overrides must be target-local. +# See "Target-specific Variable Values" in the GNU Make manual. +$(OBJS): TOOLSET := $(TOOLSET) +$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) +$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) +$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE)) +$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE)) + +# Suffix rules, putting all outputs into $(obj). + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# Try building from generated source, too. + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# End of this set of suffix rules +### Rules for final target. +LDFLAGS_Debug := \ + -Wl,-search_paths_first \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -L$(builddir) \ + -install_name @rpath/validation.node + +LIBTOOLFLAGS_Debug := \ + -Wl,-search_paths_first + +LDFLAGS_Release := \ + -Wl,-search_paths_first \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -L$(builddir) \ + -install_name @rpath/validation.node + +LIBTOOLFLAGS_Release := \ + -Wl,-search_paths_first + +LIBS := \ + -undefined dynamic_lookup + +$(builddir)/validation.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) +$(builddir)/validation.node: LIBS := $(LIBS) +$(builddir)/validation.node: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE)) +$(builddir)/validation.node: TOOLSET := $(TOOLSET) +$(builddir)/validation.node: $(OBJS) FORCE_DO_CMD + $(call do_cmd,solink_module) + +all_deps += $(builddir)/validation.node +# Add target alias +.PHONY: validation +validation: $(builddir)/validation.node + +# Short alias for building this executable. +.PHONY: validation.node +validation.node: $(builddir)/validation.node + +# Add executable to "all" target. +.PHONY: all +all: $(builddir)/validation.node + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/builderror.log b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/builderror.log new file mode 100644 index 00000000..d493584f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/builderror.log @@ -0,0 +1,2 @@ +gyp http GET http://nodejs.org/dist/v0.10.22/node-v0.10.22.tar.gz +gyp http 200 http://nodejs.org/dist/v0.10.22/node-v0.10.22.tar.gz diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/doc/ws.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/doc/ws.md new file mode 100644 index 00000000..d84fd625 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/doc/ws.md @@ -0,0 +1,181 @@ +# ws + +## Class: ws.Server + +This class is a WebSocket server. It is an `EventEmitter`. + +### new ws.Server([options], [callback]) + +* `options` Object + * `host` String + * `port` Number + * `server` http.Server + * `verifyClient` Function + * `path` String + * `noServer` Boolean + * `disableHixie` Boolean + * `clientTracking` Boolean +* `callback` Function + +Construct a new server object. + +Either `port` or `server` must be provided, otherwise you might enable +`noServer` if you want to pass the requests directly. Please note that the +`callback` is only used when you supply the a `port` number in the options. + +### server.close([code], [data]) + +Close the server and terminate all clients + +### server.handleUpgrade(request, socket, upgradeHead, callback) + +Handles a HTTP Upgrade request. `request` is an instance of `http.ServerRequest`, `socket` is an instance of `net.Socket`. + +When the Upgrade was successfully, the `callback` will be called with a `ws.WebSocket` object as parameter. + +### Event: 'error' + +`function (error) { }` + +If the underlying server emits an error, it will be forwarded here. + +### Event: 'headers' + +`function (headers) { }` + +Emitted with the object of HTTP headers that are going to be written to the `Stream` as part of the handshake. + +### Event: 'connection' + +`function (socket) { }` + +When a new WebSocket connection is established. `socket` is an object of type `ws.WebSocket`. + + +## Class: ws.WebSocket + +This class represents a WebSocket connection. It is an `EventEmitter`. + +### new ws.WebSocket(address, [options]) + +* `address` String|Array +* `options` Object + * `protocol` String + * `agent` Agent + * `headers` Object + * `protocolVersion` Number|String + -- the following only apply if `address` is a String + * `host` String + * `origin` String + * `pfx` String|Buffer + * `key` String|Buffer + * `passphrase` String + * `cert` String|Buffer + * `ca` Array + * `ciphers` String + * `rejectUnauthorized` Boolean + +Instantiating with an `address` creates a new WebSocket client object. If `address` is an Array (request, socket, rest), it is instantiated as a Server client (e.g. called from the `ws.Server`). + +### websocket.bytesReceived + +Received bytes count. + +### websocket.readyState + +Possible states are `WebSocket.CONNECTING`, `WebSocket.OPEN`, `WebSocket.CLOSING`, `WebSocket.CLOSED`. + +### websocket.protocolVersion + +The WebSocket protocol version used for this connection, `8`, `13` or `hixie-76` (the latter only for server clients). + +### websocket.url + +The URL of the WebSocket server (only for clients) + +### websocket.supports + +Describes the feature of the used protocol version. E.g. `supports.binary` is a boolean that describes if the connection supports binary messages. + +### websocket.close([code], [data]) + +Gracefully closes the connection, after sending a description message + +### websocket.pause() + +Pause the client stream + +### websocket.ping([data], [options], [dontFailWhenClosed]) + +Sends a ping. `data` is sent, `options` is an object with members `mask` and `binary`. `dontFailWhenClosed` indicates whether or not to throw if the connection isnt open. + +### websocket.pong([data], [options], [dontFailWhenClosed]) + +Sends a pong. `data` is sent, `options` is an object with members `mask` and `binary`. `dontFailWhenClosed` indicates whether or not to throw if the connection isnt open. + + +### websocket.resume() + +Resume the client stream + +### websocket.send(data, [options], [callback]) + +Sends `data` through the connection. `options` can be an object with members `mask` and `binary`. The optional `callback` is executed after the send completes. + +### websocket.stream([options], callback) + +Streams data through calls to a user supplied function. `options` can be an object with members `mask` and `binary`. `callback` is executed on successive ticks of which send is `function (data, final)`. + +### websocket.terminate() + +Immediately shuts down the connection + +### websocket.onopen +### websocket.onerror +### websocket.onclose +### websocket.onmessage + +Emulates the W3C Browser based WebSocket interface using function members. + +### websocket.addEventListener(method, listener) + +Emulates the W3C Browser based WebSocket interface using addEventListener. + +### Event: 'error' + +`function (error) { }` + +If the client emits an error, this event is emitted (errors from the underlying `net.Socket` are forwarded here). + +### Event: 'close' + +`function (code, message) { }` + +Is emitted when the connection is closed. `code` is defined in the WebSocket specification. + +The `close` event is also emitted when then underlying `net.Socket` closes the connection (`end` or `close`). + +### Event: 'message' + +`function (data, flags) { }` + +Is emitted when data is received. `flags` is an object with member `binary`. + +### Event: 'ping' + +`function (data, flags) { }` + +Is emitted when a ping is received. `flags` is an object with member `binary`. + +### Event: 'pong' + +`function (data, flags) { }` + +Is emitted when a pong is received. `flags` is an object with member `binary`. + +### Event: 'open' + +`function () { }` + +Emitted when the connection is established. + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/.npmignore b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/.npmignore new file mode 100644 index 00000000..dcd57568 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/.npmignore @@ -0,0 +1 @@ +uploaded diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/package.json new file mode 100644 index 00000000..7816f273 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/package.json @@ -0,0 +1,18 @@ +{ + "author": "", + "name": "fileapi", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "git://github.com/einaros/ws.git" + }, + "engines": { + "node": "~0.6.8" + }, + "dependencies": { + "express": "latest", + "ansi": "https://github.com/einaros/ansi.js/tarball/master" + }, + "devDependencies": {}, + "optionalDependencies": {} +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/app.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/app.js new file mode 100644 index 00000000..e812cc3e --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/app.js @@ -0,0 +1,39 @@ +function onFilesSelected(e) { + var button = e.srcElement; + button.disabled = true; + var progress = document.querySelector('div#progress'); + progress.innerHTML = '0%'; + var files = e.target.files; + var totalFiles = files.length; + var filesSent = 0; + if (totalFiles) { + var uploader = new Uploader('ws://localhost:8080', function () { + Array.prototype.slice.call(files, 0).forEach(function(file) { + if (file.name == '.') { + --totalFiles; + return; + } + uploader.sendFile(file, function(error) { + if (error) { + console.log(error); + return; + } + ++filesSent; + progress.innerHTML = ~~(filesSent / totalFiles * 100) + '%'; + console.log('Sent: ' + file.name); + }); + }); + }); + } + uploader.ondone = function() { + uploader.close(); + progress.innerHTML = '100% done, ' + totalFiles + ' files sent.'; + } +} + +window.onload = function() { + var importButtons = document.querySelectorAll('[type="file"]'); + Array.prototype.slice.call(importButtons, 0).forEach(function(importButton) { + importButton.addEventListener('change', onFilesSelected, false); + }); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/index.html b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/index.html new file mode 100644 index 00000000..0d463dd5 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/index.html @@ -0,0 +1,22 @@ + + + + + + + + +

    This example will upload an entire directory tree to the node.js server via a fast and persistent WebSocket connection.

    +

    Note that the example is Chrome only for now.

    +

    + Upload status: +
    Please select a directory to upload.
    + + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/uploader.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/uploader.js new file mode 100644 index 00000000..0c34a7fa --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/uploader.js @@ -0,0 +1,55 @@ +function Uploader(url, cb) { + this.ws = new WebSocket(url); + if (cb) this.ws.onopen = cb; + this.sendQueue = []; + this.sending = null; + this.sendCallback = null; + this.ondone = null; + var self = this; + this.ws.onmessage = function(event) { + var data = JSON.parse(event.data); + if (data.event == 'complete') { + if (data.path != self.sending.path) { + self.sendQueue = []; + self.sending = null; + self.sendCallback = null; + throw new Error('Got message for wrong file!'); + } + self.sending = null; + var callback = self.sendCallback; + self.sendCallback = null; + if (callback) callback(); + if (self.sendQueue.length === 0 && self.ondone) self.ondone(null); + if (self.sendQueue.length > 0) { + var args = self.sendQueue.pop(); + setTimeout(function() { self.sendFile.apply(self, args); }, 0); + } + } + else if (data.event == 'error') { + self.sendQueue = []; + self.sending = null; + var callback = self.sendCallback; + self.sendCallback = null; + var error = new Error('Server reported send error for file ' + data.path); + if (callback) callback(error); + if (self.ondone) self.ondone(error); + } + } +} + +Uploader.prototype.sendFile = function(file, cb) { + if (this.ws.readyState != WebSocket.OPEN) throw new Error('Not connected'); + if (this.sending) { + this.sendQueue.push(arguments); + return; + } + var fileData = { name: file.name, path: file.webkitRelativePath }; + this.sending = fileData; + this.sendCallback = cb; + this.ws.send(JSON.stringify(fileData)); + this.ws.send(file); +} + +Uploader.prototype.close = function() { + this.ws.close(); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/server.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/server.js new file mode 100644 index 00000000..badfeba7 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/server.js @@ -0,0 +1,103 @@ +var WebSocketServer = require('../../').Server + , express = require('express') + , fs = require('fs') + , http = require('http') + , util = require('util') + , path = require('path') + , app = express.createServer() + , events = require('events') + , ansi = require('ansi') + , cursor = ansi(process.stdout); + +function BandwidthSampler(ws, interval) { + interval = interval || 2000; + var previousByteCount = 0; + var self = this; + var intervalId = setInterval(function() { + var byteCount = ws.bytesReceived; + var bytesPerSec = (byteCount - previousByteCount) / (interval / 1000); + previousByteCount = byteCount; + self.emit('sample', bytesPerSec); + }, interval); + ws.on('close', function() { + clearInterval(intervalId); + }); +} +util.inherits(BandwidthSampler, events.EventEmitter); + +function makePathForFile(filePath, prefix, cb) { + if (typeof cb !== 'function') throw new Error('callback is required'); + filePath = path.dirname(path.normalize(filePath)).replace(/^(\/|\\)+/, ''); + var pieces = filePath.split(/(\\|\/)/); + var incrementalPath = prefix; + function step(error) { + if (error) return cb(error); + if (pieces.length == 0) return cb(null, incrementalPath); + incrementalPath += '/' + pieces.shift(); + fs.exists(incrementalPath, function(exists) { + if (!exists) fs.mkdir(incrementalPath, step); + else process.nextTick(step); + }); + } + step(); +} + +cursor.eraseData(2).goto(1, 1); +app.use(express.static(__dirname + '/public')); + +var clientId = 0; +var wss = new WebSocketServer({server: app}); +wss.on('connection', function(ws) { + var thisId = ++clientId; + cursor.goto(1, 4 + thisId).eraseLine(); + console.log('Client #%d connected', thisId); + + var sampler = new BandwidthSampler(ws); + sampler.on('sample', function(bps) { + cursor.goto(1, 4 + thisId).eraseLine(); + console.log('WebSocket #%d incoming bandwidth: %d MB/s', thisId, Math.round(bps / (1024*1024))); + }); + + var filesReceived = 0; + var currentFile = null; + ws.on('message', function(data, flags) { + if (!flags.binary) { + currentFile = JSON.parse(data); + // note: a real-world app would want to sanity check the data + } + else { + if (currentFile == null) return; + makePathForFile(currentFile.path, __dirname + '/uploaded', function(error, path) { + if (error) { + console.log(error); + ws.send(JSON.stringify({event: 'error', path: currentFile.path, message: error.message})); + return; + } + fs.writeFile(path + '/' + currentFile.name, data, function(error) { + ++filesReceived; + // console.log('received %d bytes long file, %s', data.length, currentFile.path); + ws.send(JSON.stringify({event: 'complete', path: currentFile.path})); + currentFile = null; + }); + }); + } + }); + + ws.on('close', function() { + cursor.goto(1, 4 + thisId).eraseLine(); + console.log('Client #%d disconnected. %d files received.', thisId, filesReceived); + }); + + ws.on('error', function(e) { + cursor.goto(1, 4 + thisId).eraseLine(); + console.log('Client #%d error: %s', thisId, e.message); + }); +}); + +fs.mkdir(__dirname + '/uploaded', function(error) { + // ignore errors, most likely means directory exists + console.log('Uploaded files will be saved to %s/uploaded.', __dirname); + console.log('Remember to wipe this directory if you upload lots and lots.'); + app.listen(8080); + console.log('Listening on http://localhost:8080'); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/package.json new file mode 100644 index 00000000..99722c42 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/package.json @@ -0,0 +1,17 @@ +{ + "author": "", + "name": "serverstats", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "git://github.com/einaros/ws.git" + }, + "engines": { + "node": ">0.4.0" + }, + "dependencies": { + "express": "~3.0.0" + }, + "devDependencies": {}, + "optionalDependencies": {} +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/public/index.html b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/public/index.html new file mode 100644 index 00000000..24d84e12 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/public/index.html @@ -0,0 +1,33 @@ + + + + + + + + Server Stats
    + RSS:

    + Heap total:

    + Heap used:

    + + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/server.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/server.js new file mode 100644 index 00000000..88bbc9eb --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/server.js @@ -0,0 +1,21 @@ +var WebSocketServer = require('../../').Server + , http = require('http') + , express = require('express') + , app = express(); + +app.use(express.static(__dirname + '/public')); + +var server = http.createServer(app); +server.listen(8080); + +var wss = new WebSocketServer({server: server}); +wss.on('connection', function(ws) { + var id = setInterval(function() { + ws.send(JSON.stringify(process.memoryUsage()), function() { /* ignore errors */ }); + }, 100); + console.log('started client interval'); + ws.on('close', function() { + console.log('stopping client interval'); + clearInterval(id); + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/package.json new file mode 100644 index 00000000..65c900ab --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/package.json @@ -0,0 +1,17 @@ +{ + "author": "", + "name": "serverstats", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "git://github.com/einaros/ws.git" + }, + "engines": { + "node": ">0.4.0" + }, + "dependencies": { + "express": "2.x" + }, + "devDependencies": {}, + "optionalDependencies": {} +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/public/index.html b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/public/index.html new file mode 100644 index 00000000..24d84e12 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/public/index.html @@ -0,0 +1,33 @@ + + + + + + + + Server Stats
    + RSS:

    + Heap total:

    + Heap used:

    + + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/server.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/server.js new file mode 100644 index 00000000..0bbce368 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/server.js @@ -0,0 +1,19 @@ +var WebSocketServer = require('../../').Server + , http = require('http') + , express = require('express') + , app = express.createServer(); + +app.use(express.static(__dirname + '/public')); +app.listen(8080); + +var wss = new WebSocketServer({server: app}); +wss.on('connection', function(ws) { + var id = setInterval(function() { + ws.send(JSON.stringify(process.memoryUsage()), function() { /* ignore errors */ }); + }, 100); + console.log('started client interval'); + ws.on('close', function() { + console.log('stopping client interval'); + clearInterval(id); + }) +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/ssl.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/ssl.js new file mode 100644 index 00000000..bf1bf530 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/ssl.js @@ -0,0 +1,59 @@ + +(function(){ + + "use strict"; + + var fs = require('fs'); + + // you'll probably load configuration from config + var cfg = { + ssl: true, + port: 8080, + ssl_key: '/path/to/you/ssl.key', + ssl_cert: '/path/to/you/ssl.crt' + }; + + var httpServ = ( cfg.ssl ) ? require('https') : require('http'); + + var WebSocketServer = require('../').Server; + + var app = null; + + // dummy request processing + var processRequest = function( req, res ) { + + res.writeHead(200); + res.end("All glory to WebSockets!\n"); + }; + + if ( cfg.ssl ) { + + app = httpServ.createServer({ + + // providing server with SSL key/cert + key: fs.readFileSync( cfg.ssl_key ), + cert: fs.readFileSync( cfg.ssl_cert ) + + }, processRequest ).listen( cfg.port ); + + } else { + + app = httpServ.createServer( processRequest ).listen( cfg.port ); + } + + // passing or reference to web server so WS would knew port and SSL capabilities + var wss = new WebSocketServer( { server: app } ); + + + wss.on( 'connection', function ( wsConnect ) { + + wsConnect.on( 'message', function ( message ) { + + console.log( message ); + + }); + + }); + + +}()); \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/index.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/index.js new file mode 100644 index 00000000..3423ff23 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/index.js @@ -0,0 +1,26 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +module.exports = require('./lib/WebSocket'); +module.exports.Server = require('./lib/WebSocketServer'); +module.exports.Sender = require('./lib/Sender'); +module.exports.Receiver = require('./lib/Receiver'); + +module.exports.createServer = function (options, connectionListener) { + var server = new module.exports.Server(options); + if (typeof connectionListener === 'function') { + server.on('connection', connectionListener); + } + return server; +}; + +module.exports.connect = module.exports.createConnection = function (address, openListener) { + var client = new module.exports(address); + if (typeof openListener === 'function') { + client.on('open', openListener); + } + return client; +}; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferPool.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferPool.js new file mode 100644 index 00000000..faf8637c --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferPool.js @@ -0,0 +1,59 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util'); + +function BufferPool(initialSize, growStrategy, shrinkStrategy) { + if (typeof initialSize === 'function') { + shrinkStrategy = growStrategy; + growStrategy = initialSize; + initialSize = 0; + } + else if (typeof initialSize === 'undefined') { + initialSize = 0; + } + this._growStrategy = (growStrategy || function(db, size) { + return db.used + size; + }).bind(null, this); + this._shrinkStrategy = (shrinkStrategy || function(db) { + return initialSize; + }).bind(null, this); + this._buffer = initialSize ? new Buffer(initialSize) : null; + this._offset = 0; + this._used = 0; + this._changeFactor = 0; + this.__defineGetter__('size', function(){ + return this._buffer == null ? 0 : this._buffer.length; + }); + this.__defineGetter__('used', function(){ + return this._used; + }); +} + +BufferPool.prototype.get = function(length) { + if (this._buffer == null || this._offset + length > this._buffer.length) { + var newBuf = new Buffer(this._growStrategy(length)); + this._buffer = newBuf; + this._offset = 0; + } + this._used += length; + var buf = this._buffer.slice(this._offset, this._offset + length); + this._offset += length; + return buf; +} + +BufferPool.prototype.reset = function(forceNewBuffer) { + var len = this._shrinkStrategy(); + if (len < this.size) this._changeFactor -= 1; + if (forceNewBuffer || this._changeFactor < -2) { + this._changeFactor = 0; + this._buffer = len ? new Buffer(len) : null; + } + this._offset = 0; + this._used = 0; +} + +module.exports = BufferPool; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.fallback.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.fallback.js new file mode 100644 index 00000000..508542c9 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.fallback.js @@ -0,0 +1,47 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +module.exports.BufferUtil = { + merge: function(mergedBuffer, buffers) { + var offset = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + var buf = buffers[i]; + buf.copy(mergedBuffer, offset); + offset += buf.length; + } + }, + mask: function(source, mask, output, offset, length) { + var maskNum = mask.readUInt32LE(0, true); + var i = 0; + for (; i < length - 3; i += 4) { + var num = maskNum ^ source.readUInt32LE(i, true); + if (num < 0) num = 4294967296 + num; + output.writeUInt32LE(num, offset + i, true); + } + switch (length % 4) { + case 3: output[offset + i + 2] = source[i + 2] ^ mask[2]; + case 2: output[offset + i + 1] = source[i + 1] ^ mask[1]; + case 1: output[offset + i] = source[i] ^ mask[0]; + case 0:; + } + }, + unmask: function(data, mask) { + var maskNum = mask.readUInt32LE(0, true); + var length = data.length; + var i = 0; + for (; i < length - 3; i += 4) { + var num = maskNum ^ data.readUInt32LE(i, true); + if (num < 0) num = 4294967296 + num; + data.writeUInt32LE(num, i, true); + } + switch (length % 4) { + case 3: data[i + 2] = data[i + 2] ^ mask[2]; + case 2: data[i + 1] = data[i + 1] ^ mask[1]; + case 1: data[i] = data[i] ^ mask[0]; + case 0:; + } + } +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.js new file mode 100644 index 00000000..15d35b98 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.js @@ -0,0 +1,16 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +try { + module.exports = require('../build/Release/bufferutil'); +} catch (e) { try { + module.exports = require('../build/default/bufferutil'); +} catch (e) { try { + module.exports = require('./BufferUtil.fallback'); +} catch (e) { + console.error('bufferutil.node seems to not have been built. Run npm install.'); + throw e; +}}} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/ErrorCodes.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/ErrorCodes.js new file mode 100644 index 00000000..55ebd529 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/ErrorCodes.js @@ -0,0 +1,24 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +module.exports = { + isValidErrorCode: function(code) { + return (code >= 1000 && code <= 1011 && code != 1004 && code != 1005 && code != 1006) || + (code >= 3000 && code <= 4999); + }, + 1000: 'normal', + 1001: 'going away', + 1002: 'protocol error', + 1003: 'unsupported data', + 1004: 'reserved', + 1005: 'reserved for extensions', + 1006: 'reserved for extensions', + 1007: 'inconsistent or invalid data', + 1008: 'policy violation', + 1009: 'message too big', + 1010: 'extension handshake missing', + 1011: 'an unexpected condition prevented the request from being fulfilled', +}; \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.hixie.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.hixie.js new file mode 100644 index 00000000..f54ad966 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.hixie.js @@ -0,0 +1,180 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util'); + +/** + * State constants + */ + +var EMPTY = 0 + , BODY = 1; +var BINARYLENGTH = 2 + , BINARYBODY = 3; + +/** + * Hixie Receiver implementation + */ + +function Receiver () { + this.state = EMPTY; + this.buffers = []; + this.messageEnd = -1; + this.spanLength = 0; + this.dead = false; + + this.onerror = function() {}; + this.ontext = function() {}; + this.onbinary = function() {}; + this.onclose = function() {}; + this.onping = function() {}; + this.onpong = function() {}; +} + +module.exports = Receiver; + +/** + * Add new data to the parser. + * + * @api public + */ + +Receiver.prototype.add = function(data) { + var self = this; + function doAdd() { + if (self.state === EMPTY) { + if (data.length == 2 && data[0] == 0xFF && data[1] == 0x00) { + self.reset(); + self.onclose(); + return; + } + if (data[0] === 0x80) { + self.messageEnd = 0; + self.state = BINARYLENGTH; + data = data.slice(1); + } else { + + if (data[0] !== 0x00) { + self.error('payload must start with 0x00 byte', true); + return; + } + data = data.slice(1); + self.state = BODY; + + } + } + if (self.state === BINARYLENGTH) { + var i = 0; + while ((i < data.length) && (data[i] & 0x80)) { + self.messageEnd = 128 * self.messageEnd + (data[i] & 0x7f); + ++i; + } + if (i < data.length) { + self.messageEnd = 128 * self.messageEnd + (data[i] & 0x7f); + self.state = BINARYBODY; + ++i; + } + if (i > 0) + data = data.slice(i); + } + if (self.state === BINARYBODY) { + var dataleft = self.messageEnd - self.spanLength; + if (data.length >= dataleft) { + // consume the whole buffer to finish the frame + self.buffers.push(data); + self.spanLength += dataleft; + self.messageEnd = dataleft; + return self.parse(); + } + // frame's not done even if we consume it all + self.buffers.push(data); + self.spanLength += data.length; + return; + } + self.buffers.push(data); + if ((self.messageEnd = bufferIndex(data, 0xFF)) != -1) { + self.spanLength += self.messageEnd; + return self.parse(); + } + else self.spanLength += data.length; + } + while(data) data = doAdd(); +} + +/** + * Releases all resources used by the receiver. + * + * @api public + */ + +Receiver.prototype.cleanup = function() { + this.dead = true; + this.state = EMPTY; + this.buffers = []; +} + +/** + * Process buffered data. + * + * @api public + */ + +Receiver.prototype.parse = function() { + var output = new Buffer(this.spanLength); + var outputIndex = 0; + for (var bi = 0, bl = this.buffers.length; bi < bl - 1; ++bi) { + var buffer = this.buffers[bi]; + buffer.copy(output, outputIndex); + outputIndex += buffer.length; + } + var lastBuffer = this.buffers[this.buffers.length - 1]; + if (this.messageEnd > 0) lastBuffer.copy(output, outputIndex, 0, this.messageEnd); + if (this.state !== BODY) --this.messageEnd; + var tail = null; + if (this.messageEnd < lastBuffer.length - 1) { + tail = lastBuffer.slice(this.messageEnd + 1); + } + this.reset(); + this.ontext(output.toString('utf8')); + return tail; +} + +/** + * Handles an error + * + * @api private + */ + +Receiver.prototype.error = function (reason, terminate) { + this.reset(); + this.onerror(reason, terminate); + return this; +} + +/** + * Reset parser state + * + * @api private + */ + +Receiver.prototype.reset = function (reason) { + if (this.dead) return; + this.state = EMPTY; + this.buffers = []; + this.messageEnd = -1; + this.spanLength = 0; +} + +/** + * Internal api + */ + +function bufferIndex(buffer, byte) { + for (var i = 0, l = buffer.length; i < l; ++i) { + if (buffer[i] === byte) return i; + } + return -1; +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.js new file mode 100644 index 00000000..2752726f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.js @@ -0,0 +1,591 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util') + , Validation = require('./Validation').Validation + , ErrorCodes = require('./ErrorCodes') + , BufferPool = require('./BufferPool') + , bufferUtil = require('./BufferUtil').BufferUtil; + +/** + * Node version 0.4 and 0.6 compatibility + */ + +var isNodeV4 = /^v0\.4/.test(process.version); + +/** + * HyBi Receiver implementation + */ + +function Receiver () { + // memory pool for fragmented messages + var fragmentedPoolPrevUsed = -1; + this.fragmentedBufferPool = new BufferPool(1024, function(db, length) { + return db.used + length; + }, function(db) { + return fragmentedPoolPrevUsed = fragmentedPoolPrevUsed >= 0 ? + (fragmentedPoolPrevUsed + db.used) / 2 : + db.used; + }); + + // memory pool for unfragmented messages + var unfragmentedPoolPrevUsed = -1; + this.unfragmentedBufferPool = new BufferPool(1024, function(db, length) { + return db.used + length; + }, function(db) { + return unfragmentedPoolPrevUsed = unfragmentedPoolPrevUsed >= 0 ? + (unfragmentedPoolPrevUsed + db.used) / 2 : + db.used; + }); + + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0, + fragmentedOperation: false + }; + this.overflow = []; + this.headerBuffer = new Buffer(10); + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.currentMessage = []; + this.expectHeader(2, this.processPacket); + this.dead = false; + + this.onerror = function() {}; + this.ontext = function() {}; + this.onbinary = function() {}; + this.onclose = function() {}; + this.onping = function() {}; + this.onpong = function() {}; +}; + +module.exports = Receiver; + +/** + * Add new data to the parser. + * + * @api public + */ + +Receiver.prototype.add = function(data) { + var dataLength = data.length; + if (dataLength == 0) return; + if (this.expectBuffer == null) { + this.overflow.push(data); + return; + } + var toRead = Math.min(dataLength, this.expectBuffer.length - this.expectOffset); + fastCopy(toRead, data, this.expectBuffer, this.expectOffset); + this.expectOffset += toRead; + if (toRead < dataLength) { + this.overflow.push(data.slice(toRead)); + } + while (this.expectBuffer && this.expectOffset == this.expectBuffer.length) { + var bufferForHandler = this.expectBuffer; + this.expectBuffer = null; + this.expectOffset = 0; + this.expectHandler.call(this, bufferForHandler); + } +} + +/** + * Releases all resources used by the receiver. + * + * @api public + */ + +Receiver.prototype.cleanup = function() { + this.dead = true; + this.overflow = null; + this.headerBuffer = null; + this.expectBuffer = null; + this.expectHandler = null; + this.unfragmentedBufferPool = null; + this.fragmentedBufferPool = null; + this.state = null; + this.currentMessage = null; + this.onerror = null; + this.ontext = null; + this.onbinary = null; + this.onclose = null; + this.onping = null; + this.onpong = null; +} + +/** + * Waits for a certain amount of header bytes to be available, then fires a callback. + * + * @api private + */ + +Receiver.prototype.expectHeader = function(length, handler) { + if (length == 0) { + handler(null); + return; + } + this.expectBuffer = this.headerBuffer.slice(this.expectOffset, this.expectOffset + length); + this.expectHandler = handler; + var toRead = length; + while (toRead > 0 && this.overflow.length > 0) { + var fromOverflow = this.overflow.pop(); + if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead)); + var read = Math.min(fromOverflow.length, toRead); + fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset); + this.expectOffset += read; + toRead -= read; + } +} + +/** + * Waits for a certain amount of data bytes to be available, then fires a callback. + * + * @api private + */ + +Receiver.prototype.expectData = function(length, handler) { + if (length == 0) { + handler(null); + return; + } + this.expectBuffer = this.allocateFromPool(length, this.state.fragmentedOperation); + this.expectHandler = handler; + var toRead = length; + while (toRead > 0 && this.overflow.length > 0) { + var fromOverflow = this.overflow.pop(); + if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead)); + var read = Math.min(fromOverflow.length, toRead); + fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset); + this.expectOffset += read; + toRead -= read; + } +} + +/** + * Allocates memory from the buffer pool. + * + * @api private + */ + +Receiver.prototype.allocateFromPool = !isNodeV4 + ? function(length, isFragmented) { return (isFragmented ? this.fragmentedBufferPool : this.unfragmentedBufferPool).get(length); } + : function(length) { return new Buffer(length); }; + +/** + * Start processing a new packet. + * + * @api private + */ + +Receiver.prototype.processPacket = function (data) { + if ((data[0] & 0x70) != 0) { + this.error('reserved fields must be empty', 1002); + return; + } + this.state.lastFragment = (data[0] & 0x80) == 0x80; + this.state.masked = (data[1] & 0x80) == 0x80; + var opcode = data[0] & 0xf; + if (opcode === 0) { + // continuation frame + this.state.fragmentedOperation = true; + this.state.opcode = this.state.activeFragmentedOperation; + if (!(this.state.opcode == 1 || this.state.opcode == 2)) { + this.error('continuation frame cannot follow current opcode', 1002); + return; + } + } + else { + if (opcode < 3 && this.state.activeFragmentedOperation != null) { + this.error('data frames after the initial data frame must have opcode 0', 1002); + return; + } + this.state.opcode = opcode; + if (this.state.lastFragment === false) { + this.state.fragmentedOperation = true; + this.state.activeFragmentedOperation = opcode; + } + else this.state.fragmentedOperation = false; + } + var handler = opcodes[this.state.opcode]; + if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode, 1002); + else { + handler.start.call(this, data); + } +} + +/** + * Endprocessing a packet. + * + * @api private + */ + +Receiver.prototype.endPacket = function() { + if (!this.state.fragmentedOperation) this.unfragmentedBufferPool.reset(true); + else if (this.state.lastFragment) this.fragmentedBufferPool.reset(false); + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + if (this.state.lastFragment && this.state.opcode === this.state.activeFragmentedOperation) { + // end current fragmented operation + this.state.activeFragmentedOperation = null; + } + this.state.lastFragment = false; + this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0; + this.state.masked = false; + this.expectHeader(2, this.processPacket); +} + +/** + * Reset the parser state. + * + * @api private + */ + +Receiver.prototype.reset = function() { + if (this.dead) return; + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0, + fragmentedOperation: false + }; + this.fragmentedBufferPool.reset(true); + this.unfragmentedBufferPool.reset(true); + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.overflow = []; + this.currentMessage = []; +} + +/** + * Unmask received data. + * + * @api private + */ + +Receiver.prototype.unmask = function (mask, buf, binary) { + if (mask != null && buf != null) bufferUtil.unmask(buf, mask); + if (binary) return buf; + return buf != null ? buf.toString('utf8') : ''; +} + +/** + * Concatenates a list of buffers. + * + * @api private + */ + +Receiver.prototype.concatBuffers = function(buffers) { + var length = 0; + for (var i = 0, l = buffers.length; i < l; ++i) length += buffers[i].length; + var mergedBuffer = new Buffer(length); + bufferUtil.merge(mergedBuffer, buffers); + return mergedBuffer; +} + +/** + * Handles an error + * + * @api private + */ + +Receiver.prototype.error = function (reason, protocolErrorCode) { + this.reset(); + this.onerror(reason, protocolErrorCode); + return this; +} + +/** + * Buffer utilities + */ + +function readUInt16BE(start) { + return (this[start]<<8) + + this[start+1]; +} + +function readUInt32BE(start) { + return (this[start]<<24) + + (this[start+1]<<16) + + (this[start+2]<<8) + + this[start+3]; +} + +function fastCopy(length, srcBuffer, dstBuffer, dstOffset) { + switch (length) { + default: srcBuffer.copy(dstBuffer, dstOffset, 0, length); break; + case 16: dstBuffer[dstOffset+15] = srcBuffer[15]; + case 15: dstBuffer[dstOffset+14] = srcBuffer[14]; + case 14: dstBuffer[dstOffset+13] = srcBuffer[13]; + case 13: dstBuffer[dstOffset+12] = srcBuffer[12]; + case 12: dstBuffer[dstOffset+11] = srcBuffer[11]; + case 11: dstBuffer[dstOffset+10] = srcBuffer[10]; + case 10: dstBuffer[dstOffset+9] = srcBuffer[9]; + case 9: dstBuffer[dstOffset+8] = srcBuffer[8]; + case 8: dstBuffer[dstOffset+7] = srcBuffer[7]; + case 7: dstBuffer[dstOffset+6] = srcBuffer[6]; + case 6: dstBuffer[dstOffset+5] = srcBuffer[5]; + case 5: dstBuffer[dstOffset+4] = srcBuffer[4]; + case 4: dstBuffer[dstOffset+3] = srcBuffer[3]; + case 3: dstBuffer[dstOffset+2] = srcBuffer[2]; + case 2: dstBuffer[dstOffset+1] = srcBuffer[1]; + case 1: dstBuffer[dstOffset] = srcBuffer[0]; + } +} + +/** + * Opcode handlers + */ + +var opcodes = { + // text + '1': { + start: function(data) { + var self = this; + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['1'].getData.call(self, firstLength); + } + else if (firstLength == 126) { + self.expectHeader(2, function(data) { + opcodes['1'].getData.call(self, readUInt16BE.call(data, 0)); + }); + } + else if (firstLength == 127) { + self.expectHeader(8, function(data) { + if (readUInt32BE.call(data, 0) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported', 1008); + return; + } + opcodes['1'].getData.call(self, readUInt32BE.call(data, 4)); + }); + } + }, + getData: function(length) { + var self = this; + if (self.state.masked) { + self.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['1'].finish.call(self, mask, data); + }); + }); + } + else { + self.expectData(length, function(data) { + opcodes['1'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + var packet = this.unmask(mask, data, true); + if (packet != null) this.currentMessage.push(packet); + if (this.state.lastFragment) { + var messageBuffer = this.concatBuffers(this.currentMessage); + if (!Validation.isValidUTF8(messageBuffer)) { + this.error('invalid utf8 sequence', 1007); + return; + } + this.ontext(messageBuffer.toString('utf8'), {masked: this.state.masked, buffer: messageBuffer}); + this.currentMessage = []; + } + this.endPacket(); + } + }, + // binary + '2': { + start: function(data) { + var self = this; + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['2'].getData.call(self, firstLength); + } + else if (firstLength == 126) { + self.expectHeader(2, function(data) { + opcodes['2'].getData.call(self, readUInt16BE.call(data, 0)); + }); + } + else if (firstLength == 127) { + self.expectHeader(8, function(data) { + if (readUInt32BE.call(data, 0) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported', 1008); + return; + } + opcodes['2'].getData.call(self, readUInt32BE.call(data, 4, true)); + }); + } + }, + getData: function(length) { + var self = this; + if (self.state.masked) { + self.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['2'].finish.call(self, mask, data); + }); + }); + } + else { + self.expectData(length, function(data) { + opcodes['2'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + var packet = this.unmask(mask, data, true); + if (packet != null) this.currentMessage.push(packet); + if (this.state.lastFragment) { + var messageBuffer = this.concatBuffers(this.currentMessage); + this.onbinary(messageBuffer, {masked: this.state.masked, buffer: messageBuffer}); + this.currentMessage = []; + } + this.endPacket(); + } + }, + // close + '8': { + start: function(data) { + var self = this; + if (self.state.lastFragment == false) { + self.error('fragmented close is not supported', 1002); + return; + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['8'].getData.call(self, firstLength); + } + else { + self.error('control frames cannot have more than 125 bytes of data', 1002); + } + }, + getData: function(length) { + var self = this; + if (self.state.masked) { + self.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['8'].finish.call(self, mask, data); + }); + }); + } + else { + self.expectData(length, function(data) { + opcodes['8'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + var self = this; + data = self.unmask(mask, data, true); + if (data && data.length == 1) { + self.error('close packets with data must be at least two bytes long', 1002); + return; + } + var code = data && data.length > 1 ? readUInt16BE.call(data, 0) : 1000; + if (!ErrorCodes.isValidErrorCode(code)) { + self.error('invalid error code', 1002); + return; + } + var message = ''; + if (data && data.length > 2) { + var messageBuffer = data.slice(2); + if (!Validation.isValidUTF8(messageBuffer)) { + self.error('invalid utf8 sequence', 1007); + return; + } + message = messageBuffer.toString('utf8'); + } + this.onclose(code, message, {masked: self.state.masked}); + this.reset(); + }, + }, + // ping + '9': { + start: function(data) { + var self = this; + if (self.state.lastFragment == false) { + self.error('fragmented ping is not supported', 1002); + return; + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['9'].getData.call(self, firstLength); + } + else { + self.error('control frames cannot have more than 125 bytes of data', 1002); + } + }, + getData: function(length) { + var self = this; + if (self.state.masked) { + self.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['9'].finish.call(self, mask, data); + }); + }); + } + else { + self.expectData(length, function(data) { + opcodes['9'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + this.onping(this.unmask(mask, data, true), {masked: this.state.masked, binary: true}); + this.endPacket(); + } + }, + // pong + '10': { + start: function(data) { + var self = this; + if (self.state.lastFragment == false) { + self.error('fragmented pong is not supported', 1002); + return; + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + opcodes['10'].getData.call(self, firstLength); + } + else { + self.error('control frames cannot have more than 125 bytes of data', 1002); + } + }, + getData: function(length) { + var self = this; + if (this.state.masked) { + this.expectHeader(4, function(data) { + var mask = data; + self.expectData(length, function(data) { + opcodes['10'].finish.call(self, mask, data); + }); + }); + } + else { + this.expectData(length, function(data) { + opcodes['10'].finish.call(self, null, data); + }); + } + }, + finish: function(mask, data) { + this.onpong(this.unmask(mask, data, true), {masked: this.state.masked, binary: true}); + this.endPacket(); + } + } +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.hixie.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.hixie.js new file mode 100644 index 00000000..1754afb6 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.hixie.js @@ -0,0 +1,123 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var events = require('events') + , util = require('util') + , EventEmitter = events.EventEmitter; + +/** + * Hixie Sender implementation + */ + +function Sender(socket) { + this.socket = socket; + this.continuationFrame = false; + this.isClosed = false; +} + +module.exports = Sender; + +/** + * Inherits from EventEmitter. + */ + +util.inherits(Sender, events.EventEmitter); + +/** + * Frames and writes data. + * + * @api public + */ + +Sender.prototype.send = function(data, options, cb) { + if (this.isClosed) return; +/* + if (options && options.binary) { + this.error('hixie websockets do not support binary'); + return; + } +*/ + var isString = typeof data == 'string' + , length = isString ? Buffer.byteLength(data) : data.length + , lengthbytes = (length > 127) ? 2 : 1 // assume less than 2**14 bytes + , writeStartMarker = this.continuationFrame == false + , writeEndMarker = !options || !(typeof options.fin != 'undefined' && !options.fin) + , buffer = new Buffer((writeStartMarker ? ((options && options.binary) ? (1 + lengthbytes) : 1) : 0) + length + ((writeEndMarker && !(options && options.binary)) ? 1 : 0)) + , offset = writeStartMarker ? 1 : 0; + + if (writeStartMarker) { + if (options && options.binary) { + buffer.write('\x80', 'binary'); + // assume length less than 2**14 bytes + if (lengthbytes > 1) + buffer.write(String.fromCharCode(128+length/128), offset++, 'binary'); + buffer.write(String.fromCharCode(length&0x7f), offset++, 'binary'); + } else + buffer.write('\x00', 'binary'); + } + + if (isString) buffer.write(data, offset, 'utf8'); + else data.copy(buffer, offset, 0); + + if (writeEndMarker) { + if (options && options.binary) { + // sending binary, not writing end marker + } else + buffer.write('\xff', offset + length, 'binary'); + this.continuationFrame = false; + } + else this.continuationFrame = true; + + try { + this.socket.write(buffer, 'binary', cb); + } catch (e) { + this.error(e.toString()); + } +} + +/** + * Sends a close instruction to the remote party. + * + * @api public + */ + +Sender.prototype.close = function(code, data, mask, cb) { + if (this.isClosed) return; + this.isClosed = true; + try { + if (this.continuationFrame) this.socket.write(new Buffer([0xff], 'binary')); + this.socket.write(new Buffer([0xff, 0x00]), 'binary', cb); + } catch (e) { + this.error(e.toString()); + } +} + +/** + * Sends a ping message to the remote party. Not available for hixie. + * + * @api public + */ + +Sender.prototype.ping = function(data, options) {} + +/** + * Sends a pong message to the remote party. Not available for hixie. + * + * @api public + */ + +Sender.prototype.pong = function(data, options) {} + +/** + * Handles an error + * + * @api private + */ + +Sender.prototype.error = function (reason) { + this.emit('error', reason); + return this; +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.js new file mode 100644 index 00000000..fc3b4378 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.js @@ -0,0 +1,227 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var events = require('events') + , util = require('util') + , EventEmitter = events.EventEmitter + , ErrorCodes = require('./ErrorCodes') + , bufferUtil = require('./BufferUtil').BufferUtil; + +/** + * HyBi Sender implementation + */ + +function Sender(socket) { + this._socket = socket; + this.firstFragment = true; +} + +/** + * Inherits from EventEmitter. + */ + +util.inherits(Sender, events.EventEmitter); + +/** + * Sends a close instruction to the remote party. + * + * @api public + */ + +Sender.prototype.close = function(code, data, mask) { + if (typeof code !== 'undefined') { + if (typeof code !== 'number' || + !ErrorCodes.isValidErrorCode(code)) throw new Error('first argument must be a valid error code number'); + } + code = code || 1000; + var dataBuffer = new Buffer(2 + (data ? Buffer.byteLength(data) : 0)); + writeUInt16BE.call(dataBuffer, code, 0); + if (dataBuffer.length > 2) dataBuffer.write(data, 2); + this.frameAndSend(0x8, dataBuffer, true, mask); +} + +/** + * Sends a ping message to the remote party. + * + * @api public + */ + +Sender.prototype.ping = function(data, options) { + var mask = options && options.mask; + this.frameAndSend(0x9, data || '', true, mask); +} + +/** + * Sends a pong message to the remote party. + * + * @api public + */ + +Sender.prototype.pong = function(data, options) { + var mask = options && options.mask; + this.frameAndSend(0xa, data || '', true, mask); +} + +/** + * Sends text or binary data to the remote party. + * + * @api public + */ + +Sender.prototype.send = function(data, options, cb) { + var finalFragment = options && options.fin === false ? false : true; + var mask = options && options.mask; + var opcode = options && options.binary ? 2 : 1; + if (this.firstFragment === false) opcode = 0; + else this.firstFragment = false; + if (finalFragment) this.firstFragment = true + this.frameAndSend(opcode, data, finalFragment, mask, cb); +} + +/** + * Frames and sends a piece of data according to the HyBi WebSocket protocol. + * + * @api private + */ + +Sender.prototype.frameAndSend = function(opcode, data, finalFragment, maskData, cb) { + var canModifyData = false; + + if (!data) { + try { + this._socket.write(new Buffer([opcode | (finalFragment ? 0x80 : 0), 0 | (maskData ? 0x80 : 0)].concat(maskData ? [0, 0, 0, 0] : [])), 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + return; + } + + if (!Buffer.isBuffer(data)) { + canModifyData = true; + if (data && (typeof data.byteLength !== 'undefined' || typeof data.buffer !== 'undefined')) { + data = getArrayBuffer(data); + } else { + data = new Buffer(data); + } + } + + var dataLength = data.length + , dataOffset = maskData ? 6 : 2 + , secondByte = dataLength; + + if (dataLength >= 65536) { + dataOffset += 8; + secondByte = 127; + } + else if (dataLength > 125) { + dataOffset += 2; + secondByte = 126; + } + + var mergeBuffers = dataLength < 32768 || (maskData && !canModifyData); + var totalLength = mergeBuffers ? dataLength + dataOffset : dataOffset; + var outputBuffer = new Buffer(totalLength); + outputBuffer[0] = finalFragment ? opcode | 0x80 : opcode; + + switch (secondByte) { + case 126: + writeUInt16BE.call(outputBuffer, dataLength, 2); + break; + case 127: + writeUInt32BE.call(outputBuffer, 0, 2); + writeUInt32BE.call(outputBuffer, dataLength, 6); + } + + if (maskData) { + outputBuffer[1] = secondByte | 0x80; + var mask = this._randomMask || (this._randomMask = getRandomMask()); + outputBuffer[dataOffset - 4] = mask[0]; + outputBuffer[dataOffset - 3] = mask[1]; + outputBuffer[dataOffset - 2] = mask[2]; + outputBuffer[dataOffset - 1] = mask[3]; + if (mergeBuffers) { + bufferUtil.mask(data, mask, outputBuffer, dataOffset, dataLength); + try { + this._socket.write(outputBuffer, 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + } + else { + bufferUtil.mask(data, mask, data, 0, dataLength); + try { + this._socket.write(outputBuffer, 'binary'); + this._socket.write(data, 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + } + } + else { + outputBuffer[1] = secondByte; + if (mergeBuffers) { + data.copy(outputBuffer, dataOffset); + try { + this._socket.write(outputBuffer, 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + } + else { + try { + this._socket.write(outputBuffer, 'binary'); + this._socket.write(data, 'binary', cb); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else this.emit('error', e); + } + } + } +} + +module.exports = Sender; + +function writeUInt16BE(value, offset) { + this[offset] = (value & 0xff00)>>8; + this[offset+1] = value & 0xff; +} + +function writeUInt32BE(value, offset) { + this[offset] = (value & 0xff000000)>>24; + this[offset+1] = (value & 0xff0000)>>16; + this[offset+2] = (value & 0xff00)>>8; + this[offset+3] = value & 0xff; +} + +function getArrayBuffer(data) { + // data is either an ArrayBuffer or ArrayBufferView. + var array = new Uint8Array(data.buffer || data) + , l = data.byteLength || data.length + , o = data.byteOffset || 0 + , buffer = new Buffer(l); + for (var i = 0; i < l; ++i) { + buffer[i] = array[o+i]; + } + return buffer; +} + +function getRandomMask() { + return new Buffer([ + ~~(Math.random() * 255), + ~~(Math.random() * 255), + ~~(Math.random() * 255), + ~~(Math.random() * 255) + ]); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.fallback.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.fallback.js new file mode 100644 index 00000000..2c7c4fd4 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.fallback.js @@ -0,0 +1,12 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +module.exports.Validation = { + isValidUTF8: function(buffer) { + return true; + } +}; + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.js new file mode 100644 index 00000000..0f3109a0 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.js @@ -0,0 +1,16 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +try { + module.exports = require('../build/Release/validation'); +} catch (e) { try { + module.exports = require('../build/default/validation'); +} catch (e) { try { + module.exports = require('./Validation.fallback'); +} catch (e) { + console.error('validation.node seems to not have been built. Run npm install.'); + throw e; +}}} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocket.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocket.js new file mode 100644 index 00000000..cce3cb41 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocket.js @@ -0,0 +1,818 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util') + , events = require('events') + , http = require('http') + , https = require('https') + , crypto = require('crypto') + , url = require('url') + , fs = require('fs') + , Options = require('options') + , Sender = require('./Sender') + , Receiver = require('./Receiver') + , SenderHixie = require('./Sender.hixie') + , ReceiverHixie = require('./Receiver.hixie'); + +/** + * Constants + */ + +// Default protocol version + +var protocolVersion = 13; + +// Close timeout + +var closeTimeout = 30000; // Allow 5 seconds to terminate the connection cleanly + +/** + * Node version 0.4 and 0.6 compatibility + */ + +var isNodeV4 = /^v0\.4/.test(process.version); + +/** + * WebSocket implementation + */ + +function WebSocket(address, protocols, options) { + + if (protocols && !Array.isArray(protocols) && 'object' == typeof protocols) { + // accept the "options" Object as the 2nd argument + options = protocols; + protocols = null; + } + if ('string' == typeof protocols) { + protocols = [ protocols ]; + } + if (!Array.isArray(protocols)) { + protocols = []; + } + // TODO: actually handle the `Sub-Protocols` part of the WebSocket client + + this._socket = null; + this.bytesReceived = 0; + this.readyState = null; + this.supports = {}; + + if (Array.isArray(address)) { + initAsServerClient.apply(this, address.concat(options)); + } else { + initAsClient.apply(this, [address, protocols, options]); + } +} + +/** + * Inherits from EventEmitter. + */ + +util.inherits(WebSocket, events.EventEmitter); + +/** + * Ready States + */ + +["CONNECTING", "OPEN", "CLOSING", "CLOSED"].forEach(function (state, index) { + WebSocket.prototype[state] = WebSocket[state] = index; +}); + +/** + * Gracefully closes the connection, after sending a description message to the server + * + * @param {Object} data to be sent to the server + * @api public + */ + +WebSocket.prototype.close = function(code, data) { + if (this.readyState == WebSocket.CLOSING || this.readyState == WebSocket.CLOSED) return; + if (this.readyState == WebSocket.CONNECTING) { + this.readyState = WebSocket.CLOSED; + return; + } + try { + this.readyState = WebSocket.CLOSING; + this._closeCode = code; + this._closeMessage = data; + var mask = !this._isServer; + this._sender.close(code, data, mask); + } + catch (e) { + this.emit('error', e); + } + finally { + this.terminate(); + } +} + +/** + * Pause the client stream + * + * @api public + */ + +WebSocket.prototype.pause = function() { + if (this.readyState != WebSocket.OPEN) throw new Error('not opened'); + return this._socket.pause(); +} + +/** + * Sends a ping + * + * @param {Object} data to be sent to the server + * @param {Object} Members - mask: boolean, binary: boolean + * @param {boolean} dontFailWhenClosed indicates whether or not to throw if the connection isnt open + * @api public + */ + +WebSocket.prototype.ping = function(data, options, dontFailWhenClosed) { + if (this.readyState != WebSocket.OPEN) { + if (dontFailWhenClosed === true) return; + throw new Error('not opened'); + } + options = options || {}; + if (typeof options.mask == 'undefined') options.mask = !this._isServer; + this._sender.ping(data, options); +} + +/** + * Sends a pong + * + * @param {Object} data to be sent to the server + * @param {Object} Members - mask: boolean, binary: boolean + * @param {boolean} dontFailWhenClosed indicates whether or not to throw if the connection isnt open + * @api public + */ + +WebSocket.prototype.pong = function(data, options, dontFailWhenClosed) { + if (this.readyState != WebSocket.OPEN) { + if (dontFailWhenClosed === true) return; + throw new Error('not opened'); + } + options = options || {}; + if (typeof options.mask == 'undefined') options.mask = !this._isServer; + this._sender.pong(data, options); +} + +/** + * Resume the client stream + * + * @api public + */ + +WebSocket.prototype.resume = function() { + if (this.readyState != WebSocket.OPEN) throw new Error('not opened'); + return this._socket.resume(); +} + +/** + * Sends a piece of data + * + * @param {Object} data to be sent to the server + * @param {Object} Members - mask: boolean, binary: boolean + * @param {function} Optional callback which is executed after the send completes + * @api public + */ + +WebSocket.prototype.send = function(data, options, cb) { + if (typeof options == 'function') { + cb = options; + options = {}; + } + if (this.readyState != WebSocket.OPEN) { + if (typeof cb == 'function') cb(new Error('not opened')); + else throw new Error('not opened'); + return; + } + if (!data) data = ''; + if (this._queue) { + var self = this; + this._queue.push(function() { self.send(data, options, cb); }); + return; + } + options = options || {}; + options.fin = true; + if (typeof options.binary == 'undefined') { + options.binary = (data instanceof ArrayBuffer || data instanceof Buffer || + data instanceof Uint8Array || + data instanceof Uint16Array || + data instanceof Uint32Array || + data instanceof Int8Array || + data instanceof Int16Array || + data instanceof Int32Array || + data instanceof Float32Array || + data instanceof Float64Array); + } + if (typeof options.mask == 'undefined') options.mask = !this._isServer; + if (data instanceof fs.ReadStream) { + startQueue(this); + var self = this; + sendStream(this, data, options, function(error) { + process.nextTick(function() { executeQueueSends(self); }); + if (typeof cb == 'function') cb(error); + }); + } + else this._sender.send(data, options, cb); +} + +/** + * Streams data through calls to a user supplied function + * + * @param {Object} Members - mask: boolean, binary: boolean + * @param {function} 'function (error, send)' which is executed on successive ticks of which send is 'function (data, final)'. + * @api public + */ + +WebSocket.prototype.stream = function(options, cb) { + if (typeof options == 'function') { + cb = options; + options = {}; + } + var self = this; + if (typeof cb != 'function') throw new Error('callback must be provided'); + if (this.readyState != WebSocket.OPEN) { + if (typeof cb == 'function') cb(new Error('not opened')); + else throw new Error('not opened'); + return; + } + if (this._queue) { + this._queue.push(function() { self.stream(options, cb); }); + return; + } + options = options || {}; + if (typeof options.mask == 'undefined') options.mask = !this._isServer; + startQueue(this); + var send = function(data, final) { + try { + if (self.readyState != WebSocket.OPEN) throw new Error('not opened'); + options.fin = final === true; + self._sender.send(data, options); + if (!final) process.nextTick(cb.bind(null, null, send)); + else executeQueueSends(self); + } + catch (e) { + if (typeof cb == 'function') cb(e); + else { + delete self._queue; + self.emit('error', e); + } + } + } + process.nextTick(cb.bind(null, null, send)); +} + +/** + * Immediately shuts down the connection + * + * @api public + */ + +WebSocket.prototype.terminate = function() { + if (this.readyState == WebSocket.CLOSED) return; + if (this._socket) { + try { + // End the connection + this._socket.end(); + } + catch (e) { + // Socket error during end() call, so just destroy it right now + cleanupWebsocketResources.call(this, true); + return; + } + + // Add a timeout to ensure that the connection is completely + // cleaned up within 30 seconds, even if the clean close procedure + // fails for whatever reason + this._closeTimer = setTimeout(cleanupWebsocketResources.bind(this, true), closeTimeout); + } + else if (this.readyState == WebSocket.CONNECTING) { + cleanupWebsocketResources.call(this, true); + } +}; + +/** + * Expose bufferedAmount + * + * @api public + */ + +Object.defineProperty(WebSocket.prototype, 'bufferedAmount', { + get: function get() { + var amount = 0; + if (this._socket) { + amount = this._socket.bufferSize || 0; + } + return amount; + } +}); + +/** + * Emulates the W3C Browser based WebSocket interface using function members. + * + * @see http://dev.w3.org/html5/websockets/#the-websocket-interface + * @api public + */ + +['open', 'error', 'close', 'message'].forEach(function(method) { + Object.defineProperty(WebSocket.prototype, 'on' + method, { + /** + * Returns the current listener + * + * @returns {Mixed} the set function or undefined + * @api public + */ + + get: function get() { + var listener = this.listeners(method)[0]; + return listener ? (listener._listener ? listener._listener : listener) : undefined; + }, + + /** + * Start listening for events + * + * @param {Function} listener the listener + * @returns {Mixed} the set function or undefined + * @api public + */ + + set: function set(listener) { + this.removeAllListeners(method); + this.addEventListener(method, listener); + } + }); +}); + +/** + * Emulates the W3C Browser based WebSocket interface using addEventListener. + * + * @see https://developer.mozilla.org/en/DOM/element.addEventListener + * @see http://dev.w3.org/html5/websockets/#the-websocket-interface + * @api public + */ +WebSocket.prototype.addEventListener = function(method, listener) { + var target = this; + if (typeof listener === 'function') { + if (method === 'message') { + function onMessage (data, flags) { + listener.call(this, new MessageEvent(data, flags.binary ? 'Binary' : 'Text', target)); + } + // store a reference so we can return the original function from the addEventListener hook + onMessage._listener = listener; + this.on(method, onMessage); + } else if (method === 'close') { + function onClose (code, message) { + listener.call(this, new CloseEvent(code, message, target)); + } + // store a reference so we can return the original function from the addEventListener hook + onClose._listener = listener; + this.on(method, onClose); + } else if (method === 'error') { + function onError (event) { + event.target = target; + listener.call(this, event); + } + // store a reference so we can return the original function from the addEventListener hook + onError._listener = listener; + this.on(method, onError); + } else if (method === 'open') { + function onOpen () { + listener.call(this, new OpenEvent(target)); + } + // store a reference so we can return the original function from the addEventListener hook + onOpen._listener = listener; + this.on(method, onOpen); + } else { + this.on(method, listener); + } + } +} + +module.exports = WebSocket; + +/** + * W3C MessageEvent + * + * @see http://www.w3.org/TR/html5/comms.html + * @api private + */ + +function MessageEvent(dataArg, typeArg, target) { + this.data = dataArg; + this.type = typeArg; + this.target = target; +} + +/** + * W3C CloseEvent + * + * @see http://www.w3.org/TR/html5/comms.html + * @api private + */ + +function CloseEvent(code, reason, target) { + this.wasClean = (typeof code == 'undefined' || code == 1000); + this.code = code; + this.reason = reason; + this.target = target; +} + +/** + * W3C OpenEvent + * + * @see http://www.w3.org/TR/html5/comms.html + * @api private + */ + +function OpenEvent(target) { + this.target = target; +} + +/** + * Entirely private apis, + * which may or may not be bound to a sepcific WebSocket instance. + */ + +function initAsServerClient(req, socket, upgradeHead, options) { + options = new Options({ + protocolVersion: protocolVersion, + protocol: null + }).merge(options); + + // expose state properties + this.protocol = options.value.protocol; + this.protocolVersion = options.value.protocolVersion; + this.supports.binary = (this.protocolVersion != 'hixie-76'); + this.upgradeReq = req; + this.readyState = WebSocket.CONNECTING; + this._isServer = true; + + // establish connection + if (options.value.protocolVersion == 'hixie-76') establishConnection.call(this, ReceiverHixie, SenderHixie, socket, upgradeHead); + else establishConnection.call(this, Receiver, Sender, socket, upgradeHead); +} + +function initAsClient(address, protocols, options) { + options = new Options({ + origin: null, + protocolVersion: protocolVersion, + host: null, + headers: null, + protocol: null, + agent: null, + + // ssl-related options + pfx: null, + key: null, + passphrase: null, + cert: null, + ca: null, + ciphers: null, + rejectUnauthorized: null + }).merge(options); + if (options.value.protocolVersion != 8 && options.value.protocolVersion != 13) { + throw new Error('unsupported protocol version'); + } + + // verify url and establish http class + var serverUrl = url.parse(address); + var isUnixSocket = serverUrl.protocol === 'ws+unix:'; + if (!serverUrl.host && !isUnixSocket) throw new Error('invalid url'); + var isSecure = serverUrl.protocol === 'wss:' || serverUrl.protocol === 'https:'; + var httpObj = isSecure ? https : http; + var port = serverUrl.port || (isSecure ? 443 : 80); + var auth = serverUrl.auth; + + // expose state properties + this._isServer = false; + this.url = address; + this.protocolVersion = options.value.protocolVersion; + this.supports.binary = (this.protocolVersion != 'hixie-76'); + + // begin handshake + var key = new Buffer(options.value.protocolVersion + '-' + Date.now()).toString('base64'); + var shasum = crypto.createHash('sha1'); + shasum.update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'); + var expectedServerKey = shasum.digest('base64'); + + var agent = options.value.agent; + // node<=v0.4.x compatibility + if (!agent && isNodeV4) { + isNodeV4 = true; + agent = new httpObj.Agent({ + host: serverUrl.hostname, + port: port + }); + } + + var headerHost = serverUrl.hostname; + // Append port number to Host and Origin header, only if specified in the url and non-default + if(serverUrl.port) { + if((isSecure && (port != 443)) || (!isSecure && (port != 80))){ + headerHost = headerHost + ':' + port; + } + } + + var requestOptions = { + port: port, + host: serverUrl.hostname, + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Host': headerHost, + 'Origin': headerHost, + 'Sec-WebSocket-Version': options.value.protocolVersion, + 'Sec-WebSocket-Key': key + } + }; + + // If we have basic auth. + if (auth) { + requestOptions.headers['Authorization'] = 'Basic ' + new Buffer(auth).toString('base64'); + } + + if (options.value.protocol) { + requestOptions.headers['Sec-WebSocket-Protocol'] = options.value.protocol; + } + + if (options.value.host) { + requestOptions.headers['Host'] = options.value.host; + } + + if (options.value.headers) { + for (var header in options.value.headers) { + if (options.value.headers.hasOwnProperty(header)) { + requestOptions.headers[header] = options.value.headers[header]; + } + } + } + + if (options.isDefinedAndNonNull('pfx') + || options.isDefinedAndNonNull('key') + || options.isDefinedAndNonNull('passphrase') + || options.isDefinedAndNonNull('cert') + || options.isDefinedAndNonNull('ca') + || options.isDefinedAndNonNull('ciphers') + || options.isDefinedAndNonNull('rejectUnauthorized')) { + + if (isNodeV4) { + throw new Error('Client side certificates are not supported on Node 0.4.x'); + } + + if (options.isDefinedAndNonNull('pfx')) requestOptions.pfx = options.value.pfx; + if (options.isDefinedAndNonNull('key')) requestOptions.key = options.value.key; + if (options.isDefinedAndNonNull('passphrase')) requestOptions.passphrase = options.value.passphrase; + if (options.isDefinedAndNonNull('cert')) requestOptions.cert = options.value.cert; + if (options.isDefinedAndNonNull('ca')) requestOptions.ca = options.value.ca; + if (options.isDefinedAndNonNull('ciphers')) requestOptions.ciphers = options.value.ciphers; + if (options.isDefinedAndNonNull('rejectUnauthorized')) requestOptions.rejectUnauthorized = options.value.rejectUnauthorized; + + if (!agent) { + // global agent ignores client side certificates + agent = new httpObj.Agent(requestOptions); + } + } + + if (isNodeV4) { + requestOptions.path = (serverUrl.pathname || '/') + (serverUrl.search || ''); + } + else requestOptions.path = serverUrl.path || '/'; + + if (agent) { + requestOptions.agent = agent; + } + + if (isUnixSocket) { + requestOptions.socketPath = serverUrl.pathname; + } + if (options.value.origin) { + if (options.value.protocolVersion < 13) requestOptions.headers['Sec-WebSocket-Origin'] = options.value.origin; + else requestOptions.headers['Origin'] = options.value.origin; + } + + var self = this; + var req = httpObj.request(requestOptions); + + (isNodeV4 ? agent : req).on('error', function(error) { + self.emit('error', error); + cleanupWebsocketResources.call(this, error); + }); + (isNodeV4 ? agent : req).once('response', function(res) { + var error = new Error('unexpected server response (' + res.statusCode + ')'); + self.emit('error', error); + cleanupWebsocketResources.call(this, error); + }); + (isNodeV4 ? agent : req).once('upgrade', function(res, socket, upgradeHead) { + if (self.readyState == WebSocket.CLOSED) { + // client closed before server accepted connection + self.emit('close'); + removeAllListeners(self); + socket.end(); + return; + } + var serverKey = res.headers['sec-websocket-accept']; + if (typeof serverKey == 'undefined' || serverKey !== expectedServerKey) { + self.emit('error', 'invalid server key'); + removeAllListeners(self); + socket.end(); + return; + } + + var serverProt = res.headers['sec-websocket-protocol']; + var protList = (options.value.protocol || "").split(/, */); + var protError = null; + if (!options.value.protocol && serverProt) { + protError = 'server sent a subprotocol even though none requested'; + } else if (options.value.protocol && !serverProt) { + protError = 'server sent no subprotocol even though requested'; + } else if (serverProt && protList.indexOf(serverProt) === -1) { + protError = 'server responded with an invalid protocol'; + } + if (protError) { + self.emit('error', protError); + removeAllListeners(self); + socket.end(); + return; + } else if (serverProt) { + self.protocol = serverProt; + } + + establishConnection.call(self, Receiver, Sender, socket, upgradeHead); + + // perform cleanup on http resources + removeAllListeners(isNodeV4 ? agent : req); + req = null; + agent = null; + }); + + req.end(); + this.readyState = WebSocket.CONNECTING; +} + +function establishConnection(ReceiverClass, SenderClass, socket, upgradeHead) { + this._socket = socket; + socket.setTimeout(0); + socket.setNoDelay(true); + var self = this; + this._receiver = new ReceiverClass(); + + // socket cleanup handlers + socket.on('end', cleanupWebsocketResources.bind(this)); + socket.on('close', cleanupWebsocketResources.bind(this)); + socket.on('error', cleanupWebsocketResources.bind(this)); + + // ensure that the upgradeHead is added to the receiver + function firstHandler(data) { + if (self.readyState != WebSocket.OPEN) return; + if (upgradeHead && upgradeHead.length > 0) { + self.bytesReceived += upgradeHead.length; + var head = upgradeHead; + upgradeHead = null; + self._receiver.add(head); + } + dataHandler = realHandler; + if (data) { + self.bytesReceived += data.length; + self._receiver.add(data); + } + } + // subsequent packets are pushed straight to the receiver + function realHandler(data) { + if (data) self.bytesReceived += data.length; + self._receiver.add(data); + } + var dataHandler = firstHandler; + // if data was passed along with the http upgrade, + // this will schedule a push of that on to the receiver. + // this has to be done on next tick, since the caller + // hasn't had a chance to set event handlers on this client + // object yet. + process.nextTick(firstHandler); + + // receiver event handlers + self._receiver.ontext = function (data, flags) { + flags = flags || {}; + self.emit('message', data, flags); + }; + self._receiver.onbinary = function (data, flags) { + flags = flags || {}; + flags.binary = true; + self.emit('message', data, flags); + }; + self._receiver.onping = function(data, flags) { + flags = flags || {}; + self.pong(data, {mask: !self._isServer, binary: flags.binary === true}, true); + self.emit('ping', data, flags); + }; + self._receiver.onpong = function(data, flags) { + self.emit('pong', data, flags); + }; + self._receiver.onclose = function(code, data, flags) { + flags = flags || {}; + self.close(code, data); + }; + self._receiver.onerror = function(reason, errorCode) { + // close the connection when the receiver reports a HyBi error code + self.close(typeof errorCode != 'undefined' ? errorCode : 1002, ''); + self.emit('error', reason, errorCode); + }; + + // finalize the client + this._sender = new SenderClass(socket); + this._sender.on('error', function(error) { + self.close(1002, ''); + self.emit('error', error); + }); + this.readyState = WebSocket.OPEN; + this.emit('open'); + + socket.on('data', dataHandler); +} + +function startQueue(instance) { + instance._queue = instance._queue || []; +} + +function executeQueueSends(instance) { + var queue = instance._queue; + if (typeof queue == 'undefined') return; + delete instance._queue; + for (var i = 0, l = queue.length; i < l; ++i) { + queue[i](); + } +} + +function sendStream(instance, stream, options, cb) { + stream.on('data', function(data) { + if (instance.readyState != WebSocket.OPEN) { + if (typeof cb == 'function') cb(new Error('not opened')); + else { + delete instance._queue; + instance.emit('error', new Error('not opened')); + } + return; + } + options.fin = false; + instance._sender.send(data, options); + }); + stream.on('end', function() { + if (instance.readyState != WebSocket.OPEN) { + if (typeof cb == 'function') cb(new Error('not opened')); + else { + delete instance._queue; + instance.emit('error', new Error('not opened')); + } + return; + } + options.fin = true; + instance._sender.send(null, options); + if (typeof cb == 'function') cb(null); + }); +} + +function cleanupWebsocketResources(error) { + if (this.readyState == WebSocket.CLOSED) return; + var emitClose = this.readyState != WebSocket.CONNECTING; + this.readyState = WebSocket.CLOSED; + + clearTimeout(this._closeTimer); + this._closeTimer = null; + if (emitClose) this.emit('close', this._closeCode || 1000, this._closeMessage || ''); + + if (this._socket) { + removeAllListeners(this._socket); + // catch all socket error after removing all standard handlers + var socket = this._socket; + this._socket.on('error', function() { + try { socket.destroy(); } catch (e) {} + }); + try { + if (!error) this._socket.end(); + else this._socket.destroy(); + } + catch (e) { /* Ignore termination errors */ } + this._socket = null; + } + if (this._sender) { + removeAllListeners(this._sender); + this._sender = null; + } + if (this._receiver) { + this._receiver.cleanup(); + this._receiver = null; + } + removeAllListeners(this); + this.on('error', function() {}); // catch all errors after this + delete this._queue; +} + +function removeAllListeners(instance) { + if (isNodeV4) { + // node v4 doesn't *actually* remove all listeners globally, + // so we do that instead + instance._events = {}; + } + else instance.removeAllListeners(); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocketServer.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocketServer.js new file mode 100644 index 00000000..da759f8b --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocketServer.js @@ -0,0 +1,460 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var util = require('util') + , events = require('events') + , http = require('http') + , crypto = require('crypto') + , url = require('url') + , Options = require('options') + , WebSocket = require('./WebSocket') + , tls = require('tls') + , url = require('url'); + +/** + * WebSocket Server implementation + */ + +function WebSocketServer(options, callback) { + options = new Options({ + host: '0.0.0.0', + port: null, + server: null, + verifyClient: null, + handleProtocols: null, + path: null, + noServer: false, + disableHixie: false, + clientTracking: true + }).merge(options); + + if (!options.isDefinedAndNonNull('port') && !options.isDefinedAndNonNull('server') && !options.value.noServer) { + throw new TypeError('`port` or a `server` must be provided'); + } + + var self = this; + + if (options.isDefinedAndNonNull('port')) { + this._server = http.createServer(function (req, res) { + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.end('Not implemented'); + }); + this._server.listen(options.value.port, options.value.host, callback); + this._closeServer = function() { self._server.close(); }; + } + else if (options.value.server) { + this._server = options.value.server; + if (options.value.path) { + // take note of the path, to avoid collisions when multiple websocket servers are + // listening on the same http server + if (this._server._webSocketPaths && options.value.server._webSocketPaths[options.value.path]) { + throw new Error('two instances of WebSocketServer cannot listen on the same http server path'); + } + if (typeof this._server._webSocketPaths !== 'object') { + this._server._webSocketPaths = {}; + } + this._server._webSocketPaths[options.value.path] = 1; + } + } + if (this._server) this._server.once('listening', function() { self.emit('listening'); }); + + if (typeof this._server != 'undefined') { + this._server.on('error', function(error) { + self.emit('error', error) + }); + this._server.on('upgrade', function(req, socket, upgradeHead) { + //copy upgradeHead to avoid retention of large slab buffers used in node core + var head = new Buffer(upgradeHead.length); + upgradeHead.copy(head); + + self.handleUpgrade(req, socket, head, function(client) { + self.emit('connection'+req.url, client); + self.emit('connection', client); + }); + }); + } + + this.options = options.value; + this.path = options.value.path; + this.clients = []; +} + +/** + * Inherits from EventEmitter. + */ + +util.inherits(WebSocketServer, events.EventEmitter); + +/** + * Immediately shuts down the connection. + * + * @api public + */ + +WebSocketServer.prototype.close = function() { + // terminate all associated clients + var error = null; + try { + for (var i = 0, l = this.clients.length; i < l; ++i) { + this.clients[i].terminate(); + } + } + catch (e) { + error = e; + } + + // remove path descriptor, if any + if (this.path && this._server._webSocketPaths) { + delete this._server._webSocketPaths[this.path]; + if (Object.keys(this._server._webSocketPaths).length == 0) { + delete this._server._webSocketPaths; + } + } + + // close the http server if it was internally created + try { + if (typeof this._closeServer !== 'undefined') { + this._closeServer(); + } + } + finally { + delete this._server; + } + if (error) throw error; +} + +/** + * Handle a HTTP Upgrade request. + * + * @api public + */ + +WebSocketServer.prototype.handleUpgrade = function(req, socket, upgradeHead, cb) { + // check for wrong path + if (this.options.path) { + var u = url.parse(req.url); + if (u && u.pathname !== this.options.path) return; + } + + if (typeof req.headers.upgrade === 'undefined' || req.headers.upgrade.toLowerCase() !== 'websocket') { + abortConnection(socket, 400, 'Bad Request'); + return; + } + + if (req.headers['sec-websocket-key1']) handleHixieUpgrade.apply(this, arguments); + else handleHybiUpgrade.apply(this, arguments); +} + +module.exports = WebSocketServer; + +/** + * Entirely private apis, + * which may or may not be bound to a sepcific WebSocket instance. + */ + +function handleHybiUpgrade(req, socket, upgradeHead, cb) { + // handle premature socket errors + var errorHandler = function() { + try { socket.destroy(); } catch (e) {} + } + socket.on('error', errorHandler); + + // verify key presence + if (!req.headers['sec-websocket-key']) { + abortConnection(socket, 400, 'Bad Request'); + return; + } + + // verify version + var version = parseInt(req.headers['sec-websocket-version']); + if ([8, 13].indexOf(version) === -1) { + abortConnection(socket, 400, 'Bad Request'); + return; + } + + // verify protocol + var protocols = req.headers['sec-websocket-protocol']; + + // verify client + var origin = version < 13 ? + req.headers['sec-websocket-origin'] : + req.headers['origin']; + + // handler to call when the connection sequence completes + var self = this; + var completeHybiUpgrade2 = function(protocol) { + + // calc key + var key = req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + if (typeof protocol != 'undefined') { + headers.push('Sec-WebSocket-Protocol: ' + protocol); + } + + // allows external modification/inspection of handshake headers + self.emit('headers', headers); + + socket.setTimeout(0); + socket.setNoDelay(true); + try { + socket.write(headers.concat('', '').join('\r\n')); + } + catch (e) { + // if the upgrade write fails, shut the connection down hard + try { socket.destroy(); } catch (e) {} + return; + } + + var client = new WebSocket([req, socket, upgradeHead], { + protocolVersion: version, + protocol: protocol + }); + + if (self.options.clientTracking) { + self.clients.push(client); + client.on('close', function() { + var index = self.clients.indexOf(client); + if (index != -1) { + self.clients.splice(index, 1); + } + }); + } + + // signal upgrade complete + socket.removeListener('error', errorHandler); + cb(client); + } + + // optionally call external protocol selection handler before + // calling completeHybiUpgrade2 + var completeHybiUpgrade1 = function() { + // choose from the sub-protocols + if (typeof self.options.handleProtocols == 'function') { + var protList = (protocols || "").split(/, */); + var callbackCalled = false; + var res = self.options.handleProtocols(protList, function(result, protocol) { + callbackCalled = true; + if (!result) abortConnection(socket, 404, 'Unauthorized') + else completeHybiUpgrade2(protocol); + }); + if (!callbackCalled) { + // the handleProtocols handler never called our callback + abortConnection(socket, 501, 'Could not process protocols'); + } + return; + } else { + if (typeof protocols !== 'undefined') { + completeHybiUpgrade2(protocols.split(/, */)[0]); + } + else { + completeHybiUpgrade2(); + } + } + } + + // optionally call external client verification handler + if (typeof this.options.verifyClient == 'function') { + var info = { + origin: origin, + secure: typeof req.connection.authorized !== 'undefined' || typeof req.connection.encrypted !== 'undefined', + req: req + }; + if (this.options.verifyClient.length == 2) { + this.options.verifyClient(info, function(result) { + if (!result) abortConnection(socket, 401, 'Unauthorized') + else completeHybiUpgrade1(); + }); + return; + } + else if (!this.options.verifyClient(info)) { + abortConnection(socket, 401, 'Unauthorized'); + return; + } + } + + completeHybiUpgrade1(); +} + +function handleHixieUpgrade(req, socket, upgradeHead, cb) { + // handle premature socket errors + var errorHandler = function() { + try { socket.destroy(); } catch (e) {} + } + socket.on('error', errorHandler); + + // bail if options prevent hixie + if (this.options.disableHixie) { + abortConnection(socket, 401, 'Hixie support disabled'); + return; + } + + // verify key presence + if (!req.headers['sec-websocket-key2']) { + abortConnection(socket, 400, 'Bad Request'); + return; + } + + var origin = req.headers['origin'] + , self = this; + + // setup handshake completion to run after client has been verified + var onClientVerified = function() { + var wshost; + if (!req.headers['x-forwarded-host']) + wshost = req.headers.host; + else + wshost = req.headers['x-forwarded-host']; + var location = ((req.headers['x-forwarded-proto'] === 'https' || socket.encrypted) ? 'wss' : 'ws') + '://' + wshost + req.url + , protocol = req.headers['sec-websocket-protocol']; + + // handshake completion code to run once nonce has been successfully retrieved + var completeHandshake = function(nonce, rest) { + // calculate key + var k1 = req.headers['sec-websocket-key1'] + , k2 = req.headers['sec-websocket-key2'] + , md5 = crypto.createHash('md5'); + + [k1, k2].forEach(function (k) { + var n = parseInt(k.replace(/[^\d]/g, '')) + , spaces = k.replace(/[^ ]/g, '').length; + if (spaces === 0 || n % spaces !== 0){ + abortConnection(socket, 400, 'Bad Request'); + return; + } + n /= spaces; + md5.update(String.fromCharCode( + n >> 24 & 0xFF, + n >> 16 & 0xFF, + n >> 8 & 0xFF, + n & 0xFF)); + }); + md5.update(nonce.toString('binary')); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: WebSocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Location: ' + location + ]; + if (typeof protocol != 'undefined') headers.push('Sec-WebSocket-Protocol: ' + protocol); + if (typeof origin != 'undefined') headers.push('Sec-WebSocket-Origin: ' + origin); + + socket.setTimeout(0); + socket.setNoDelay(true); + try { + // merge header and hash buffer + var headerBuffer = new Buffer(headers.concat('', '').join('\r\n')); + var hashBuffer = new Buffer(md5.digest('binary'), 'binary'); + var handshakeBuffer = new Buffer(headerBuffer.length + hashBuffer.length); + headerBuffer.copy(handshakeBuffer, 0); + hashBuffer.copy(handshakeBuffer, headerBuffer.length); + + // do a single write, which - upon success - causes a new client websocket to be setup + socket.write(handshakeBuffer, 'binary', function(err) { + if (err) return; // do not create client if an error happens + var client = new WebSocket([req, socket, rest], { + protocolVersion: 'hixie-76', + protocol: protocol + }); + if (self.options.clientTracking) { + self.clients.push(client); + client.on('close', function() { + var index = self.clients.indexOf(client); + if (index != -1) { + self.clients.splice(index, 1); + } + }); + } + + // signal upgrade complete + socket.removeListener('error', errorHandler); + cb(client); + }); + } + catch (e) { + try { socket.destroy(); } catch (e) {} + return; + } + } + + // retrieve nonce + var nonceLength = 8; + if (upgradeHead && upgradeHead.length >= nonceLength) { + var nonce = upgradeHead.slice(0, nonceLength); + var rest = upgradeHead.length > nonceLength ? upgradeHead.slice(nonceLength) : null; + completeHandshake.call(self, nonce, rest); + } + else { + // nonce not present in upgradeHead, so we must wait for enough data + // data to arrive before continuing + var nonce = new Buffer(nonceLength); + upgradeHead.copy(nonce, 0); + var received = upgradeHead.length; + var rest = null; + var handler = function (data) { + var toRead = Math.min(data.length, nonceLength - received); + if (toRead === 0) return; + data.copy(nonce, received, 0, toRead); + received += toRead; + if (received == nonceLength) { + socket.removeListener('data', handler); + if (toRead < data.length) rest = data.slice(toRead); + completeHandshake.call(self, nonce, rest); + } + } + socket.on('data', handler); + } + } + + // verify client + if (typeof this.options.verifyClient == 'function') { + var info = { + origin: origin, + secure: typeof req.connection.authorized !== 'undefined' || typeof req.connection.encrypted !== 'undefined', + req: req + }; + if (this.options.verifyClient.length == 2) { + var self = this; + this.options.verifyClient(info, function(result) { + if (!result) abortConnection(socket, 401, 'Unauthorized') + else onClientVerified.apply(self); + }); + return; + } + else if (!this.options.verifyClient(info)) { + abortConnection(socket, 401, 'Unauthorized'); + return; + } + } + + // no client verification required + onClientVerified(); +} + +function abortConnection(socket, code, name) { + try { + var response = [ + 'HTTP/1.1 ' + code + ' ' + name, + 'Content-type: text/html' + ]; + socket.write(response.concat('', '').join('\r\n')); + } + catch (e) { /* ignore errors - we've aborted this connection */ } + finally { + // ensure that an early aborted connection is shut down completely + try { socket.destroy(); } catch (e) {} + } +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/browser.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/browser.js new file mode 100644 index 00000000..8d3a755c --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/browser.js @@ -0,0 +1,43 @@ + +/** + * Module dependencies. + */ + +var global = (function() { return this; })(); + +/** + * WebSocket constructor. + */ + +var WebSocket = global.WebSocket || global.MozWebSocket; + +/** + * Module exports. + */ + +module.exports = WebSocket ? ws : null; + +/** + * WebSocket constructor. + * + * The third `opts` options object gets ignored in web browsers, since it's + * non-standard, and throws a TypeError if passed to the constructor. + * See: https://github.com/einaros/ws/issues/227 + * + * @param {String} uri + * @param {Array} protocols (optional) + * @param {Object) opts (optional) + * @api public + */ + +function ws(uri, protocols, opts) { + var instance; + if (protocols) { + instance = new WebSocket(uri, protocols); + } else { + instance = new WebSocket(uri); + } + return instance; +} + +if (WebSocket) ws.prototype = WebSocket.prototype; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.npmignore b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.npmignore new file mode 100644 index 00000000..f1250e58 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.travis.yml b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.travis.yml new file mode 100644 index 00000000..f1d0f13c --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/History.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/History.md new file mode 100644 index 00000000..4961d2e2 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/History.md @@ -0,0 +1,107 @@ + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Makefile b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Makefile new file mode 100644 index 00000000..00746255 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Makefile @@ -0,0 +1,7 @@ + +TESTS = $(shell find test/test.*.js) + +test: + @./test/run $(TESTS) + +.PHONY: test \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Readme.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Readme.md new file mode 100644 index 00000000..b8328c37 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Readme.md @@ -0,0 +1,262 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineappe'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineappe + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .prompt(msg, fn) + + Single-line prompt: + +```js +program.prompt('name: ', function(name){ + console.log('hi %s', name); +}); +``` + + Multi-line prompt: + +```js +program.prompt('description:', function(name){ + console.log('hi %s', name); +}); +``` + + Coercion: + +```js +program.prompt('Age: ', Number, function(age){ + console.log('age: %j', age); +}); +``` + +```js +program.prompt('Birthdate: ', Date, function(date){ + console.log('date: %s', date); +}); +``` + +## .password(msg[, mask], fn) + +Prompt for password without echoing: + +```js +program.password('Password: ', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +Prompt for password with mask char "*": + +```js +program.password('Password: ', '*', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +## .confirm(msg, fn) + + Confirm with the given `msg`: + +```js +program.confirm('continue? ', function(ok){ + console.log(' got %j', ok); +}); +``` + +## .choose(list, fn) + + Let the user choose from a `list`: + +```js +var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + +console.log('Choose the coolest pet:'); +program.choose(list, function(i){ + console.log('you chose %d "%s"', i, list[i]); +}); +``` + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/index.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/index.js new file mode 100644 index 00000000..06ec1e4b --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/commander'); \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/lib/commander.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/lib/commander.js new file mode 100644 index 00000000..5ba87ebb --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/lib/commander.js @@ -0,0 +1,1026 @@ + +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , path = require('path') + , tty = require('tty') + , basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this.args = []; + this.name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + return cmd; +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self.args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self.args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this.name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + self.args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self.args.length) { + args[self.args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // store raw args + this.rawArgs = argv; + + // guess name + if (!this.name) this.name = basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + this.args = parsed.args; + return this.parseArgs(this.args, parsed.unknown); +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0]) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || '-' == arg[0]) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this.args.length ? ' ' + args : ''); + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return cmd.name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args + + (cmd.description() + ? '\n' + cmd.description() + : ''); + }).join('\n\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this.name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Prompt for a `Number`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForNumber = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseNumber(val){ + val = Number(val); + if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); + fn(val); + }); +}; + +/** + * Prompt for a `Date`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForDate = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseDate(val){ + val = new Date(val); + if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); + fn(val); + }); +}; + +/** + * Single-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptSingleLine = function(str, fn){ + if ('function' == typeof arguments[2]) { + return this['promptFor' + (fn.name || fn)](str, arguments[2]); + } + + process.stdout.write(str); + process.stdin.setEncoding('utf8'); + process.stdin.once('data', function(val){ + fn(val.trim()); + }).resume(); +}; + +/** + * Multi-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptMultiLine = function(str, fn){ + var buf = []; + console.log(str); + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(val){ + if ('\n' == val || '\r\n' == val) { + process.stdin.removeAllListeners('data'); + fn(buf.join('\n')); + } else { + buf.push(val.trimRight()); + } + }).resume(); +}; + +/** + * Prompt `str` and callback `fn(val)` + * + * Commander supports single-line and multi-line prompts. + * To issue a single-line prompt simply add white-space + * to the end of `str`, something like "name: ", whereas + * for a multi-line prompt omit this "description:". + * + * + * Examples: + * + * program.prompt('Username: ', function(name){ + * console.log('hi %s', name); + * }); + * + * program.prompt('Description:', function(desc){ + * console.log('description was "%s"', desc.trim()); + * }); + * + * @param {String|Object} str + * @param {Function} fn + * @api public + */ + +Command.prototype.prompt = function(str, fn){ + var self = this; + + if ('string' == typeof str) { + if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); + this.promptMultiLine(str, fn); + } else { + var keys = Object.keys(str) + , obj = {}; + + function next() { + var key = keys.shift() + , label = str[key]; + + if (!key) return fn(obj); + self.prompt(label, function(val){ + obj[key] = val; + next(); + }); + } + + next(); + } +}; + +/** + * Prompt for password with `str`, `mask` char and callback `fn(val)`. + * + * The mask string defaults to '', aka no output is + * written while typing, you may want to use "*" etc. + * + * Examples: + * + * program.password('Password: ', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * program.password('Password: ', '*', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {String} mask + * @param {Function} fn + * @api public + */ + +Command.prototype.password = function(str, mask, fn){ + var self = this + , buf = ''; + + // default mask + if ('function' == typeof mask) { + fn = mask; + mask = ''; + } + + process.stdin.resume(); + tty.setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.removeAllListeners('keypress'); + tty.setRawMode(false); + if (!buf.trim().length) return self.password(str, mask, fn); + fn(buf); + return; + } + + if (key && key.ctrl && 'c' == key.name) { + console.log('%s', buf); + process.exit(); + } + + process.stdout.write(mask); + buf += c; + }).resume(); +}; + +/** + * Confirmation prompt with `str` and callback `fn(bool)` + * + * Examples: + * + * program.confirm('continue? ', function(ok){ + * console.log(' got %j', ok); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {Function} fn + * @api public + */ + + +Command.prototype.confirm = function(str, fn, verbose){ + var self = this; + this.prompt(str, function(ok){ + if (!ok.trim()) { + if (!verbose) str += '(yes or no) '; + return self.confirm(str, fn, true); + } + fn(parseBool(ok)); + }); +}; + +/** + * Choice prompt with `list` of items and callback `fn(index, item)` + * + * Examples: + * + * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + * + * console.log('Choose the coolest pet:'); + * program.choose(list, function(i){ + * console.log('you chose %d "%s"', i, list[i]); + * process.stdin.destroy(); + * }); + * + * @param {Array} list + * @param {Number|Function} index or fn + * @param {Function} fn + * @api public + */ + +Command.prototype.choose = function(list, index, fn){ + var self = this + , hasDefault = 'number' == typeof index; + + if (!hasDefault) { + fn = index; + index = null; + } + + list.forEach(function(item, i){ + if (hasDefault && i == index) { + console.log('* %d) %s', i + 1, item); + } else { + console.log(' %d) %s', i + 1, item); + } + }); + + function again() { + self.prompt(' : ', function(val){ + val = parseInt(val, 10) - 1; + if (hasDefault && isNaN(val)) val = index; + + if (null == list[val]) { + again(); + } else { + fn(val, list[val]); + } + }); + } + + again(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Parse a boolean `str`. + * + * @param {String} str + * @return {Boolean} + * @api private + */ + +function parseBool(str) { + return /^y|yes|ok|true$/i.test(str); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + process.stdout.write(cmd.helpInformation()); + cmd.emit('--help'); + process.exit(0); + } + } +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/package.json new file mode 100644 index 00000000..9936f7d7 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/package.json @@ -0,0 +1,39 @@ +{ + "name": "commander", + "version": "0.6.1", + "description": "the complete solution for node.js command-line programs", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/commander.js.git" + }, + "dependencies": {}, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.4.x" + }, + "readme": "# Commander.js\n\n The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n $ npm install commander\n\n## Option parsing\n\n Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n .version('0.0.1')\n .option('-p, --peppers', 'Add peppers')\n .option('-P, --pineapple', 'Add pineapple')\n .option('-b, --bbq', 'Add bbq sauce')\n .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log(' - peppers');\nif (program.pineapple) console.log(' - pineappe');\nif (program.bbq) console.log(' - bbq');\nconsole.log(' - %s cheese', program.cheese);\n```\n\n Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as \"--template-engine\" are camel-cased, becoming `program.templateEngine` etc.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n``` \n $ ./examples/pizza --help\n\n Usage: pizza [options]\n\n Options:\n\n -V, --version output the version number\n -p, --peppers Add peppers\n -P, --pineapple Add pineappe\n -b, --bbq Add bbq sauce\n -c, --cheese Add the specified type of cheese [marble]\n -h, --help output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n return val.split('..').map(Number);\n}\n\nfunction list(val) {\n return val.split(',');\n}\n\nprogram\n .version('0.0.1')\n .usage('[options] ')\n .option('-i, --integer ', 'An integer argument', parseInt)\n .option('-f, --float ', 'A float argument', parseFloat)\n .option('-r, --range ..', 'A range', range)\n .option('-l, --list ', 'A list', list)\n .option('-o, --optional [value]', 'An optional value')\n .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n return val.split(',').map(Number);\n}\n\nprogram\n .version('0.0.1')\n .option('-f, --foo', 'enable some foo')\n .option('-b, --bar', 'enable some bar')\n .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n console.log(' Examples:');\n console.log('');\n console.log(' $ custom-help --help');\n console.log(' $ custom-help -h');\n console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -f, --foo enable some foo\n -b, --bar enable some bar\n -B, --baz enable some baz\n\nExamples:\n\n $ custom-help --help\n $ custom-help -h\n\n```\n\n## .prompt(msg, fn)\n\n Single-line prompt:\n\n```js\nprogram.prompt('name: ', function(name){\n console.log('hi %s', name);\n});\n```\n\n Multi-line prompt:\n\n```js\nprogram.prompt('description:', function(name){\n console.log('hi %s', name);\n});\n```\n\n Coercion:\n\n```js\nprogram.prompt('Age: ', Number, function(age){\n console.log('age: %j', age);\n});\n```\n\n```js\nprogram.prompt('Birthdate: ', Date, function(date){\n console.log('date: %s', date);\n});\n```\n\n## .password(msg[, mask], fn)\n\nPrompt for password without echoing:\n\n```js\nprogram.password('Password: ', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\nPrompt for password with mask char \"*\":\n\n```js\nprogram.password('Password: ', '*', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\n## .confirm(msg, fn)\n\n Confirm with the given `msg`:\n\n```js\nprogram.confirm('continue? ', function(ok){\n console.log(' got %j', ok);\n});\n```\n\n## .choose(list, fn)\n\n Let the user choose from a `list`:\n\n```js\nvar list = ['tobi', 'loki', 'jane', 'manny', 'luna'];\n\nconsole.log('Choose the coolest pet:');\nprogram.choose(list, function(i){\n console.log('you chose %d \"%s\"', i, list[i]);\n});\n```\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/commander.js/issues" + }, + "homepage": "https://github.com/visionmedia/commander.js", + "_id": "commander@0.6.1", + "_from": "commander@~0.6.1" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/.index.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/.index.js new file mode 100644 index 00000000..68da1f34 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/.index.js @@ -0,0 +1 @@ +//noop \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/LICENSE b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/LICENSE new file mode 100644 index 00000000..352c2874 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/LICENSE @@ -0,0 +1,43 @@ +Copyright 2013, NAN contributors: + - Rod Vagg + - Benjamin Byholm + - Trevor Norris +(the "Original Author") +All rights reserved. + +MIT +no-false-attribs License + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +Distributions of all or part of the Software intended to be used +by the recipients as they would use the unmodified Software, +containing modifications that substantially alter, remove, or +disable functionality of the Software, outside of the documented +configuration mechanisms provided by the Software, shall be +modified such that the Original Author's bug reporting email +addresses and urls are either replaced with the contact information +of the parties responsible for the changes, or removed entirely. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + +Except where noted, this license applies to any and all software +programs and associated documentation files created by the +Original Author, when distributed with the Software. diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/README.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/README.md new file mode 100644 index 00000000..6ba57f78 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/README.md @@ -0,0 +1,705 @@ +Native Abstractions for Node.js +=============================== + +**A header file filled with macro and utility goodness for making addon development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.** + +***Current version: 0.3.2*** *(See [nan.h](https://github.com/rvagg/nan/blob/master/nan.h) for changelog)* + +[![NPM](https://nodei.co/npm/nan.png?downloads=true&stars=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/) + +Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. + +This project also contains some helper utilities that make addon development a bit more pleasant. + + * **[Usage](#usage)** + * **[Example](#example)** + * **[API](#api)** + + +## Usage + +Simply add **NAN** as a dependency in the *package.json* of your Node addon: + +```js +"dependencies": { + ... + "nan" : "~0.3.1" + ... +} +``` + +Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include "nan.h"` in your *.cpp*: + +```js +"include_dirs" : [ + ... + "` when compiling your addon. + + +## Example + +See **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use. + +For a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. + +Compare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work). + +Note that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class. + +```c++ +// addon.cc +#include +#include "nan.h" +// ... + +using namespace v8; + +void InitAll(Handle exports) { + exports->Set(NanSymbol("calculateSync"), + FunctionTemplate::New(CalculateSync)->GetFunction()); + + exports->Set(NanSymbol("calculateAsync"), + FunctionTemplate::New(CalculateAsync)->GetFunction()); +} + +NODE_MODULE(addon, InitAll) +``` + +```c++ +// sync.h +#include +#include "nan.h" + +NAN_METHOD(CalculateSync); +``` + +```c++ +// sync.cc +#include +#include "nan.h" +#include "sync.h" +// ... + +using namespace v8; + +// Simple synchronous access to the `Estimate()` function +NAN_METHOD(CalculateSync) { + NanScope(); + + // expect a number as the first argument + int points = args[0]->Uint32Value(); + double est = Estimate(points); + + NanReturnValue(Number::New(est)); +} +``` + +```c++ +// async.cc +#include +#include "nan.h" +#include "async.h" + +// ... + +using namespace v8; + +class PiWorker : public NanAsyncWorker { + public: + PiWorker(NanCallback *callback, int points) + : NanAsyncWorker(callback), points(points) {} + ~PiWorker() {} + + // Executed inside the worker-thread. + // It is not safe to access V8, or V8 data structures + // here, so everything we need for input and output + // should go on `this`. + void Execute () { + estimate = Estimate(points); + } + + // Executed when the async work is complete + // this function will be run inside the main event loop + // so it is safe to use V8 again + void HandleOKCallback () { + NanScope(); + + Local argv[] = { + Local::New(Null()) + , Number::New(estimate) + }; + + callback->Call(2, argv); + }; + + private: + int points; + double estimate; +}; + +// Asynchronous access to the `Estimate()` function +NAN_METHOD(CalculateAsync) { + NanScope(); + + int points = args[0]->Uint32Value(); + NanCallback *callback = new NanCallback(args[1].As()); + + NanAsyncQueueWorker(new PiWorker(callback, points)); + NanReturnUndefined(); +} +``` + + +## API + + * NAN_METHOD + * NAN_GETTER + * NAN_SETTER + * NAN_PROPERTY_GETTER + * NAN_PROPERTY_SETTER + * NAN_PROPERTY_ENUMERATOR + * NAN_PROPERTY_DELETER + * NAN_PROPERTY_QUERY + * NAN_WEAK_CALLBACK + * NanReturnValue + * NanReturnUndefined + * NanReturnNull + * NanReturnEmptyString + * NanScope + * NanLocker + * NanUnlocker + * NanGetInternalFieldPointer + * NanSetInternalFieldPointer + * NanObjectWrapHandle + * NanMakeWeak + * NanSymbol + * NanGetPointerSafe + * NanSetPointerSafe + * NanFromV8String + * NanBooleanOptionValue + * NanUInt32OptionValue + * NanThrowError, NanThrowTypeError, NanThrowRangeError, NanThrowError(Handle), NanThrowError(Handle, int) + * NanNewBufferHandle(char *, size_t, FreeCallback, void *), NanNewBufferHandle(char *, uint32_t), NanNewBufferHandle(uint32_t) + * NanBufferUse(char *, uint32_t) + * NanNewContextHandle + * NanHasInstance + * NanPersistentToLocal + * NanDispose + * NanAssignPersistent + * NanInitPersistent + * NanCallback + * NanAsyncWorker + * NanAsyncQueueWorker + + +### NAN_METHOD(methodname) + +Use `NAN_METHOD` to define your V8 accessible methods: + +```c++ +// .h: +class Foo : public node::ObjectWrap { + ... + + static NAN_METHOD(Bar); + static NAN_METHOD(Baz); +} + + +// .cc: +NAN_METHOD(Foo::Bar) { + ... +} + +NAN_METHOD(Foo::Baz) { + ... +} +``` + +The reason for this macro is because of the method signature change in 0.11: + +```c++ +// 0.10 and below: +Handle name(const Arguments& args) + +// 0.11 and above +void name(const FunctionCallbackInfo& args) +``` + +The introduction of `FunctionCallbackInfo` brings additional complications: + + +### NAN_GETTER(methodname) + +Use `NAN_GETTER` to declare your V8 accessible getters. You get a `Local` `property` and an appropriately typed `args` object that can act like the `args` argument to a `NAN_METHOD` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_GETTER`. + + +### NAN_SETTER(methodname) + +Use `NAN_SETTER` to declare your V8 accessible setters. Same as `NAN_GETTER` but you also get a `Local` `value` object to work with. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_SETTER`. + + +### NAN_PROPERTY_GETTER(cbname) +Use `NAN_PROPERTY_GETTER` to declare your V8 accessible property getters. You get a `Local` `property` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_GETTER`. + + +### NAN_PROPERTY_SETTER(cbname) +Use `NAN_PROPERTY_SETTER` to declare your V8 accessible property setters. Same as `NAN_PROPERTY_GETTER` but you also get a `Local` `value` object to work with. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_SETTER`. + + +### NAN_PROPERTY_ENUMERATOR(cbname) +Use `NAN_PROPERTY_ENUMERATOR` to declare your V8 accessible property enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_PROPERTY_GETTER` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_ENUMERATOR`. + + +### NAN_PROPERTY_DELETER(cbname) +Use `NAN_PROPERTY_DELETER` to declare your V8 accessible property deleters. Same as `NAN_PROPERTY_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_DELETER`. + + +### NAN_PROPERTY_QUERY(cbname) +Use `NAN_PROPERTY_QUERY` to declare your V8 accessible property queries. Same as `NAN_PROPERTY_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_QUERY`. + + +### NAN_WEAK_CALLBACK(type, cbname) + +Use `NAN_WEAK_CALLBACK` to declare your V8 WeakReference callbacks. There is an object argument accessible through `NAN_WEAK_CALLBACK_OBJECT`. The `type` argument gives the type of the `data` argument, accessible through `NAN_WEAK_CALLBACK_DATA(type)`. + +```c++ +static NAN_WEAK_CALLBACK(BufferReference*, WeakCheck) { + if (NAN_WEAK_CALLBACK_DATA(BufferReference*)->noLongerNeeded_) { + delete NAN_WEAK_CALLBACK_DATA(BufferReference*); + } else { + // Still in use, revive, prevent GC + NanMakeWeak(NAN_WEAK_CALLBACK_OBJECT, NAN_WEAK_CALLBACK_DATA(BufferReference*), &WeakCheck); + } +} + +``` + +### NanReturnValue(Handle<Value>) + +Use `NanReturnValue` when you want to return a value from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Bar) { + ... + + NanReturnValue(String::New("FooBar!")); +} +``` + +No `return` statement required. + + +### NanReturnUndefined() + +Use `NanReturnUndefined` when you don't want to return anything from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnUndefined(); +} +``` + + +### NanReturnNull() + +Use `NanReturnNull` when you want to return `Null` from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnNull(); +} +``` + + +### NanReturnEmptyString() + +Use `NanReturnEmptyString` when you want to return an empty `String` from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnEmptyString(); +} +``` + + +### NanScope() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanScope()` necessary, use it in place of `HandleScope scope`: + +```c++ +NAN_METHOD(Foo::Bar) { + NanScope(); + + NanReturnValue(String::New("FooBar!")); +} +``` + + +### NanLocker() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanLocker()` necessary, use it in place of `Locker locker`: + +```c++ +NAN_METHOD(Foo::Bar) { + NanLocker(); + ... + NanUnlocker(); +} +``` + + +### NanUnlocker() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanUnlocker()` necessary, use it in place of `Unlocker unlocker`: + +```c++ +NAN_METHOD(Foo::Bar) { + NanLocker(); + ... + NanUnlocker(); +} +``` + + +### void * NanGetInternalFieldPointer(Handle<Object>, int) + +Gets a pointer to the internal field with at `index` from a V8 `Object` handle. + +```c++ +Local obj; +... +NanGetInternalFieldPointer(obj, 0); +``` + +### void NanSetInternalFieldPointer(Handle<Object>, int, void *) + +Sets the value of the internal field at `index` on a V8 `Object` handle. + +```c++ +static Persistent dataWrapperCtor; +... +Local wrapper = NanPersistentToLocal(dataWrapperCtor)->NewInstance(); +NanSetInternalFieldPointer(wrapper, 0, this); +``` + + +### Local<Object> NanObjectWrapHandle(Object) + +When you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`: + +```c++ +NanObjectWrapHandle(iterator)->Get(String::NewSymbol("end")) +``` + + +### NanMakeWeak(Persistent<T>, parameter, callback) + +Make a persistent reference weak. + + +### String NanSymbol(char *) + +This isn't strictly about compatibility, it's just an easier way to create string symbol objects (i.e. `String::NewSymbol(x)`), for getting and setting object properties, or names of objects. + +```c++ +bool foo = false; +if (obj->Has(NanSymbol("foo"))) + foo = optionsObj->Get(NanSymbol("foo"))->BooleanValue() +``` + + +### Type NanGetPointerSafe(Type *[, Type]) + +A helper for getting values from optional pointers. If the pointer is `NULL`, the function returns the optional default value, which defaults to `0`. Otherwise, the function returns the value the pointer points to. + +```c++ +char *plugh(uint32_t *optional) { + char res[] = "xyzzy"; + uint32_t param = NanGetPointerSafe(optional, 0x1337); + switch (param) { + ... + } + NanSetPointerSafe(optional, 0xDEADBEEF); +} +``` + + +### bool NanSetPointerSafe(Type *, Type) + +A helper for setting optional argument pointers. If the pointer is `NULL`, the function simply return `false`. Otherwise, the value is assigned to the variable the pointer points to. + +```c++ +const char *plugh(size_t *outputsize) { + char res[] = "xyzzy"; + if !(NanSetPointerSafe(outputsize, strlen(res) + 1)) { + ... + } + + ... +} +``` + + +### char* NanFromV8String(Handle<Value>[, enum Nan::Encoding, size_t *, char *, size_t, int]) + +When you want to convert a V8 `String` to a `char*` use `NanFromV8String`. It is possible to define an encoding that defaults to `Nan::UTF8` as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `String::HINT_MANY_WRITES_EXPECTED | String::NO_NULL_TERMINATION`. +Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: + +```c++ +size_t count; +char* name = NanFromV8String(args[0]); +char* decoded = NanFromV8String(args[1], Nan::BASE64, &count, NULL, 0, String::HINT_MANY_WRITES_EXPECTED); +char param_copy[count]; +memcpy(param_copy, decoded, count); +delete[] decoded; +``` + + +### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool]) + +When you have an "options" object that you need to fetch properties from, boolean options can be fetched with this pair. They check first if the object exists (`IsEmpty`), then if the object has the given property (`Has`) then they get and convert/coerce the property to a `bool`. + +The optional last parameter is the *default* value, which is `false` if left off: + +```c++ +// `foo` is false unless the user supplies a truthy value for it +bool foo = NanBooleanOptionValue(optionsObj, NanSymbol("foo")); +// `bar` is true unless the user supplies a falsy value for it +bool bar = NanBooleanOptionValueDefTrue(optionsObj, NanSymbol("bar"), true); +``` + + +### uint32_t NanUInt32OptionValue(Handle<Value>, Handle<String>, uint32_t) + +Similar to `NanBooleanOptionValue`, use `NanUInt32OptionValue` to fetch an integer option from your options object. Can be any kind of JavaScript `Number` and it will be coerced to an unsigned 32-bit integer. + +Requires all 3 arguments as a default is not optional: + +```c++ +uint32_t count = NanUInt32OptionValue(optionsObj, NanSymbol("count"), 1024); +``` + + +### NanThrowError(message), NanThrowTypeError(message), NanThrowRangeError(message), NanThrowError(Local<Value>), NanThrowError(Local<Value>, int) + +For throwing `Error`, `TypeError` and `RangeError` objects. You should `return` this call: + +```c++ +return NanThrowError("you must supply a callback argument"); +``` + +Can also handle any custom object you may want to throw. If used with the error code argument, it will add the supplied error code to the error object as a property called `code`. + + +### Local<Object> NanNewBufferHandle(char *, uint32_t), Local<Object> NanNewBufferHandle(uint32_t) + +The `Buffer` API has changed a little in Node 0.11, this helper provides consistent access to `Buffer` creation: + +```c++ +NanNewBufferHandle((char*)value.data(), value.size()); +``` + +Can also be used to initialize a `Buffer` with just a `size` argument. + +Can also be supplied with a `NAN_WEAK_CALLBACK` and a hint for the garbage collector, when dealing with weak references. + + +### Local<Object> NanBufferUse(char*, uint32_t) + +`Buffer::New(char*, uint32_t)` prior to 0.11 would make a copy of the data. +While it was possible to get around this, it required a shim by passing a +callback. So the new API `Buffer::Use(char*, uint32_t)` was introduced to remove +needing to use this shim. + +`NanBufferUse` uses the `char*` passed as the backing data, and will free the +memory automatically when the weak callback is called. Keep this in mind, as +careless use can lead to "double free or corruption" and other cryptic failures. + + +### bool NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>) + +Can be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent` handle for. + + +### Local<Type> NanPersistentToLocal(Persistent<Type>&) + +Aside from `FunctionCallbackInfo`, the biggest and most painful change to V8 in Node 0.11 is the many restrictions now placed on `Persistent` handles. They are difficult to assign and difficult to fetch the original value out of. + +Use `NanPersistentToLocal` to convert a `Persistent` handle back to a `Local` handle. + +```c++ +Local handle = NanPersistentToLocal(persistentHandle); +``` + + +### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>]) +Creates a new `Local` handle. + +```c++ +Local ftmpl = FunctionTemplate::New(); +Local otmpl = ftmpl->InstanceTemplate(); +Local ctx = NanNewContextHandle(NULL, otmpl); +``` + + +### void NanDispose(Persistent<T> &) + +Use `NanDispose` to dispose a `Persistent` handle. + +```c++ +NanDispose(persistentHandle); +``` + + +### NanAssignPersistent(type, handle, object) + +Use `NanAssignPersistent` to assign a non-`Persistent` handle to a `Persistent` one. You can no longer just declare a `Persistent` handle and assign directly to it later, you have to `Reset` it in Node 0.11, so this makes it easier. + +In general it is now better to place anything you want to protect from V8's garbage collector as properties of a generic `Object` and then assign that to a `Persistent`. This works in older versions of Node also if you use `NanAssignPersistent`: + +```c++ +Persistent persistentHandle; + +... + +Local obj = Object::New(); +obj->Set(NanSymbol("key"), keyHandle); // where keyHandle might be a Local +NanAssignPersistent(Object, persistentHandle, obj) +``` + + +### NanInitPersistent(type, name, object) + +User `NanInitPersistent` to declare and initialize a new `Persistent` with the supplied object. The assignment operator for `Persistent` is no longer public in Node 0.11, so this macro makes it easier to declare and initializing a new `Persistent`. See NanAssignPersistent for more information. + +```c++ +Local obj = Object::New(); +obj->Set(NanSymbol("key"), keyHandle); // where keyHandle might be a Local +NanInitPersistent(Object, persistentHandle, obj); +``` + + +### NanCallback + +Because of the difficulties imposed by the changes to `Persistent` handles in V8 in Node 0.11, creating `Persistent` versions of your `Local` handles is annoyingly tricky. `NanCallback` makes it easier by taking your `Local` handle, making it persistent until the `NanCallback` is deleted and even providing a handy `Call()` method to fetch and execute the callback `Function`. + +```c++ +Local callbackHandle = callback = args[0].As(); +NanCallback *callback = new NanCallback(callbackHandle); +// pass `callback` around and it's safe from GC until you: +delete callback; +``` + +You can execute the callback like so: + +```c++ +// no arguments: +callback->Call(0, NULL); + +// an error argument: +Local argv[] = { + Exception::Error(String::New("fail!")) +}; +callback->Call(1, argv); + +// a success argument: +Local argv[] = { + Local::New(Null()), + String::New("w00t!") +}; +callback->Call(2, argv); +``` + +`NanCallback` also has a `Local GetCallback()` method that you can use to fetch a local handle to the underlying callback function if you need it. + + +### NanAsyncWorker + +`NanAsyncWorker` is an abstract class that you can subclass to have much of the annoying async queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the async work is in progress. + +See a rough outline of the implementation: + +```c++ +class NanAsyncWorker { +public: + NanAsyncWorker (NanCallback *callback); + + // Clean up persistent handles and delete the *callback + virtual ~NanAsyncWorker (); + + // Check the `char *errmsg` property and call HandleOKCallback() + // or HandleErrorCallback depending on whether it has been set or not + virtual void WorkComplete (); + + // You must implement this to do some async work. If there is an + // error then allocate `errmsg` to to a message and the callback will + // be passed that string in an Error object + virtual void Execute (); + +protected: + // Set this if there is an error, otherwise it's NULL + const char *errmsg; + + // Save a V8 object in a Persistent handle to protect it from GC + void SavePersistent(const char *key, Local &obj); + + // Fetch a stored V8 object (don't call from within `Execute()`) + Local GetFromPersistent(const char *key); + + // Default implementation calls the callback function with no arguments. + // Override this to return meaningful data + virtual void HandleOKCallback (); + + // Default implementation calls the callback function with an Error object + // wrapping the `errmsg` string + virtual void HandleErrorCallback (); +}; +``` + + +### NanAsyncQueueWorker(NanAsyncWorker *) + +`NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`. + +### Contributors + +NAN is only possible due to the excellent work of the following contributors: + +
'; +html += '
Enter Your Password
'; +html += '
'; +html += '
Password:


'; +html += '
'; +html += '
'; +html += '

'; +html += ''; +html += ''; +html += ''; +html += '
' + large_icon_button('x', 'Cancel', "clear_login()") + ' ' + large_icon_button('check', 'Login', 'do_effect_login()') + '
'; +html += '
'; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_effect_login'; +session.hooks.keys[ESC_KEY] = 'clear_login'; +safe_focus( 'fe_lp_password' ); +show_popup_dialog(450, 225, html); +} +function clear_login() { +hide_popup_dialog(); +Nav.prev(); +} +function do_login() { +if ($('fe_username').value.match(/^\w+$/)) { +session.username = $('fe_username').value; +session.auto_login = $('fe_auto_login').checked; +do_login_prompt_2(); +return; +} +else { +do_openid_login(); +} +} +function do_openid_login() { +if (!$('fe_username').value) return; +session.openid_win = popup_window(''); +if (!session.openid_win) return; +session.open_id = $('fe_username').value; +session.auto_login = $('fe_auto_login') && $('fe_auto_login').checked; +hide_popup_dialog(); +show_progress_dialog(1, "Logging in..."); +session.hooks.before_error = 'close_openid_window'; +session.hooks.after_error = 'do_login_prompt'; +effect_api_send('openid_login', { +OpenID: session.open_id, +Infinite: session.auto_login ? 1 : 0 +}, 'do_openid_login_2'); +} +function close_openid_window() { +if (session.openid_win) { +session.openid_win.close(); +delete session.openid_win; +} +} +function do_openid_login_2(response) { +if (response.CheckURL) { +Debug.trace('openid', "Redirecting popup window to OpenID Check URL: " + response.CheckURL); +show_progress_dialog(1, "Waiting for popup window...", false, ['x', 'Cancel', 'do_login_prompt()']); +session.openid_win.location = response.CheckURL; +session.openid_win.focus(); +} +} +function receive_openid_response(iframe_response) { +var response = deep_copy_object(iframe_response); +Debug.trace('openid', "Received OpenID Response: " + dumper(response)); +hide_popup_dialog(); +if (response.Code) { +close_openid_window(); +return do_error( response.Description ); +} +delete session.hooks.before_error; +delete session.hooks.after_error; +if (response.SessionID) { +session.cookie.set( 'effect_session_id', response.SessionID ); +session.cookie.save(); +} +switch (response.Action) { +case 'popup': +show_progress_dialog(1, "Waiting for popup window...", false, ['x', 'Cancel', 'do_login_prompt()']); +Debug.trace('openid', "Redirecting popup window to OpenID Setup URL: " + response.SetupURL); +session.openid_win.location = response.SetupURL; +session.openid_win.focus(); +break; +case 'login': +close_openid_window(); +do_login_2(response); +break; +case 'register': +if (!response.Info) response.Info = {}; +close_openid_window(); +Debug.trace('openid', 'Original OpenID: ' + response.OpenID_Login); +Debug.trace('openid', 'Clean OpenID: ' + response.OpenID_Unique); +Debug.trace('openid', 'Registration Info: ' + dumper(response.Info)); +session.prereg = response.Info; +session.prereg.open_id_login = response.OpenID_Login; +session.prereg.open_id = response.OpenID_Unique; +if (session.user) { +if (!session.user.OpenIDs) session.user.OpenIDs = {}; +if (!session.user.OpenIDs.OpenID) session.user.OpenIDs.OpenID = []; +var dupe = find_object( session.user.OpenIDs.OpenID, { Unique: session.prereg.open_id } ); +if (dupe) return do_error("That OpenID is already registered and attached to your account. No need to add it again."); +session.user.OpenIDs.OpenID.push({ +Login: session.prereg.open_id_login, +Unique: session.prereg.open_id +}); +setTimeout( function() { +Nav.go('MyAccount', true); +do_message('success', 'Added new OpenID URL to account.'); +}, 1 ); +} +else { +setTimeout( function() { Nav.go('CreateAccount', true); }, 1 ); +} +break; +} +} +function do_effect_login() { +var password = $('fe_lp_password').value; +session.auto_login = $('fe_auto_login').checked; +hide_popup_dialog(); +show_progress_dialog(1, "Logging in..."); +session.hooks.after_error = 'do_login_prompt'; +effect_api_send('user_login', { +Username: session.username, +Password: password, +Infinite: session.auto_login ? 1 : 0 +}, 'do_login_2'); +} +function do_logout() { +effect_api_send('user_logout', {}, 'do_logout_2'); +} +function do_logout_2(response) { +hide_popup_dialog(); +show_default_login_status(); +delete session.hooks.after_error; +delete session.cookie.tree.effect_session_id; +session.cookie.save(); +session.storage = {}; +session.storage_dirty = false; +delete session.user; +delete session.first_login; +var old_username = session.username; +session.username = ''; +if (Nav.inited) { +Nav.go('Main'); +if (old_username) $GR.growl('success', "Logged out of account: " + old_username); +} +else { +Nav.init(); +} +} +function do_login_2(response, tx) { +if (response.FirstLogin) session.first_login = 1; +if (response.User.UserStorage) { +Debug.trace('Recovering site storage blob: session.storage = ' + response.User.UserStorage + ';'); +try { +eval( 'session.storage = ' + response.User.UserStorage + ';' ); +} +catch (e) { +Debug.trace("SITE STORAGE RECOVERY FAILED: " + e); +session.storage = {}; +} +delete response.User.UserStorage; +session.storage_dirty = false; +} +session.user = response.User; +session.username = session.user.Username; +hide_popup_dialog(); +delete session.hooks.after_error; +update_header(); +if (!tx || !tx._from_recover) $GR.growl('success', "Logged in as: " + session.username); +if (session.nav_after_login) { +Nav.go( session.nav_after_login ); +delete session.nav_after_login; +} +else if (Nav.currentAnchor().match(/^Login/)) { +Nav.go('Home'); +} +else { +Nav.refresh(); +} +Nav.init(); +} +function user_storage_mark() { +Debug.trace("Marking user storage as dirty"); +session.storage_dirty = true; +} +function user_storage_idle() { +if (session.storage_dirty && !session.mouseIsDown) { +user_storage_save(); +session.storage_dirty = false; +} +setTimeout( 'user_storage_idle()', 5000 ); +} +function user_storage_save() { +if (session.user) { +Debug.trace("Committing user storage blob"); +effect_api_send('update_user_storage', { Data: serialize(session.storage) }, 'user_storage_save_finish', { _silent: 1 } ); +} +} +function user_storage_save_finish(response, tx) { +} +function show_default_login_status() { +$('d_sidebar_wrapper_recent_games').hide(); +$('d_login_status').innerHTML = '
' + +'
' + +large_icon_button('key', "Login", '#Home') + '' + spacer(1,1) + '' + +'' + large_icon_button('user_add.png', "Signup", '#CreateAccount') + '
' + +'
'; +$('d_tagline').innerHTML = +'Login' + ' | ' + +'Create Account'; +} +function update_header() { +var html = ''; +html += '
'; +html += ''; +html += ''; +html += ''; +html += ''+spacer(2,2)+''; +html += session.user.FullName + '
'; +html += spacer(1,5) + '
'; +html += 'My Home  |  '; +html += 'Logout'; +html += '
'; +$('d_login_status').innerHTML = html; +$('d_tagline').innerHTML = +'Welcome '+session.user.FirstName+'' + ' | ' + +'My Home' + ' | ' + +'Logout'; +effect_api_get( 'get_user_games', { limit:5, offset:0 }, 'receive_sidebar_recent_games', { } ); +} +function receive_sidebar_recent_games(response, tx) { +var html = ''; +if (response.Rows && response.Rows.Row) { +var games = always_array( response.Rows.Row ); +for (var idx = 0, len = games.length; idx < len; idx++) { +var game = games[idx]; +html += ''; +} +html += ''; +$('d_sidebar_recent_games').innerHTML = html; +$('d_sidebar_wrapper_recent_games').show(); +} +else { +$('d_sidebar_wrapper_recent_games').hide(); +} +} +function check_privilege(key) { +if (!session.user) return false; +if (session.user.Privileges.admin == 1) return true; +if (!key.toString().match(/^\//)) key = '/' + key; +var value = lookup_path(key, session.user.Privileges); +return( value && (value != 0) ); +} +function is_admin() { +return check_privilege('admin'); +} +function upgrade_flash_error() { +return alert("Sorry, file upload requires Adobe Flash Player 9 or higher."); +} +function cancel_user_image_manager() { +upload_destroy(); +hide_popup_dialog(); +delete session.hooks.keys[DELETE_KEY]; +} +function do_user_image_manager(callback) { +if (callback) session.uim_callback = callback; +else session.uim_callback = null; +session.temp_last_user_img = null; +session.temp_last_user_image_filename = ''; +var html = '
'; +html += '
Image Manager
'; +html += '
'; +html += ''; +html += '
'; +html += '
'; +html += ''; +html += ''; +html += ''; +html += ''; +html += ''; +html += '
' + large_icon_button('x', 'Cancel', 'cancel_user_image_manager()') + ' ' + large_icon_button('bullet_upload.png', 'Upload Files...', 'upload_basic()', 'b_upload_user_image') + ' ' + large_icon_button('check', 'Choose', 'do_choose_user_image()', 'btn_choose_user_image', '', 'disabled') + '
'; +html += '
'; +session.hooks.keys[ENTER_KEY] = 'do_choose_user_image'; +session.hooks.keys[ESC_KEY] = 'cancel_user_image_manager'; +session.hooks.keys[DELETE_KEY] = 'do_delete_selected_user_image'; +show_popup_dialog(500, 300, html); +var self = this; +setTimeout( function() { +prep_upload('b_upload_user_image', '/effect/api/upload_user_image', [self, 'do_upload_user_image_2'], ['Image Files', '*.jpg;*.jpe;*.jpeg;*.gif;*.png']); +}, 1 ); +var args = { +limit: 50, +offset: 0, +random: Math.random() +}; +effect_api_get( 'user_images_get', args, 'uim_populate_images', { } ); +} +function do_upload_user_image_2() { +effect_api_mod_touch('user_images_get'); +effect_api_send('user_get', { +Username: session.username +}, [this, 'do_upload_user_image_3']); +} +function do_upload_user_image_3(response) { +if (response.User.LastUploadError) return do_error( "Failed to upload image: " + response.User.LastUploadError ); +do_user_image_manager( session.uim_callback ); +} +function uim_populate_images(response, tx) { +var html = ''; +var base_url = '/effect/api/view/users/' + session.username + '/images'; +if (response.Rows && response.Rows.Row) { +var imgs = always_array( response.Rows.Row ); +for (var idx = 0, len = imgs.length; idx < len; idx++) { +var img = imgs[idx]; +var class_name = ((img.Filename == session.temp_last_user_image_filename) ? 'choose_item_selected' : 'choose_item'); +html += ''; +} +} +else { +html = ''; +} +$('d_user_image_list').innerHTML = html; +} +function do_select_user_image(img, filename) { +if (session.temp_last_user_img) session.temp_last_user_img.className = 'choose_item'; +img.className = 'choose_item_selected'; +$('btn_choose_user_image').removeClass('disabled'); +session.temp_last_user_img = img; +session.temp_last_user_image_filename = filename; +} +function do_delete_selected_user_image() { +if (session.temp_last_user_image_filename) { +effect_api_send('user_image_delete', { Filename: session.temp_last_user_image_filename }, 'do_delete_selected_user_image_finish', {}); +} +} +function do_delete_selected_user_image_finish(response, tx) { +try { $('d_user_image_list').removeChild( session.temp_last_user_img ); } catch(e) {;} +session.temp_last_user_img = null; +session.temp_last_user_image_filename = null; +} +function do_choose_user_image() { +if (!session.temp_last_user_image_filename) return; +if (session.uim_callback) { +fire_callback( session.uim_callback, session.temp_last_user_image_filename ); +} +cancel_user_image_manager(); +} +function user_image_thumbnail(filename, width, height, attribs) { +var username = session.username; +if (filename.match(/^(\w+)\/(.+)$/)) { +username = RegExp.$1; +filename = RegExp.$2; +} +var url = '/effect/api/view/users/' + username + '/images/' + filename.replace(/\.(\w+)$/, '_thumb.jpg'); +return ''; +} +function get_user_display(username, full_name, base_url) { +if (!base_url) base_url = ''; +return icon('user', full_name || username, base_url + '#User/' + username); +} +function get_game_tab_bar(game_id, cur_page_name) { +return tab_bar([ +['#Game/' + game_id, 'Game', 'controller.png'], +['#GameDisplay/' + game_id, 'Display', 'monitor.png'], +['#GameAssets/' + game_id, 'Assets', 'folder_page_white.png'], +['#GameObjects/' + game_id, 'Objects', 'bricks.png'], +['#GameAudio/' + game_id, 'Audio', 'sound.gif'], +['#GameKeys/' + game_id, 'Keyboard', 'keyboard.png'], +['#GameLevels/' + game_id, 'Levels', 'world.png'], +['#GamePublisher/' + game_id, 'Publish', 'cd.png'] +], cur_page_name); +} +function get_user_tab_bar(cur_page_name) { +var tabs = [ +['#Home', 'My Home', 'house.png'] +]; +tabs.push( ['#MyAccount', 'Edit Account', 'user_edit.png'] ); +tabs.push( ['#ArticleEdit', 'Post Article', 'page_white_edit.png'] ); +if (config.ProEnabled) { +tabs.push( ['#UserPayments', 'Payments', 'money.png'] ); +} +tabs.push( ['#UserLog', 'Security Log', 'application_view_detail.png'] ); +return tab_bar(tabs, cur_page_name); +} +function get_admin_tab_bar(cur_page_name) { +var tabs = []; +tabs.push( ['#Admin', 'Admin', 'lock.png'] ); +tabs.push( ['#TicketSearch/bugs', 'Bug Tracker', 'bug.png'] ); +tabs.push( ['#TicketSearch/helpdesk', 'Help Desk', 'telephone.png'] ); +tabs.push( ['#AdminReport', 'Reports', 'chart_pie.png'] ); +return tab_bar(tabs, cur_page_name); +} +function get_string(path, args) { +assert(window.config, "get_string() called before config loaded"); +if (!args) args = {}; +args.config = config; +args.session = session; +args.query = session.query; +var value = lookup_path(path, config.Strings); +return (typeof(value) == 'string') ? substitute(value, args) : value; +} +function normalize_dir_path(path) { +if (!path.match(/^\//)) path = '/' + path; +if (!path.match(/\/$/)) path += '/'; +return path; +} +function textedit_window_save(storage_key, filename, content, callback) { +if (!callback) callback = null; +effect_api_mod_touch('textedit'); +if (storage_key.match(/^\/games\/([a-z0-9][a-z0-9\-]*[a-z0-9])\/assets(.+)$/)) { +var game_id = RegExp.$1; +var path = RegExp.$2; +show_progress_dialog(1, "Saving file..."); +effect_api_send('asset_save_file_contents', { +GameID: game_id, +Path: path, +Filename: filename, +Content: content +}, 'textedit_window_save_finish', { _mode: 'asset', _game_id: game_id, _filename: filename, _callback: callback } ); +} +else { +show_progress_dialog(1, "Saving data..."); +effect_api_send('admin_save_file_contents', { +Path: storage_key, +Filename: filename, +Content: content +}, 'textedit_window_save_finish', { _mode: 'admin', _storage_key: storage_key, _filename: filename, _callback: callback } ); +} +} +function textedit_window_save_finish(response, tx) { +hide_progress_dialog(); +if (tx._mode == 'asset') { +do_message('success', "Saved asset: \""+tx._filename+"\""); +show_glog_widget(); +} +else { +do_message('success', "Saved data: \""+tx._storage_key+'/'+tx._filename+"\""); +} +if (tx._callback) tx._callback(); +} +function do_buy(args) { +$P().hide(); +$('d_page_loading').show(); +effect_api_send('create_order', args, 'do_buy_redirect', { _buy_args: args } ); +} +function do_buy_redirect(response, tx) { +var args = tx._buy_args; +$('fe_gco_title').value = args.Title || ''; +$('fe_gco_desc').value = args.Desc || ''; +$('fe_gco_price').value = args.Price || ''; +$('fe_gco_after').value = args.After || ''; +$('fe_gco_unique_id').value = response.OrderID; +Debug.trace('payment', "Redirecting to Google Checkout"); +setTimeout( function() { $('BB_BuyButtonForm').submit(); }, 1 ); +} +function show_glog_widget(game_id) { +if (!game_id) game_id = session.glog_game_id; +if (!game_id) { +$('glog_widget').hide(); +return; +} +if (game_id != session.glog_game_id) { +$('glog_widget').hide(); +session.glog_game_id = game_id; +update_glog_widget(game_id); +} +else { +$('glog_widget').show(); +setTimeout( function() { update_glog_widget(game_id); }, 500 ); +} +} +function update_glog_widget(game_id) { +effect_api_get('game_get_log', { +id: game_id, +offset: 0, +limit: 1, +rand: Math.random() +}, 'receive_glog_data', { _game_id: game_id }); +} +function receive_glog_data(response, tx) { +var game_id = tx._game_id; +if (response && response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +var row = rows[0]; +var html = ''; +html += '
'; +html += '
Latest Game Activity
'; +html += ''; +html += ''; +html += '
'; +html += '
'; +html += ''; +html += ''; +html += ''; +html += '
' + get_buddy_icon_display(row.Username, 1, 0) + ''; +html += '
' + icon( get_icon_for_glog_type(row.Type), ''+row.Message+'' ) + '
'; +html += '
' + get_relative_date(row.Date, true) + '
'; +html += '
'; +$('glog_widget').innerHTML = html; +$('glog_widget').show(); +} +} +function show_glog_post_dialog(game_id) { +hide_popup_dialog(); +delete session.progress; +var html = ''; +html += '
'; +html += '\n \n \n \n'); + }; + __out.push('\n\n'); + __out.push(require('templates/clients/modules/sub_header').call(this, { + heading: t("Ride Request") + })); + __out.push('\n\n\n
\n
\n
\n
\n \n \n \n \n
\n\n
'; +html += '
Post Game Log Message
'; +html += '
'; +html += ''; +html += '
Enter your log message here. Plain text only please.
'; +html += '
'; +html += '

'; +html += ''; +html += ''; +html += ''; +html += '
' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Message', "glog_post('"+game_id+"')") + '
'; +html += '
'; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_glog_body' ); +show_popup_dialog(500, 175, html); +} +function glog_post(game_id) { +var msg = trim( $('fe_glog_body').value ); +if (msg) { +hide_popup_dialog(); +effect_api_send('game_post_log', { +GameID: game_id, +Message: msg +}, [this, 'glog_post_finish'], { _game_id: game_id }); +} +} +function glog_post_finish(response, tx) { +show_glog_widget( tx._game_id ); +} +function hide_glog_widget() { +$('glog_widget').hide(); +} +function get_icon_for_glog_type(type) { +var icon = 'page_white.png'; +switch (type) { +case 'asset': icon = 'folder_page_white.png'; break; +case 'game': icon = 'controller.png'; break; +case 'member': icon = 'user'; break; +case 'comment': icon = 'comment.png'; break; +case 'level': icon = 'world.png'; break; +case 'sprite': icon = 'cog.png'; break; +case 'tile': icon = 'brick.png'; break; +case 'tileset': icon = 'color_swatch.png'; break; +case 'rev': icon = 'cd.png'; break; +case 'revision': icon = 'cd.png'; break; +case 'font': icon = 'style.png'; break; +case 'key': icon = 'keyboard.png'; break; +case 'audio': icon = 'sound'; break; +case 'payment': icon = 'money.png'; break; +case 'env': icon = 'weather.png'; break; +case 'environment': icon = 'weather.png'; break; +} +return icon; +} +function effect_load_script(url) { +Debug.trace('api', 'Loading script: ' + url); +load_script(url); +} +function effect_api_get_ie(cmd, params, userData) { +if (!session.api_state_ie) session.api_state_ie = {}; +var unique_id = get_unique_id(); +session.api_state_ie[unique_id] = userData; +params.format = 'js'; +params.onafter = 'effect_api_response_ie(' + unique_id + ', response);'; +var url = '/effect/api/' + cmd + composeQueryString(params); +Debug.trace('api', "Sending MSIE HTTP GET: " + url); +load_script(url); +} +function effect_api_response_ie(unique_id, tree) { +Debug.trace('api', "Got response from MSIE HTTP GET"); +var tx = session.api_state_ie[unique_id]; +delete session.api_state_ie[unique_id]; +if (tree.Code == 'session') { +do_logout_2(); +return; +} +if (tree.Code == 'access') { +do_notice("Access Denied", tree.Description, 'do_not_pass_go'); +return; +} +if (tree.Code != 0) { +if (tx._on_error) return fire_callback( tx._on_error, tree, tx ); +return do_error( tree.Description ); +} +if (tree.SessionID) { +if (tree.SessionID == '_DELETE_') { +delete session.cookie.tree.effect_session_id; +} +else { +session.cookie.set( 'effect_session_id', tree.SessionID ); +} +session.cookie.save(); +} +if (tx._api_callback) { +fire_callback( tx._api_callback, tree, tx ); +} +} +function effect_api_get(cmd, params, callback, userData) { +if (!userData) userData = {}; +userData._api_callback = callback; +if (!session.api_mod_cache[cmd] && session.username) session.api_mod_cache[cmd] = hires_time_now(); +if (!params.mod && session.api_mod_cache[cmd]) params.mod = session.api_mod_cache[cmd]; +if (ie) return effect_api_get_ie(cmd, params, userData); +var url = '/effect/api/' + cmd + composeQueryString(params); +Debug.trace('api', "Sending HTTP GET: " + url); +ajax.get( url, 'effect_api_response', userData ); +} +function effect_api_send(cmd, xml, callback, userData) { +if (!userData) userData = {}; +userData._api_callback = callback; +var data = compose_xml('EffectRequest', xml); +Debug.trace('api', "Sending API Command: " + cmd + ": " + data); +ajax.send({ +method: 'POST', +url: '/effect/api/' + cmd, +data: data, +headers: { 'Content-Type': 'text/xml' } +}, 'effect_api_response', userData); +} +function effect_api_response(tx) { +Debug.trace('api', "HTTP " + tx.response.code + ": " + tx.response.data); +if (tx.response.code == 999) { +if (tx.request._auto_retry) { +session.net_error = false; +show_progress_dialog(1, "Trying to reestablish connection..."); +session.net_error = true; +setTimeout( function() { ajax.send(tx.request); }, 1000 ); +return; +} +else return do_error( "HTTP ERROR: " + tx.response.code + ": " + tx.response.data + ' (URL: ' + tx.request.url + ')' ); +} +if (session.net_error) { +hide_progress_dialog(); +session.net_error = false; +} +if (tx.response.code != 200) { +if (tx._silent) return; +else return do_error( "HTTP ERROR: " + tx.response.code + ": " + tx.response.data + ' (URL: ' + tx.request.url + ')' ); +} +var tree = null; +if (!tx._raw) { +var parser = new XML({ +preserveAttributes: true, +text: tx.response.data +}); +if (parser.getLastError()) return do_error("XML PARSE ERROR: " + parser.getLastError()); +tree = parser.getTree(); +if (tree.Code == 'session') { +do_logout_2(); +return; +} +if (tree.Code == 'access') { +do_notice("Access Denied", tree.Description, 'do_not_pass_go'); +return; +} +if (tree.Code != 0) { +if (tx._on_error) return fire_callback( tx._on_error, tree, tx ); +return do_error( tree.Description ); +} +if (tree.SessionID) { +if (tree.SessionID == '_DELETE_') { +delete session.cookie.tree.effect_session_id; +} +else { +session.cookie.set( 'effect_session_id', tree.SessionID ); +} +session.cookie.save(); +} +} +if (tx._api_callback) { +fire_callback( tx._api_callback, tree, tx ); +} +} +function effect_api_mod_touch() { +for (var idx = 0, len = arguments.length; idx < len; idx++) { +session.api_mod_cache[ arguments[idx] ] = hires_time_now(); +} +} +function do_not_pass_go() { +Nav.go('Main'); +} +var Nav = { +loc: '', +old_loc: '', +inited: false, +nodes: [], +init: function() { +if (!this.inited) { +this.inited = true; +this.loc = 'init'; +this.monitor(); +} +}, +monitor: function() { +var parts = window.location.href.split(/\#/); +var anchor = parts[1]; +if (!anchor) anchor = 'Main'; +var full_anchor = '' + anchor; +var sub_anchor = ''; +anchor = anchor.replace(/\%7C/, '|'); +if (anchor.match(/\|(\w+)$/)) { +sub_anchor = RegExp.$1.toLowerCase(); +anchor = anchor.replace(/\|(\w+)$/, ''); +} +if ((anchor != this.loc) && !anchor.match(/^_/)) { +Debug.trace('nav', "Caught navigation anchor: " + full_anchor); +var page_name = ''; +var page_args = null; +if (full_anchor.match(/^\w+\?.+/)) { +parts = full_anchor.split(/\?/); +page_name = parts[0]; +page_args = parseQueryString( parts[1] ); +} +else if (full_anchor.match(/^(\w+)\/(.*)$/)) { +page_name = RegExp.$1; +page_args = RegExp.$2; +} +else { +parts = full_anchor.split(/\//); +page_name = parts[0]; +page_args = parts.slice(1); +} +Debug.trace('nav', "Calling page: " + page_name + ": " + serialize(page_args)); +hide_popup_dialog(); +var result = page_manager.click( page_name, page_args ); +if (result) { +if (window.pageTracker && (this.loc != 'init')) { +setTimeout( function() { pageTracker._trackPageview('/effect/' + anchor); }, 1000 ); +} +this.old_loc = this.loc; +if (this.old_loc == 'init') this.old_loc = 'Main'; +this.loc = anchor; +} +else { +this.go( this.loc ); +} +} +else if (sub_anchor != this.sub_anchor) { +Debug.trace('nav', "Caught sub-anchor: " + sub_anchor); +$P().gosub( sub_anchor ); +} +this.sub_anchor = sub_anchor; +setTimeout( 'Nav.monitor()', 100 ); +}, +go: function(anchor, force) { +anchor = anchor.replace(/^\#/, ''); +if (force) this.loc = 'init'; +window.location.href = '#' + anchor; +}, +prev: function() { +this.go( this.old_loc || 'Main' ); +}, +refresh: function() { +this.loc = 'refresh'; +}, +bar: function() { +var nodes = arguments; +var html = ''; +for (var idx = 0, len = nodes.length; idx < len; idx++) { +var node = nodes[idx]; +if (node) this.nodes[idx] = node; +else node = this.nodes[idx]; +if (node != '_ignore_') { +html += ''; +} +} +html += '
'; +$('d_nav_bar').innerHTML = html; +}, +title: function(name) { +if (name) document.title = name + ' | EffectGames.com'; +else document.title = 'EffectGames.com'; +}, +currentAnchor: function() { +var parts = window.location.href.split(/\#/); +var anchor = parts[1] || ''; +var sub_anchor = ''; +anchor = anchor.replace(/\%7C/, '|'); +if (anchor.match(/\|(\w+)$/)) { +sub_anchor = RegExp.$1.toLowerCase(); +anchor = anchor.replace(/\|(\w+)$/, ''); +} +return anchor; +} +}; +var Blog = { +edit_caption: '
*Bold*  |Italic|  {monospace}  [http://link]  Formatting Guide...
', +search: function(args) { +if (!args.mode) args.mode = 'and'; +if (!args.offset) args.offset = 0; +if (!args.limit) args.limit = 10; +if (!args.format) args.format = 'xml'; +var query_args = copy_object( args ); +delete query_args.callback; +effect_api_get( 'article_search', query_args, [this, 'search_response'], { _search_args: args } ); +}, +get_article_preview: function(row, args) { +var html = ''; +Debug.trace('blog', 'Row: ' + dumper(row)); +html += '
'; +var ext_article_url = 'http://' + location.hostname + '/effect/article.psp.html' + row.Path + '/' + row.ArticleID; +var article_url = '#Article' + row.Path + '/' + row.ArticleID; +html += ''; +if (!args.title_only) { +html += '
'; +html += row.Preview; +html += '  ' + (args.link_title || 'Read Full Story...') + ''; +html += '
'; +html += ''; +html += '
'; +var elem_class = args.footer_element_class || 'blog_preview_footer_element'; +if ((session.username == row.Username) || is_admin()) { +html += '
' + +icon('page_white_edit.png', "Edit", '#ArticleEdit?path=' + row.Path + '&id=' + row.ArticleID) + '
'; +} +html += '
' + get_user_display(row.Username) + '
'; +html += '
' + icon('calendar', get_short_date_time(row.Published)) + '
'; +html += '
' + icon('talk', row.Comments) + '
'; +if (0 && row.Tags) html += '
' + icon('note.png', make_tag_links(row.Tags, 3)) + '
'; +html += '
' + icon('facebook.png', 'Facebook', "window.open('http://www.facebook.com/sharer.php?u="+encodeURIComponent(ext_article_url)+'&t='+encodeURIComponent(row.Title)+"','sharer','toolbar=0,status=0,width=626,height=436')", "Share on Facebook") + '
'; +html += '
' + icon('twitter.png', 'Twitter', "window.open('http://twitter.com/home?status=Reading%20" + encodeURIComponent(row.Title) + "%3A%20" + encodeURIComponent(ext_article_url)+"')", "Share on Twitter") + '
'; +html += '
'; +html += '
'; +html += '
'; +} +html += '
'; +return html; +}, +search_response: function(response, tx) { +var args = tx._search_args; +if (args.callback) return fire_callback(args.callback, response, args); +var div = $(args.target); +assert(div, "Could not find target DIV: " + args.target); +var html = ''; +if (response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +html += this.get_article_preview( row, args ); +} +if (args.more && (rows.length == args.limit)) { +html += large_icon_button('page_white_put.png', 'More...', "Blog.more(this, "+encode_object(args)+")") + '
'; +html += spacer(1,15) + '
'; +} +if (args.after) html += args.after; +} +else if (response.Code != 0) { +html = 'Search Error: ' . response.Code + ': ' + response.Description; +} +else { +html = args.none_found_msg || 'No articles found.'; +} +div.innerHTML = html; +}, +more: function(div, args) { +args.offset += args.limit; +Debug.trace('blog', "More Args: " + dumper(args)); +div.innerHTML = ''; +effect_api_get( 'article_search', args, [this, 'more_response'], { _search_args: args, _div: div } ); +}, +more_response: function(response, tx) { +var args = tx._search_args; +var button = tx._div; +var html = ''; +if (response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +html += this.get_article_preview( row, args ); +} +if (args.more && (rows.length == args.limit)) { +html += large_icon_button('page_white_put.png', 'More...', "Blog.more(this, "+encode_object(args)+")") + '
'; +html += spacer(1,15) + '
'; +} +} +else if (response.Code != 0) { +html = 'Search Error: ' . response.Code + ': ' + response.Description; +} +else { +html = args.none_found_msg || 'No more articles found.'; +} +var div = document.createElement('div'); +div.innerHTML = html; +button.parentNode.replaceChild( div, button ); +} +}; +function make_tag_links(csv, max, base_url) { +if (!base_url) base_url = ''; +var tags = csv.split(/\,\s*/); +var append = ''; +if (max && (tags.length > max)) { +tags.length = max; +append = '...'; +} +var html = ''; +for (var idx = 0, len = tags.length; idx < len; idx++) { +html += ''+tags[idx]+''; +if (idx < len - 1) html += ', '; +} +html += append; +return html; +} +function get_url_friendly_title(title) { +title = title.toString().replace(/\W+/g, '_'); +if (title.length > 40) title = title.substring(0, 40); +title = title.replace(/^_+/, ''); +title = title.replace(/_+$/, ''); +return title; +} +function get_full_url(url) { +if (url.match(/^\#/)) { +var parts = window.location.href.split(/\#/); +url = parts[0] + url; +} +return url; +} +var Comments = { +comments_per_page: 10, +get: function(page_id) { +var html = ''; +html += '
'; +html += '
Comments'; +html += '
'; +html += '
'; +html += '
'; +setTimeout( function() { Comments.search({ page_id: page_id }); }, 1 ); +return html; +}, +search: function(args) { +if (!args.limit) args.limit = this.comments_per_page; +if (!args.offset) args.offset = 0; +assert(args.page_id, "Comments.search: No page_id specified"); +args.format = 'xml'; +this.last_search = args; +effect_api_get( 'comments_get', args, [this, 'search_response'], { _search_args: args } ); +}, +research: function(offset) { +var args = this.last_search; +if (!args) return; +args.offset = offset; +effect_api_get( 'comments_get', args, [this, 'search_response'], { _search_args: args } ); +}, +search_response: function(response, tx) { +this.comments = []; +var args = tx._search_args; +if (args.callback) return fire_callback(args.callback, response, args); +var html = ''; +html += '
' + +large_icon_button( 'comment_edit.png', 'Post Comment...', "Comments.add('"+args.page_id+"')" ) + '
'; +if (args.page_id.match(/^Article\//)) { +html += '
' + icon('feed.png', 'RSS', '/effect/api/comment_feed/' + args.page_id + '.rss', 'Comments RSS Feed') + '
'; +} +if (response.Items && response.Items.Item && response.List && response.List.length) { +html += ''; +html += '
'; +var items = this.comments = always_array( response.Items.Item ); +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var extra_classes = (args.highlight && (args.highlight == item.ID)) ? ' highlight' : ''; +html += '
'; +html += '
'; +if (item.Username) html += ''; +html += '' + item.Name.toString().toUpperCase() + ''; +if (item.Username) html += ''; +html += ', ' + get_short_date_time(item.Date) + '
'; +html += '
'; +html += this.get_comment_controls( args.page_id, item ); +html += '
'; +html += '
'; +html += '
' + item.Comment + '
'; +html += '
'; +html += ''; +if (item.LastReply && ((item.LastReply >= time_now() - (86400 * 7)) || (session.username && (session.username == item.Username)))) { +setTimeout( "Comments.show_replies('"+args.page_id+"','"+item.ID+"')", 1 ); +} +} +} +else { +} +$( 'd_comments_' + args.page_id ).innerHTML = html; +}, +get_control: function(icon, code, text, status_text) { +if (!icon.match(/\.\w+$/)) icon += '.gif'; +return '' + code_link(code, text, status_text) + ''; +}, +get_comment_controls: function(page_id, comment) { +var html = ''; +var spacer_txt = '  |  '; +if (session.user) { +html += this.get_control('comment', "Comments.reply('"+page_id+"','"+comment.ID+"')", 'Reply') + spacer_txt; +} +if (comment.Replies) { +if (comment._replies_visible) html += this.get_control('magnify_minus', "Comments.hide_replies('"+page_id+"','"+comment.ID+"')", 'Hide Replies'); +else html += this.get_control('magnify_plus', "Comments.show_replies('"+page_id+"','"+comment.ID+"')", 'Show Replies ('+comment.Replies+')'); +if (session.user) html += spacer_txt; +} +if (session.user) { +html += this.get_control( +'star', +"Comments.like('"+page_id+"','"+comment.ID+"')", +'Like' + (comment.Like ? (' ('+comment.Like+')') : ''), +comment.Like ? (comment.Like + ' ' + ((comment.Like == 1) ? 'person likes this' : 'people like this')) : 'I like this comment' +) + spacer_txt; +if (is_admin()) html += this.get_control('trash', "Comments._delete('"+page_id+"','"+comment.ID+"')", 'Delete') + spacer_txt; +html += this.get_control('warning', "Comments.report('"+page_id+"','"+comment.ID+"')", 'Report Abuse'); +} +return html; +}, +reply: function(page_id, comment_id) { +hide_popup_dialog(); +delete session.progress; +var comment = find_object( this.comments, { ID: comment_id } ); +var html = ''; +html += '
'; +html += '\n \n \n \n \n \n \n \n \n \n '); + }, this); + __out.push('\n\n
\n
'; +html += '
Reply to Comment by "'+comment.Name+'"
'; +html += '
'; +var name = this.get_name(); +html += '

Posted by: ' + name; +if (!session.user) html += ' → Create Account'; +html += '


'; +html += ''; +html += Blog.edit_caption; +html += '
'; +html += '

'; +html += ''; +html += ''; +html += ''; +html += '
' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Reply', "Comments.post_reply('"+page_id+"','"+comment_id+"')") + '
'; +html += '
'; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_comment_body' ); +show_popup_dialog(600, 300, html); +}, +post_reply: function(page_id, comment_id) { +var value = $('fe_comment_body').value; +if (!value) return; +hide_popup_dialog(); +show_progress_dialog(1, "Posting reply..."); +var name = this.get_name(); +effect_api_mod_touch('comment_replies_get'); +effect_api_send('comment_post_reply', { +PageID: page_id, +CommentID: comment_id, +Username: session.username || '', +Name: name, +Comment: value, +PageURL: location.href +}, [this, 'post_reply_finish'], { _page_id: page_id, _comment_id: comment_id } ); +}, +post_reply_finish: function(response, tx) { +hide_popup_dialog(); +var page_id = tx._page_id; +var comment_id = tx._comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +do_message('success', "Comment reply posted successfully."); +this.show_replies(page_id, comment_id); +if (!comment.Replies) comment.Replies = 1; else comment.Replies++; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +show_replies: function(page_id, comment_id) { +var comment = find_object( this.comments, { ID: comment_id } ); +if (!comment._replies_visible) { +$('d_comment_replies_' + comment_id).show().innerHTML = ''; +} +var args = { page_id: page_id, comment_id: comment_id, offset: 0, limit: 100 }; +effect_api_get( 'comment_replies_get', args, [this, 'receive_replies_response'], { _search_args: args } ); +}, +receive_replies_response: function(response, tx) { +var page_id = tx._search_args.page_id; +var comment_id = tx._search_args.comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +var html = ''; +var replies = always_array( response.Items.Item ); +for (var idx = 0, len = replies.length; idx < len; idx++) { +var reply = replies[idx]; +html += get_chat_balloon( +(reply.Username == session.username) ? 'blue' : 'grey', +reply.Username, +reply.Comment.replace(/^]*?>(.+)<\/div>$/i, '$1') +); +} +$('d_comment_replies_' + comment_id).innerHTML = html; +if (!comment._replies_visible) { +$('d_comment_replies_' + comment_id).hide(); +animate_div_visibility( 'd_comment_replies_' + comment_id, true ); +} +comment._replies_visible = true; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +hide_replies: function(page_id, comment_id) { +var comment = find_object( this.comments, { ID: comment_id } ); +if (comment._replies_visible) { +animate_div_visibility( 'd_comment_replies_' + comment_id, false ); +comment._replies_visible = false; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +} +}, +like: function(page_id, comment_id) { +effect_api_mod_touch('comments_get'); +effect_api_send('comment_like', { +PageID: page_id, +CommentID: comment_id +}, [this, 'like_finish'], { _page_id: page_id, _comment_id: comment_id, _on_error: [this, 'like_error'] } ); +}, +like_error: function(response, tx) { +if (response.Code == 'comment_already_like') do_message('error', "You already like this comment."); +else do_error( response.Description ); +}, +like_finish: function(resopnse, tx) { +var page_id = tx._page_id; +var comment_id = tx._comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +do_message('success', "You now like this comment."); +if (!comment.Like) comment.Like = 1; else comment.Like++; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +add: function(page_id) { +hide_popup_dialog(); +delete session.progress; +var html = ''; +html += '
'; +html += '", "" ], + legend: [ 1, "
", "
" ], + thead: [ 1, "
'; +html += '
Post New Comment
'; +html += '
'; +var name = this.get_name(); +html += '

Posted by: ' + name; +if (!session.user) html += ' → Create Account'; +html += '


'; +html += ''; +html += Blog.edit_caption; +html += '
'; +html += '

'; +html += ''; +html += ''; +html += ''; +html += '
' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Comment', "Comments.post('"+page_id+"')") + '
'; +html += '
'; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_comment_body' ); +show_popup_dialog(600, 300, html); +}, +report: function(page_id, comment_id) { +if (confirm('Are you sure you want to report this comment to the site administrators as abusive and/or spam?')) { +effect_api_send('comment_report_abuse', { +PageID: page_id, +CommentID: comment_id +}, [this, 'report_finish'], { _page_id: page_id, _comment_id: comment_id } ); +} +}, +report_finish: function(response, tx) { +do_message('success', 'Your abuse report has been received, and will be evaluated by the site administrators.'); +}, +_delete: function(page_id, comment_id) { +if (confirm('Are you sure you want to permanently delete this comment?')) { +effect_api_mod_touch('comments_get'); +effect_api_send('comment_delete', { +PageID: page_id, +CommentID: comment_id +}, [this, 'delete_finish'], { _page_id: page_id, _comment_id: comment_id } ); +} +}, +delete_finish: function(response, tx) { +do_message('success', 'The comment was deleted successfully.'); +var page_id = tx._page_id; +this.search({ page_id: page_id }); +}, +get_name: function() { +var name = '(Anonymous)'; +if (session.user) { +if (get_bool_pref('public_profile')) name = session.user.FullName; +else name = session.username; +} +return name; +}, +post: function(page_id) { +var value = $('fe_comment_body').value; +if (!value) return; +hide_popup_dialog(); +show_progress_dialog(1, "Posting comment..."); +var name = this.get_name(); +effect_api_mod_touch('comments_get'); +effect_api_send('comment_post', { +PageID: page_id, +Username: session.username || '', +Name: name, +Comment: value +}, [this, 'post_finish'], { _page_id: page_id } ); +}, +post_finish: function(response, tx) { +hide_popup_dialog(); +var comment_id = response.CommentID; +var page_id = tx._page_id; +this.search({ page_id: page_id, highlight: comment_id }); +} +}; +Class.create( 'Menu', { +id: '', +menu: null, +__construct: function(id) { +this.id = id; +}, +load: function() { +if (!this.menu) { +this.menu = $(this.id); +assert( !!this.menu, "Could not locate DOM element: " + this.id ); +} +}, +get_value: function() { +this.load(); +return this.menu.options[this.menu.selectedIndex].value; +}, +set_value: function(value, auto_add) { +value = str_value(value); +this.load(); +for (var idx = 0, len = this.menu.options.length; idx < len; idx++) { +if (this.menu.options[idx].value == value) { +this.menu.selectedIndex = idx; +return true; +} +} +if (auto_add) { +this.menu.options[this.menu.options.length] = new Option(value, value); +this.menu.selectedIndex = this.menu.options.length - 1; +return true; +} +return false; +}, +disable: function() { +this.load(); +this.menu.disabled = true; +this.menu.setAttribute( 'disabled', 'disabled' ); +}, +enable: function() { +this.load(); +this.menu.setAttribute( 'disabled', '' ); +this.menu.disabled = false; +}, +populate: function(items, sel_value) { +this.load(); +this.menu.options.length = 0; +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var item_name = ''; +var item_value = ''; +if (isa_hash(item)) { +item_name = item.label; +item_value = item.data; +} +else if (isa_array(item)) { +item_name = item[0]; +item_value = item[1]; +} +else { +item_name = item_value = item; +} +this.menu.options[ this.menu.options.length ] = new Option( item_name, item_value ); +if (item_value == sel_value) this.menu.selectedIndex = idx; +} +} +} ); +Class.subclass( Menu, 'MultiMenu', { +__static: { +toggle_type: function(id) { +var menu = $(id); +assert(menu, "Could not find menu in DOM: " + id); +if (menu.disabled) return; +var obj = MenuManager.find(id); +assert(obj, "Could not find menu in MenuManager: " + id); +var div = $( 'd_inner_' + id ); +var ic = $( 'ic_' + id ); +var is_multiple = (ic.src.indexOf('contract') > -1); +obj.multi = !is_multiple; +var multiple_tag = !is_multiple ? +' multiple="multiple" size=5' : ''; +var items = []; +for (var idx = 0; idx < menu.options.length; idx++) { +var option = menu.options[idx]; +array_push( items, { +value: option.value, +text: option.text, +selected: option.selected +}); +} +var html = ''; +html += ''; +div.innerHTML = html; +ic.src = images_uri + '/menu_' + (is_multiple ? 'expand' : 'contract') + '.gif'; +obj.menu = null; +} +}, +attribs: null, +multi: false, +toggle: true, +__construct: function(id, attribs) { +this.id = id; +if (attribs) this.attribs = attribs; +}, +get_html: function(items, selected_csv, attribs) { +if (!items) items = []; +if (!selected_csv) selected_csv = ''; +if (attribs) this.attribs = attribs; +var selected = csv_to_hash(selected_csv); +this.menu = null; +if (num_keys(selected) > 1) this.multi = true; +var html = '
'; +html += ''; +html += ''; +html += ''; +if (this.toggle) html += ''; +html += '
' + spacer(1,1) + '
'+spacer(1,2)+'
'; +html += '
'; +return html; +}, +get_value: function() { +this.load(); +var value = ''; +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +if (option.selected && option.value.length) { +if (value.length > 0) value += ','; +value += option.value; +} +} +return value; +}, +set_value: function(value, auto_add) { +value = '' + value; +this.load(); +if (!value) { +value = ''; +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +option.selected = (option.value == value); +} +return; +} +var selected = csv_to_hash(value); +if ((num_keys(selected) > 1) && !this.multi) { +MultiMenu.toggle_type(this.id); +var self = this; +setTimeout( function() { +self.set_value(value, auto_add); +}, 1 ); +return; +} +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +option.selected = selected[option.value] ? true : false; +} +}, +populate: function(items, value) { +this.load(); +this.menu.options.length = 0; +if (!value) value = ''; +var selected = csv_to_hash(value); +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var item_name = ''; +var item_value = ''; +if (isa_hash(item)) { +item_name = item.label; +item_value = item.data; +} +else if (isa_array(item)) { +item_name = item[0]; +item_value = item[1]; +} +else { +item_name = item_value = item; +} +var opt = new Option( item_name, item_value ); +this.menu.options[ this.menu.options.length ] = opt; +opt.selected = selected[item_value] ? true : false; +} +}, +collapse: function() { +if (this.multi) MultiMenu.toggle_type(this.id); +}, +expand: function() { +if (!this.multi) MultiMenu.toggle_type(this.id); +} +} ); +Class.create( 'MenuManager', { +__static: { +menus: {}, +register: function(menu) { +this.menus[ menu.id ] = menu; +return menu; +}, +find: function(id) { +return this.menus[id]; +} +} +} ); +Class.create( 'GrowlManager', { +lifetime: 10, +marginRight: 0, +marginTop: 0, +__construct: function() { +this.growls = []; +}, +growl: function(type, msg) { +if (find_object(this.growls, { type: type, msg: msg })) return; +var div = $(document.createElement('div')); +div.className = 'growl_message ' + type; +div.setOpacity(0.0); +div.innerHTML = '
' + msg + '
' + spacer(1,5) + '
'; +$('d_growl_wrapper').insertBefore( div, $('d_growl_top').nextSibling ); +var growl = { id:get_unique_id(), type: type, msg: msg, opacity:0.0, start:hires_time_now(), div:div }; +this.growls.push(growl); +this.handle_resize(); +this.animate(growl); +var self = this; +div.onclick = function() { +delete_object(self.growls, { id: growl.id }); +$('d_growl_wrapper').removeChild( div ); +}; +}, +animate: function(growl) { +if (growl.deleted) return; +var now = hires_time_now(); +var div = growl.div; +if (now - growl.start <= 0.5) { +div.setOpacity( tweenFrame(0.0, 1.0, (now - growl.start) * 2, 'EaseOut', 'Quadratic') ); +} +else if (now - growl.start <= this.lifetime) { +if (!growl._fully_opaque) { +div.setOpacity( 1.0 ); +growl._fully_opaque = true; +} +} +else if (now - growl.start <= this.lifetime + 1.0) { +div.setOpacity( tweenFrame(1.0, 0.0, (now - growl.start) - this.lifetime, 'EaseOut', 'Quadratic') ); +} +else { +delete_object(this.growls, { id: growl.id }); +$('d_growl_wrapper').removeChild( div ); +return; +} +var self = this; +setTimeout( function() { self.animate(growl); }, 33 ); +}, +handle_resize: function() { +var div = $('d_growl_wrapper'); +if (this.growls.length) { +var size = getInnerWindowSize(); +div.style.top = '' + (10 + this.marginTop) + 'px'; +div.style.left = '' + Math.floor((size.width - 310) - this.marginRight) + 'px'; +} +else { +div.style.left = '-2000px'; +} +} +} ); +window.$GR = new GrowlManager(); +if (window.addEventListener) { +window.addEventListener( "resize", function() { +$GR.handle_resize(); +}, false ); +} +else if (window.attachEvent && !ie6) { +window.attachEvent("onresize", function() { +$GR.handle_resize(); +}); +} +Class.create( 'Effect.Page', { +ID: '', +data: null, +active: false, +__construct: function(config) { +if (!config) return; +this.data = {}; +if (!config) config = {}; +for (var key in config) this[key] = config[key]; +this.div = $('page_' + this.ID); +assert(this.div, "Cannot find page div: page_" + this.ID); +}, +onInit: function() { +}, +onActivate: function() { +return true; +}, +onDeactivate: function() { +return true; +}, +show: function() { +this.div.show(); +}, +hide: function() { +this.div.hide(); +}, +gosub: function(anchor) { +} +} ); +Class.require( 'Effect.Page' ); +Class.create( 'Effect.PageManager', { +pages: null, +current_page_id: '', +on_demand: {}, +__construct: function(page_list) { +this.pages = []; +this.page_list = page_list; +for (var idx = 0, len = page_list.length; idx < len; idx++) { +Debug.trace( 'page', "Initializing page: " + page_list[idx].ID ); +if (Effect.Page[ page_list[idx].ID ]) { +var page = new Effect.Page[ page_list[idx].ID ]( page_list[idx] ); +page.onInit(); +this.pages.push(page); +} +else { +Debug.trace( 'page', 'Page ' + page_list[idx].ID + ' will be loaded on-demand' ); +} +} +}, +find: function(id) { +var page = find_object( this.pages, { ID: id } ); +if (!page) Debug.trace('PageManager', "Could not find page: " + id); +return page; +}, +notify_load: function(file, id) { +for (var idx = 0, len = this.page_list.length; idx < len; idx++) { +var page_config = this.page_list[idx]; +if (page_config.File == file) { +Debug.trace( 'page', "Initializing page on-demand: " + page_config.ID ); +var page = new Effect.Page[ page_config.ID ]( page_config ); +page.onInit(); +this.pages.push(page); +} +} +var self = this; +setTimeout( function() { +var result = self.activate(id, self.temp_args); +delete self.temp_args; +$('d_page_loading').hide(); +if (!result) { +$('page_'+id).hide(); +self.current_page_id = ''; +} +}, 1 ); +}, +activate: function(id, args) { +if (!find_object( this.pages, { ID: id } )) { +var page_config = find_object( this.page_list, { ID: id } ); +assert(!!page_config, "Page config not found: " + id ); +Debug.trace('page', "Loading file on-demand: " + page_config.File + " for page: " + id); +var url = '/effect/api/load_page/' + page_config.File + '?onafter=' + escape('page_manager.notify_load(\''+page_config.File+'\',\''+id+'\')'); +if (page_config.Requires) { +var files = page_config.Requires.split(/\,\s*/); +for (var idx = 0, len = files.length; idx < len; idx++) { +var filename = files[idx]; +if (!this.on_demand[filename]) { +Debug.trace('page', "Also loading file: " + filename); +url += '&file=' + filename; +this.on_demand[filename] = 1; +} +} +} +$('d_page_loading').show(); +this.temp_args = args; +load_script( url ); +return true; +} +$('page_'+id).show(); +var page = this.find(id); +page.active = true; +if (!args) args = []; +if (!isa_array(args)) args = [ args ]; +var result = page.onActivate.apply(page, args); +if (typeof(result) == 'boolean') return result; +else return alert("Page " + id + " onActivate did not return a boolean!"); +}, +deactivate: function(id, new_id) { +var page = this.find(id); +var result = page.onDeactivate(new_id); +if (result) { +$('page_'+id).hide(); +page.active = false; +} +return result; +}, +click: function(id, args) { +Debug.trace('page', "Switching pages to: " + id); +var old_id = this.current_page_id; +if (this.current_page_id) { +var result = this.deactivate( this.current_page_id, id ); +if (!result) return false; +} +this.current_page_id = id; +this.old_page_id = old_id; +window.scrollTo( 0, 0 ); +var result = this.activate(id, args); +if (!result) { +$('page_'+id).hide(); +this.current_page_id = ''; +} +return true; +} +} ); +Class.subclass( Effect.Page, "Effect.Page.Main", { +inited: false, +onActivate: function() { +Nav.bar( ['Main', 'EffectGames.com'] ); +Nav.title(''); +$('d_blog_news').innerHTML = loading_image(); +$('d_blog_community').innerHTML = loading_image(); +$('d_blog_featured').innerHTML = loading_image(); +Blog.search({ +stag: 'featured_game', +limit: 4, +full: 1, +callback: [this, 'receive_featured_games'] +}); +effect_api_get( 'get_site_info', { cat: 'pop_pub_games' }, [this, 'receive_pop_pub_games'], { } ); +Blog.search({ +stag: 'front_page', +limit: 5, +target: 'd_blog_news', +more: 1 +}); +Blog.search({ +path: '/community', +limit: 5, +target: 'd_blog_community', +more: 1 +}); +if (!this.inited) { +this.inited = true; +config.Strings.MainSlideshow.Slide = always_array( config.Strings.MainSlideshow.Slide ); +this.slide_idx = 0; +this.num_slides = config.Strings.MainSlideshow.Slide.length; +this.slide_div_num = 0; +this.slide_dir = 1; +this.bk_pos = -340; +this.bk_pos_target = -340; +this.slide_images = []; +for (var idx = 0, len = this.num_slides; idx < len; idx++) { +var url = images_uri + '/' + config.Strings.MainSlideshow.Slide[idx].Photo; +this.slide_images[idx] = new Image(); +this.slide_images[idx].src = png(url, true); +} +} +this.height_target = 470; +this.height_start = $('d_header').offsetHeight; +this.time_start = hires_time_now(); +this.duration = 0.75; +if (!this.timer) this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +if (session.user) $('d_blurb_main').hide(); +else { +$('d_blurb_main').innerHTML = get_string('/Main/Blurb'); +$('d_blurb_main').show(); +} +return true; +}, +receive_pop_pub_games: function(response, tx) { +var html = ''; +if (response.Data && response.Data.Games && response.Data.Games.Game) { +var games = always_array( response.Data.Games.Game ); +for (var idx = 0, len = Math.min(games.length, 16); idx < len; idx++) { +var game = games[idx]; +html += '
' + +(game.Logo ? +user_image_thumbnail(game.Logo, 80, 60) : +'' +) + '
' + ww_fit_box(game.Title, 80, 2, session.em_width, 1) + '
'; +} +html += '
'; +} +else { +html += 'No active public games found! Why not create a new one?'; +} +$('d_main_pop_pub_games').innerHTML = html; +}, +receive_featured_games: function(response, tx) { +var html = ''; +if (response.Rows && response.Rows.Row) { +html += ''; +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +var image_url = row.Params.featured_image; +if (image_url && image_url.match(/^(\w+)\/(\w+\.\w+)$/)) { +image_url = '/effect/api/view/users/' + RegExp.$1 + '/images/' + RegExp.$2; +} +if (idx % 2 == 0) html += ''; +html += ''; +if (idx % 2 == 1) html += ''; +} +if (rows.length % 2 == 1) { +html += ''; +html += ''; +} +html += '
'; +html += ''; +html += ''; +html += ''; +html += ''; +html += ''; +html += '
'; +html += ''; +html += '' + spacer(10,1) + ''; +html += ''; +html += ''; +html += '' + spacer(15,1) + '
'; +html += spacer(1,20); +html += '
'; +} +$('d_blog_featured').innerHTML = html; +}, +animate_mhs: function() { +var now = hires_time_now(); +if (now - this.time_start >= this.duration) { +$('d_header').style.height = '' + this.height_target + 'px'; +$('d_shadow').style.height = '' + this.height_target + 'px'; +delete this.timer; +} +else { +var height = tweenFrame(this.height_start, this.height_target, (now - this.time_start) / this.duration, 'EaseOut', 'Circular'); +$('d_header').style.height = '' + height + 'px'; +$('d_shadow').style.height = '' + height + 'px'; +this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +} +}, +onDeactivate: function() { +$('d_blog_news').innerHTML = ''; +$('d_blog_community').innerHTML = ''; +this.height_target = 75; +this.height_start = $('d_header').offsetHeight; +this.time_start = hires_time_now(); +if (!this.timer) this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +return true; +}, +draw_slide: function() { +if (this.slide_timer) return; +var slide = config.Strings.MainSlideshow.Slide[ this.slide_idx ]; +this.old_photo = $('d_header_slideshow_photo_' + this.slide_div_num); +this.old_text = $('d_header_slideshow_text_' + this.slide_div_num); +this.slide_div_num = 1 - this.slide_div_num; +this.new_photo = $('d_header_slideshow_photo_' + this.slide_div_num); +this.new_text = $('d_header_slideshow_text_' + this.slide_div_num); +this.new_photo.style.backgroundImage = 'url('+png(images_uri+'/'+slide.Photo, true)+')'; +this.new_photo.setOpacity(0.0); +var html = ''; +html += slide.Text; +this.slide_width = this.new_text.offsetWidth; +this.new_text.innerHTML = html; +if (this.slide_dir == 1) this.new_text.style.left = '' + this.slide_width + 'px'; +else this.new_text.style.left = '-' + this.slide_width + 'px'; +this.slide_time_start = hires_time_now(); +this.slide_timer = setTimeout( '$P("Main").animate_mhs_slide()', 33 ); +}, +animate_mhs_slide: function() { +var now = hires_time_now(); +if (now - this.slide_time_start >= this.duration) { +this.new_text.style.left = '0px'; +this.old_text.style.left = '-' + this.slide_width + 'px'; +this.new_photo.setOpacity( 1.0 ); +this.old_photo.setOpacity( 0.0 ); +delete this.slide_timer; +this.bk_pos = this.bk_pos_target; +} +else { +var value = tweenFrame(0.0, 1.0, (now - this.slide_time_start) / this.duration, 'EaseOut', 'Circular'); +if (this.slide_dir == 1) { +this.new_text.style.left = '' + Math.floor( this.slide_width - (this.slide_width * value) ) + 'px'; +this.old_text.style.left = '-' + Math.floor( this.slide_width * value ) + 'px'; +} +else { +this.new_text.style.left = '-' + Math.floor( this.slide_width - (this.slide_width * value) ) + 'px'; +this.old_text.style.left = '' + Math.floor( this.slide_width * value ) + 'px'; +} +this.new_photo.setOpacity( value ); +this.old_photo.setOpacity( 1.0 - value ); +var bkp = Math.floor( this.bk_pos + ((this.bk_pos_target - this.bk_pos) * value) ); +$('d_header').style.backgroundPosition = '' + bkp + 'px 0px'; +this.slide_timer = setTimeout( '$P("Main").animate_mhs_slide()', 33 ); +} +}, +prev_slide: function() { +this.bk_pos_target += 200; +this.slide_idx--; +if (this.slide_idx < 0) this.slide_idx += this.num_slides; +this.slide_dir = -1; +this.draw_slide(); +}, +next_slide: function() { +this.bk_pos_target -= 200; +this.slide_idx++; +if (this.slide_idx >= this.num_slides) this.slide_idx -= this.num_slides; +this.slide_dir = 1; +this.draw_slide(); +} +} ); +Class.subclass( Effect.Page, "Effect.Page.PublicGameList", { +onActivate: function() { +Nav.bar( +['Main', 'EffectGames.com'], +['PublicGameList', "All Public Games"] +); +Nav.title( "List of All Public Game Projects" ); +effect_api_get( 'get_site_info', { cat: 'all_pub_games' }, [this, 'receive_all_pub_games'], { } ); +this.div.innerHTML = loading_image(); +return true; +}, +onDeactivate: function() { +this.div.innerHTML = ''; +return true; +}, +receive_all_pub_games: function(response, tx) { +var html = ''; +html += '

List of All Public Game Projects

'; +html += '
This is the complete list of public games currently being built by our users, presented in alphabetical order. Maybe they could use some help! Check out the game project pages and see (requires user account).
'; +if (response.Data && response.Data.Games && response.Data.Games.Game) { +var games = always_array( response.Data.Games.Game ); +for (var idx = 0, len = games.length; idx < len; idx++) { +var game = games[idx]; +html += '
' + +(game.Logo ? +user_image_thumbnail(game.Logo, 80, 60) : +'' +) + '
' + ww_fit_box(game.Title, 80, 2, session.em_width, 1) + '
'; +} +html += '
'; +} +else { +html += 'No public games found! Why not create a new one?'; +} +this.div.innerHTML = html; +} +} ); +Class.subclass( Effect.Page, "Effect.Page.Search", { +onActivate: function(args) { +if (!args) args = {}; +var search_text = args.q; +var start = args.s || 0; +if (!start) start = 0; +var title = 'Search results for "'+search_text+'"'; +Nav.bar( +['Main', 'EffectGames.com'], +['Search?q=' + escape(search_text), "Search Results"] +); +Nav.title( title ); +this.last_search_text = search_text; +$('d_article_search').innerHTML = loading_image(); +load_script( 'http://www.google.com/uds/GwebSearch?callback=receive_google_search_results&context=0&lstkp=0&rsz=large&hl=en&source=gsc&gss=.com&sig=&q='+escape(search_text)+'%20site%3Ahttp%3A%2F%2Fwww.effectgames.com%2F&key=notsupplied&v=1.0&start='+start+'&nocache=' + (new Date()).getTime() ); +$('h_article_search').innerHTML = title; +return true; +}, +onDeactivate: function(new_page) { +$('fe_search_bar').value = ''; +$('d_article_search').innerHTML = ''; +return true; +} +} ); +function do_search_bar() { +var search_text = $('fe_search_bar').value; +if (search_text.length) { +Nav.go('Search?q=' + escape(search_text)); +} +} +function receive_google_search_results(context, response) { +var html = ''; +html += '
Powered by
'; +if (response.results.length) { +for (var idx = 0, len = response.results.length; idx < len; idx++) { +var row = response.results[idx]; +var url = row.unescapedUrl.replace(/^.+article\.psp\.html/, '#Article'); +html += '
'; +html += ''; +html += '
' + row.content + '
'; +html += '
'; +} +} +else { +html += 'No results found.'; +} +if (response.cursor.pages) { +html += '
Page: '; +for (var idx = 0, len = response.cursor.pages.length; idx < len; idx++) { +html += ''; +var page = response.cursor.pages[idx]; +var url = '#Search?q=' + escape($P('Search').last_search_text) + '&s=' + page.start; +if (response.cursor.currentPageIndex != idx) html += ''; +else html += ''; +html += page.label; +if (response.cursor.currentPageIndex != idx) html += ''; +else html += ''; +html += ''; +} +html += '
'; +} +$('d_article_search').innerHTML = html; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js new file mode 100644 index 00000000..8b164a42 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js @@ -0,0 +1 @@ +exports.ZeParser = require('./ZeParser').ZeParser; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json new file mode 100644 index 00000000..90320447 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json @@ -0,0 +1,27 @@ +{ + "author": { + "name": "Peter van der Zee", + "url": "http://qfox.nl/" + }, + "name": "zeparser", + "description": "My JavaScript parser", + "version": "0.0.5", + "homepage": "https://github.com/qfox/ZeParser/", + "repository": { + "type": "git", + "url": "git://github.com/qfox/ZeParser.git" + }, + "main": "./index", + "engines": { + "node": "*" + }, + "dependencies": {}, + "devDependencies": {}, + "readme": "This is a JavaScript parser.\nhttp://github.com/qfox/ZeParser\n(c) Peter van der Zee\nhttp://qfox.nl\n\n\nBenchmark\nhttp://qfox.github.com/ZeParser/benchmark.html\n\nThe Tokenizer is used by the parser. The parser tells the tokenizer whether the next token may be a regular expression or not. Without the parser, the tokenizer will fail if regular expression literals are used in the input.\n\nUsage:\nZeParser.parse(input);\n\nReturns a \"parse tree\" which is a tree of an array of arrays with tokens (regular objects) as leafs. Meta information embedded as properties (of the arrays and the tokens).\n\nZeParser.createParser(input);\n\nReturns a new ZeParser instance which has already parsed the input. Amongst others, the ZeParser instance will have the properties .tree, .wtree and .btree.\n\n.tree is the parse tree mentioned above.\n.wtree (\"white\" tree) is a regular array with all the tokens encountered (including whitespace, line terminators and comments)\n.btree (\"black\" tree) is just like .wtree but without the whitespace, line terminators and comments. This is what the specification would call the \"token stream\".\n\nI'm aware that the naming convention is a bit awkward. It's a tradeoff between short and descriptive. The streams are used quite often in the analysis.\n\nTokens are regular objects with several properties. Amongst them are .tokposw and .tokposw, they correspond with their own position in the .wtree and .btree.\n\nThe parser has two modes for parsing: simple and extended. Simple mode is mainly for just parsing and returning the streams and a simple parse tree. There's not so much meta information here and this mode is mainly built for speed. The other mode has everything required for Zeon to do its job. This mode is toggled by the instance property .ast, which is true by default :)\n\nNon-factory example:\n\nvar input = \"foo\";\nvar tree = []; // this should probably be refactored away some day\nvar tokenizer = new Tokenizer(input); // dito\nvar parser = new ZeParser(input, tokenizer, tree);\nparser.parse(); // returns tree..., should never throw errors\n", + "readmeFilename": "README", + "bugs": { + "url": "https://github.com/qfox/ZeParser/issues" + }, + "_id": "zeparser@0.0.5", + "_from": "zeparser@0.0.5" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html new file mode 100755 index 00000000..1ff5ff43 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html @@ -0,0 +1,26 @@ + + + + Parser Test Suite Page + + + + (c) qfox.nl
+ Parser test suite
+
Running...
+ + + + + + + \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html new file mode 100755 index 00000000..0e0d1b1a --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html @@ -0,0 +1,23 @@ + + + + Tokenizer Test Suite Page + + + + (c) qfox.nl
+ + + + + + \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js new file mode 100644 index 00000000..8a4138be --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js @@ -0,0 +1,478 @@ +// tests for both the tokenizer and parser. Parser test results could be checked tighter. +// api: [input, token-output-count, ?regex-hints, desc] +// regex-hints are for tokenizer, will tell for each token whether it might parse regex or not (parser's job) +var Tests = [ + +["var abc;", 4, "Variable Declaration"], +["var abc = 5;", 8, "Variable Declaration, Assignment"], +["/* */", 1, "Block Comment"], +["/** **/", 1, "JSDoc-style Comment"], +["var f = function(){;};", 13, "Assignment, Function Expression"], +["hi; // moo", 4, "Trailing Line Comment"], +["hi; // moo\n;", 6, "Trailing Line Comment, Linefeed, `;`"], +["var varwithfunction;", 4, "Variable Declaration, Identifier Containing Reserved Words, `;`"], +["a + b;", 6, "Addition/Concatenation"], + +["'a'", 1, "Single-Quoted String"], +["'a';", 2, "Single-Quoted String, `;`"], // Taken from the parser test suite. + +["'a\\n'", 1, "Single-Quoted String With Escaped Linefeed"], +["'a\\n';", 2, "Single-Quoted String With Escaped Linefeed, `;`"], // Taken from the parser test suite. + +["\"a\"", 1, "Double-Quoted String"], +["\"a\";", 2, "Double-Quoted String, `;`"], // Taken from the parser test suite. + +["\"a\\n\"", 1, "Double-Quoted String With Escaped Linefeed"], +["\"a\\n\";", 2, "Double-Quoted String With Escaped Linefeed, `;`"], // Taken from the parser test suite. + +["500", 1, "Integer"], +["500;", 2, "Integer, `;`"], // Taken from the parser test suite. + +["500.", 1, "Double With Trailing Decimal Point"], +["500.;", 2, "Double With Trailing Decimal Point"], // Taken from the parser test suite. + +["500.432", 1, "Double With Decimal Component"], +["500.432;", 2, "Double With Decimal Component, `;`"], // Taken from the parser test suite. + +[".432432", 1, "Number, 0 < Double < 1"], +[".432432;", 2, "Number, 0 < Double < 1, `;`"], // Taken from the parser test suite. + +["(a,b,c)", 7, "Parentheses, Comma-separated identifiers"], +["(a,b,c);", 8, "Parentheses, Comma-separated identifiers, `;`"], // Taken from the parser test suite. + +["[1,2,abc]", 7, "Array literal"], +["[1,2,abc];", 8, "Array literal, `;`"], // Taken from the parser test suite. + +["{a:1,\"b\":2,c:c}", 13, "Object literal"], +["var o = {a:1,\"b\":2,c:c};", 20, "Assignment, Object Literal, `;`"], // Taken from the parser test suite. + +["var x;\nvar y;", 9, "2 Variable Declarations, Multiple lines"], +["var x;\nfunction n(){ }", 13, "Variable, Linefeed, Function Declaration"], +["var x;\nfunction n(abc){ }", 14, "Variable, Linefeed, Function Declaration With One Argument"], +["var x;\nfunction n(abc, def){ }", 17, "Variable, Linefeed, Function Declaration With Multiple Arguments"], +["function n(){ \"hello\"; }", 11, "Function Declaration, Body"], + +["/a/;", 2, [true, false], "RegExp Literal, `;`"], +["/a/b;", 2, [true, true], "RegExp Literal, Flags, `;`"], +["++x;", 3, "Unary Increment, Prefix, `;`"], +[" / /;", 3, [true, true, false], "RegExp, Leading Whitespace, `;`"], +["/ / / / /", 5, [true, false, false, false, true], "RegExp Containing One Space, Space, Division, Space, RegExp Containing One Space"], + +// Taken from the parser test suite. + +["\"var\";", 2, "Keyword String, `;`"], +["\"variable\";", 2, "String Beginning With Keyword, `;`"], +["\"somevariable\";", 2, "String Containing Keyword, `;`"], +["\"somevar\";", 2, "String Ending With Keyword, `;`"], + +["var varwithfunction;", 4, "Keywords should not be matched in identifiers"], + +["var o = {a:1};", 12, "Object Literal With Unquoted Property"], +["var o = {\"b\":2};", 12, "Object Literal With Quoted Property"], +["var o = {c:c};", 12, "Object Literal With Equivalent Property Name and Identifier"], + +["/a/ / /b/;", 6, [true, true, false, false, true, false], "RegExp, Division, RegExp, `;`"], +["a/b/c;", 6, "Triple Division (Identifier / Identifier / Identifier)"], + +["+function(){/regex/;};", 9, [false, false, false, false, false, true, false, false, false], "Unary `+` Operator, Function Expression Containing RegExp and Semicolon, `;`"], + +// Line Terminators. +["\r\n", 1, "CRLF Line Ending = 1 Linefeed"], +["\r", 1, "CR Line Ending = 1 Linefeed"], +["\n", 1, "LF Line Ending = 1 Linefeed"], +["\r\n\n\u2028\u2029\r", 5, "Various Line Terminators"], + +// Whitespace. +["a \t\u000b\u000c\u00a0\uFFFFb", 8, "Whitespace"], + +// Comments. +["//foo!@#^&$1234\nbar;", 4, "Line Comment, Linefeed, Identifier, `;`"], +["/* abcd!@#@$* { } && null*/;", 2, "Single-Line Block Comment, `;`"], +["/*foo\nbar*/;", 2, "Multi-Line Block Comment, `;`"], +["/*x*x*/;", 2, "Block Comment With Asterisks, `;`"], +["/**/;", 2, "Empty Comment, `;`"], + +// Identifiers. +["x;", 2, "Single-Character Identifier, `;`"], +["_x;", 2, "Identifier With Leading `_`, `;`"], +["xyz;", 2, "Identifier With Letters Only, `;`"], +["$x;", 2, "Identifier With Leading `$`, `;`"], +["x5;", 2, "Identifier With Number As Second Character, `;`"], +["x_y;", 2, "Identifier Containing `_`, `;`"], +["x+5;", 4, "Identifier, Binary `+` Operator, Identifier, `;`"], +["xyz123;", 2, "Alphanumeric Identifier, `;`"], +["x1y1z1;", 2, "Alternating Alphanumeric Identifier, `;`"], +["foo\\u00d8bar;", 2, "Identifier With Unicode Escape Sequence (`\\uXXXX`), `;`"], +["f\u00d8\u00d8bar;", 2, "Identifier With Embedded Unicode Character"], + +// Numbers. +["5;", 2, "Integer, `;`"], +["5.5;", 2, "Double, `;`"], +["0;", 2, "Integer Zero, `;`"], +["0.0;", 2, "Double Zero, `;`"], +["0.001;", 2, "0 < Decimalized Double < 1, `;`"], +["1.e2;", 2, "Integer With Decimal and Exponential Component (`e`), `;`"], +["1.e-2;", 2, "Integer With Decimal and Negative Exponential Component, `;`"], +["1.E2;", 2, "Integer With Decimal and Uppercase Exponential Component (`E`), `;`"], +["1.E-2;", 2, "Integer With Decimal and Uppercase Negative Exponential Component, `;`"], +[".5;", 2, "0 < Double < 1, `;`"], +[".5e3;", 2, "(0 < Double < 1) With Exponential Component"], +[".5e-3;", 2, "(0 < Double < 1) With Negative Exponential Component"], +["0.5e3;", 2, "(0 < Decimalized Double < 1) With Exponential Component"], +["55;", 2, "Two-Digit Integer, `;`"], +["123;", 2, "Three-Digit Integer, `;`"], +["55.55;", 2, "Two-Digit Double, `;`"], +["55.55e10;", 2, "Two-Digit Double With Exponential Component, `;`"], +["123.456;", 2, "Three-Digit Double, `;`"], +["1+e;", 4, "Additive Expression, `;`"], +["0x01;", 2, "Hexadecimal `1` With 1 Leading Zero, `;`"], +["0xcafe;", 2, "Hexadecimal `51966`, `;`"], +["0x12345678;", 2, "Hexadecimal `305419896`, `;`"], +["0x1234ABCD;", 2, "Hexadecimal `305441741` With Uppercase Letters, `;`"], +["0x0001;", 2, "Hexadecimal `1` with 3 Leading Zeros, `;`"], + +// Strings. +["\"foo\";", 2, "Multi-Character Double-Quoted String, `;`"], +["\"a\\n\";", 2, "Double-Quoted String Containing Linefeed, `;`"], +["\'foo\';", 2, "Single-Quoted String, `;`"], +["'a\\n';", 2, "Single-Quoted String Containing Linefeed, `;`"], +["\"x\";", 2, "Single-Character Double-Quoted String, `;`"], +["'';", 2, "Empty Single-Quoted String, `;`"], +["\"foo\\tbar\";", 2, "Double-Quoted String With Tab Character, `;`"], +["\"!@#$%^&*()_+{}[]\";", 2, "Double-Quoted String Containing Punctuators, `;`"], +["\"/*test*/\";", 2, "Double-Quoted String Containing Block Comment, `;`"], +["\"//test\";", 2, "Double-Quoted String Containing Line Comment, `;`"], +["\"\\\\\";", 2, "Double-Quoted String Containing Reverse Solidus, `;`"], +["\"\\u0001\";", 2, "Double-Quoted String Containing Numeric Unicode Escape Sequence, `;`"], +["\"\\uFEFF\";", 2, "Double-Quoted String Containing Alphanumeric Unicode Escape Sequence, `;`"], +["\"\\u10002\";", 2, "Double-Quoted String Containing 5-Digit Unicode Escape Sequence, `;`"], +["\"\\x55\";", 2, "Double-Quoted String Containing Hex Escape Sequence, `;`"], +["\"\\x55a\";", 2, "Double-Quoted String Containing Hex Escape Sequence and Additional Character, `;`"], +["\"a\\\\nb\";", 2, "Double-Quoted String Containing Escaped Linefeed, `;`"], +["\";\"", 1, "Double-Quoted String Containing `;`"], +["\"a\\\nb\";", 2, "Double-Quoted String Containing Reverse Solidus and Linefeed, `;`"], +["'\\\\'+ ''", 4, "Single-Quoted String Containing Reverse Solidus, `+`, Empty Single-Quoted String"], + +// `null`, `true`, and `false`. +["null;", 2, "`null`, `;`"], +["true;", 2, "`true`, `;`"], +["false;", 2, "`false`, `;`"], + +// RegExps +["/a/;", 2, [true, true], "Single-Character RegExp, `;`"], +["/abc/;", 2, [true, true], "Multi-Character RegExp, `;`"], +["/abc[a-z]*def/g;", 2, [true, true], "RegExp Containing Character Range and Quantifier, `;`"], +["/\\b/;", 2, [true, true], "RegExp Containing Control Character, `;`"], +["/[a-zA-Z]/;", 2, [true, true], "RegExp Containing Extended Character Range, `;`"], +["/foo(.*)/g;", 2, [true, false], "RegExp Containing Capturing Group and Quantifier, `;`"], + +// Array Literals. +["[];", 3, "Empty Array, `;`"], +["[\b\n\f\r\t\x20];", 9, "Array Containing Whitespace, `;`"], +["[1];", 4, "Array Containing 1 Element, `;`"], +["[1,2];", 6, "Array Containing 2 Elements, `;`"], +["[1,2,,];", 8, "Array Containing 2 Elisions, `;`"], +["[1,2,3];", 8, "Array Containing 3 Elements, `;`"], +["[1,2,3,,,];", 11, "Array Containing 3 Elisions, `;`"], + +// Object Literals. +["({x:5});", 8, "Object Literal Containing 1 Member; `;`"], +["({x:5,y:6});", 12, "Object Literal Containing 2 Members, `;`"], +["({x:5,});", 9, "Object Literal Containing 1 Member and Trailing Comma, `;`"], +["({if:5});", 8, "Object Literal Containing Reserved Word Property Name, `;`"], +["({ get x() {42;} });", 17, "Object Literal Containing Getter, `;`"], +["({ set y(a) {1;} });", 18, "Object Literal Containing Setter, `;`"], + +// Member Expressions. +["o.m;", 4, "Dot Member Accessor, `;`"], +["o['m'];", 5, "Square Bracket Member Accessor, `;`"], +["o['n']['m'];", 8, "Nested Square Bracket Member Accessor, `;`"], +["o.n.m;", 6, "Nested Dot Member Accessor, `;`"], +["o.if;", 4, "Dot Reserved Property Name Accessor, `;`"], + +// Function Calls. +["f();", 4, "Function Call Operator, `;`"], +["f(x);", 5, "Function Call Operator With 1 Argument, `;`"], +["f(x,y);", 7, "Function Call Operator With Multiple Arguments, `;`"], +["o.m();", 6, "Dot Member Accessor, Function Call, `;`"], +["o['m']();", 7, "Square Bracket Member Accessor, Function Call, `;`"], +["o.m(x);", 7, "Dot Member Accessor, Function Call With 1 Argument, `;`"], +["o['m'](x);", 8, "Square Bracket Member Accessor, Function Call With 1 Argument, `;`"], +["o.m(x,y);", 9, "Dot Member Accessor, Function Call With 2 Arguments, `;`"], +["o['m'](x,y);", 10, "Square Bracket Member Accessor, Function Call With 2 Arguments, `;`"], +["f(x)(y);", 8, "Nested Function Call With 1 Argument Each, `;`"], +["f().x;", 6, "Function Call, Dot Member Accessor, `;`"], + +// `eval` Function. +["eval('x');", 5, "`eval` Invocation With 1 Argument, `;`"], +["(eval)('x');", 7, "Direct `eval` Call Example, `;`"], +["(1,eval)('x');", 9, "Indirect `eval` Call Example, `;`"], +["eval(x,y);", 7, "`eval` Invocation With 2 Arguments, `;`"], + +// `new` Operator. +["new f();", 6, "`new` Operator, Function Call, `;`"], +["new o;", 4, "`new` Operator, Identifier, `;`"], +["new o.m;", 6, "`new` Operator, Dot Member Accessor, `;`"], +["new o.m(x);", 9, "`new` Operator, Dot Member Accessor, Function Call With 1 Argument, `;`"], +["new o.m(x,y);", 11, "``new` Operator, Dot Member Accessor, Function Call With 2 Arguments , `;`"], + +// Prefix and Postfix Increment. +["++x;", 3, "Prefix Increment, Identifier, `;`"], +["x++;", 3, "Identifier, Postfix Increment, `;`"], +["--x;", 3, "Prefix Decrement, Identifier, `;`"], +["x--;", 3, "Postfix Decrement, Identifier, `;`"], +["x ++;", 4, "Identifier, Space, Postfix Increment, `;`"], +["x /* comment */ ++;", 6, "Identifier, Block Comment, Postfix Increment, `;`"], +["++ /* comment */ x;", 6, "Prefix Increment, Block Comment, Identifier, `;`"], + +// Unary Operators. +["delete x;", 4, "`delete` Operator, Space, Identifier, `;`"], +["void x;", 4, "`void` Operator, Space, Identifier, `;`"], +["typeof x;", 4, "`typeof` Operator, Space, Identifier, `;`"], +["+x;", 3, "Unary `+` Operator, Identifier, `;`"], +["-x;", 3, "Unary Negation Operator, Identifier, `;`"], +["~x;", 3, "Bitwise NOT Operator, Identifier, `;`"], +["!x;", 3, "Logical NOT Operator, Identifier, `;`"], + +// Comma Operator. +["x, y;", 5, "Comma Operator"], + +// Miscellaneous. +["new Date++;", 5, "`new` Operator, Identifier, Postfix Increment, `;`"], +["+x++;", 4, "Unary `+`, Identifier, Postfix Increment, `;`"], + +// Expressions. +["1 * 2;", 6, "Integer, Multiplication, Integer, `;`"], +["1 / 2;", 6, "Integer, Division, Integer, `;`"], +["1 % 2;", 6, "Integer, Modulus, Integer, `;`"], +["1 + 2;", 6, "Integer, Addition, Integer, `;`"], +["1 - 2;", 6, "Integer, Subtraction, Integer, `;`"], +["1 << 2;", 6, "Integer, Bitwise Left Shift, Integer, `;`"], +["1 >>> 2;", 6, "Integer, Bitwise Zero-fill Right Shift, Integer, `;`"], +["1 >> 2;", 6, "Integer, Bitwise Sign-Propagating Right Shift, Integer, `;`"], +["1 * 2 + 3;", 10, "Order-of-Operations Expression, `;`"], +["(1+2)*3;", 8, "Parenthesized Additive Expression, Multiplication, `;`"], +["1*(2+3);", 8, "Multiplication, Parenthesized Additive Expression, `;`"], +["xy;", 4, "Greater-Than Relational Operator, `;`"], +["x<=y;", 4, "Less-Than-or-Equal-To Relational Operator, `;`"], +["x>=y;", 4, "Greater-Than-or-Equal-To Relational Operator, `;`"], +["x instanceof y;", 6, "`instanceof` Operator, `;`"], +["x in y;", 6, "`in` Operator, `;`"], +["x&y;", 4, "Bitwise AND Operator, `;`"], +["x^y;", 4, "Bitwise XOR Operator, `;`"], +["x|y;", 4, "Bitwise OR Operator, `;`"], +["x+y>>= y;", 6, "Bitwise Zero-Fill Right Shift Assignment, `;`"], +["x <<= y;", 6, "Bitwise Left Shift Assignment, `;`"], +["x += y;", 6, "Additive Assignment, `;`"], +["x -= y;", 6, "Subtractive Assignment, `;`"], +["x *= y;", 6, "Multiplicative Assignment, `;`"], +["x /= y;", 6, "Divisive Assignment, `;`"], +["x %= y;", 6, "Modulus Assignment, `;`"], +["x >>= y;", 6, "Bitwise Sign-Propagating Right Shift Assignment, `;`"], +["x &= y;", 6, "Bitwise AND Assignment, `;`"], +["x ^= y;", 6, "Bitwise XOR Assignment, `;`"], +["x |= y;", 6, "Bitwise OR Assignment, `;`"], + +// Blocks. +["{};", 3, "Empty Block, `;`"], +["{x;};", 5, "Block Containing 1 Identifier, `;`"], +["{x;y;};", 7, "Block Containing 2 Identifiers, `;`"], + +// Variable Declarations. +["var abc;", 4, "Variable Declaration"], +["var x,y;", 6, "Comma-Separated Variable Declarations, `;`"], +["var x=1,y=2;", 10, "Comma-Separated Variable Initializations, `;`"], +["var x,y=2;", 8, "Variable Declaration, Variable Initialization, `;`"], + +// Empty Statements. +[";", 1, "Empty Statement"], +["\n;", 2, "Linefeed, `;`"], + +// Expression Statements. +["x;", 2, "Identifier, `;`"], +["5;", 2, "Integer, `;`"], +["1+2;", 4, "Additive Statement, `;`"], + +// `if...else` Statements. +["if (c) x; else y;", 13, "Space-Delimited `if...else` Statement"], +["if (c) x;", 8, "Space-Delimited `if` Statement, `;`"], +["if (c) {} else {};", 14, "Empty Block-Delimited `if...else` Statement"], +["if (c1) if (c2) s1; else s2;", 19, "Nested `if...else` Statement Without Dangling `else`"], + +// `while` and `do...while` Loops. +["do s; while (e);", 11, "Space-Delimited `do...while` Loop"], +["do { s; } while (e);", 15, "Block-Delimited `do...while` Loop"], +["while (e) s;", 8, "Space-Delimited `while` Loop"], +["while (e) { s; };", 13, "Block-Delimited `while` Loop"], + +// `for` and `for...in` Loops. +["for (;;) ;", 8, "Infinite Space-Delimited `for` Loop"], +["for (;c;x++) x;", 12, "`for` Loop: Empty Initialization Condition; Space-Delimited Body"], +["for (i;i foo(new window[(['Active'].concat('Object').join('X'))])\n```\n\n## License\n\nLicensed under the MIT license.\n\n[socket.io]: http://socket.io/\n", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/felixge/node-active-x-obfuscator/issues" + }, + "_id": "active-x-obfuscator@0.0.1", + "_from": "active-x-obfuscator@0.0.1" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js new file mode 100644 index 00000000..e8fc807f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js @@ -0,0 +1,53 @@ +var activeXObfuscator = require('./index'); +var assert = require('assert'); + +var OBFUSCATED_ACTIVE_X_OBJECT = activeXObfuscator.OBFUSCATED_ACTIVE_X_OBJECT; +var OBFUSCATED_ACTIVE_X = activeXObfuscator.OBFUSCATED_ACTIVE_X; + +var input = + "foo(new ActiveXObject('Microsoft.XMLHTTP'))"; +var expected = + "foo(new window[" + OBFUSCATED_ACTIVE_X_OBJECT + "]('Microsoft.XMLHTTP'))"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveXObject';"; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X_OBJECT + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = "ActiveXObject";'; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X_OBJECT + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = o.ActiveXObject;'; +var expected = + "var foo = o[" + OBFUSCATED_ACTIVE_X_OBJECT + "];"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = "ActiveX";'; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveX';"; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo; // ActiveX is cool"; +var expected = + "var foo; // Ac...eX is cool"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveX is cool';"; +assert.throws(function() { + activeXObfuscator(input); +}, /Unknown ActiveX occurence/); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore new file mode 100644 index 00000000..d97eaa09 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore @@ -0,0 +1,4 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html new file mode 100644 index 00000000..5f37ac0f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html @@ -0,0 +1,981 @@ + + + + +UglifyJS – a JavaScript parser/compressor/beautifier + + + + + + + + + + + + + +
+ +
+ +
+

UglifyJS – a JavaScript parser/compressor/beautifier

+ + + + +
+

1 UglifyJS — a JavaScript parser/compressor/beautifier

+
+ + +

+This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on NodeJS, but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the exports.* lines from UglifyJS sources). +

+

+The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in parse-js.js and it's a +port to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke. +

+

+( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

+

+The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

+
    +
  • ability to re-generate JavaScript code from the AST. Optionally + indented—you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +
  • +
  • shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with eval() calls or with{} statements. In short, if eval() or + with{} are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +
  • +
  • various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + +
      +
    • foo["bar"] ==> foo.bar + +
    • +
    • remove block brackets {} + +
    • +
    • join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + +
    • +
    • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + +
    • +
    • consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + +
    • +
    • various optimizations for IF statements: + +
        +
      • if (foo) bar(); else baz(); ==> foo?bar():baz(); +
      • +
      • if (!foo) bar(); else baz(); ==> foo?baz():bar(); +
      • +
      • if (foo) bar(); ==> foo&&bar(); +
      • +
      • if (!foo) bar(); ==> foo||bar(); +
      • +
      • if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); +
      • +
      • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + +
      • +
      + +
    • +
    • remove some unreachable code and warn about it (code that follows a + return, throw, break or continue statement, except + function/variable declarations). + +
    • +
    • act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. +
    • +
    + +
  • +
+ + + +
+ +
+

1.1 Unsafe transformations

+
+ + +

+The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +--unsafe flag. +

+ +
+ +
+

1.1.1 Calls involving the global Array constructor

+
+ + +

+The following transformations occur: +

+ + + +
new Array(1, 2, 3, 4)  => [1,2,3,4]
+Array(a, b, c)         => [a,b,c]
+new Array(5)           => Array(5)
+new Array(a)           => Array(a)
+
+ + +

+These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. +

+

+UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

+ + + +
// case 1.  globally declared variable
+  var Array;
+  new Array(1, 2, 3);
+  Array(a, b);
+
+  // or (can be declared later)
+  new Array(1, 2, 3);
+  var Array;
+
+  // or (can be a function)
+  new Array(1, 2, 3);
+  function Array() { ... }
+
+// case 2.  declared in a function
+  (function(){
+    a = new Array(1, 2, 3);
+    b = Array(5, 6);
+    var Array;
+  })();
+
+  // or
+  (function(Array){
+    return Array(5, 6, 7);
+  })();
+
+  // or
+  (function(){
+    return new Array(1, 2, 3, 4);
+    function Array() { ... }
+  })();
+
+  // etc.
+
+ + +
+ +
+ +
+

1.1.2 obj.toString() ==> obj+“”

+
+ + +
+
+ +
+ +
+

1.2 Install (NPM)

+
+ + +

+UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

+
+ +
+ +
+

1.3 Install latest code from GitHub

+
+ + + + + +
## clone the repository
+mkdir -p /where/you/wanna/put/it
+cd /where/you/wanna/put/it
+git clone git://github.com/mishoo/UglifyJS.git
+
+## make the module available to Node
+mkdir -p ~/.node_libraries/
+cd ~/.node_libraries/
+ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
+
+## and if you want the CLI script too:
+mkdir -p ~/bin
+cd ~/bin
+ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
+  # (then add ~/bin to your $PATH if it's not there already)
+
+ + +
+ +
+ +
+

1.4 Usage

+
+ + +

+There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

+ + + +
uglifyjs [ options... ] [ filename ]
+
+ + +

+filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

+

+Supported options: +

+
    +
  • -b or --beautify — output indented code; when passed, additional + options control the beautifier: + +
      +
    • -i N or --indent N — indentation level (number of spaces) + +
    • +
    • -q or --quote-keys — quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +
    • +
    + +
  • +
  • --ascii — pass this argument to encode non-ASCII characters as + \uXXXX sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +
  • +
  • -nm or --no-mangle — don't mangle names. + +
  • +
  • -nmf or --no-mangle-functions – in case you want to mangle variable + names, but not touch function names. + +
  • +
  • -ns or --no-squeeze — don't call ast_squeeze() (which does various + optimizations that result in smaller, less readable code). + +
  • +
  • -mt or --mangle-toplevel — mangle names in the toplevel scope too + (by default we don't do this). + +
  • +
  • --no-seqs — when ast_squeeze() is called (thus, unless you pass + --no-squeeze) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass --no-seqs to disable it. + +
  • +
  • --no-dead-code — by default, UglifyJS will remove code that is + obviously unreachable (code that follows a return, throw, break or + continue statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +
  • +
  • -nc or --no-copyright — by default, uglifyjs will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +
  • +
  • -o filename or --output filename — put the result in filename. If + this isn't given, the result goes to standard output (or see next one). + +
  • +
  • --overwrite — if the code is read from a file (not from STDIN) and you + pass --overwrite then the output will be written in the same file. + +
  • +
  • --ast — pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +
  • +
  • -v or --verbose — output some notes on STDERR (for now just how long + each operation takes). + +
  • +
  • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value true, or you can specify a numeric value (such as + 1024), a quoted string value (such as ="object"= or + ='https://github.com'), or the name of another symbol or keyword (such as =null or document). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of conditional compilation + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + --define-from-module more suitable for use. + +
  • +
  • -define-from-module SOMEMODULE — will load the named module (as + per the NodeJS require() function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the --define option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of --define + options. + +
  • +
  • --unsafe — enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + +
      +
    • foo.toString() ==> foo+"" +
    • +
    • new Array(x,…) ==> [x,…] +
    • +
    • new Array(x) ==> Array(x) + +
    • +
    + +
  • +
  • --max-line-len (default 32K characters) — add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass –max-line-len 0 to disable this + safety feature. + +
  • +
  • --reserved-names — some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names require and $super + intact you'd specify –reserved-names "require,$super". + +
  • +
  • --inline-script – when you want to include the output literally in an + HTML <script> tag you can use this option to prevent </script from + showing up in the output. + +
  • +
  • --lift-vars – when you pass this, UglifyJS will apply the following + transformations (see the notes in API, ast_lift_variables): + +
      +
    • put all var declarations at the start of the scope +
    • +
    • make sure a variable is declared only once +
    • +
    • discard unused function arguments +
    • +
    • discard unused inner (named) functions +
    • +
    • finally, try to merge assignments into that one var declaration, if + possible. +
    • +
    + +
  • +
+ + + +
+ +
+

1.4.1 API

+
+ + +

+To use the library from JavaScript, you'd do the following (example for +NodeJS): +

+ + + +
var jsp = require("uglify-js").parser;
+var pro = require("uglify-js").uglify;
+
+var orig_code = "... JS code here";
+var ast = jsp.parse(orig_code); // parse code and get the initial AST
+ast = pro.ast_mangle(ast); // get a new AST with mangled names
+ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
+var final_code = pro.gen_code(ast); // compressed code here
+
+ + +

+The above performs the full compression that is possible right now. As you +can see, there are a sequence of steps which you can apply. For example if +you want compressed output but for some reason you don't want to mangle +variable names, you would simply skip the line that calls +pro.ast_mangle(ast). +

+

+Some of these functions take optional arguments. Here's a description: +

+
    +
  • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST. + strict_semicolons is optional and defaults to false. If you pass + true then the parser will throw an error when it expects a semicolon and + it doesn't find it. For most JS code you don't want that, but it's useful + if you want to strictly sanitize your code. + +
  • +
  • pro.ast_lift_variables(ast) – merge and move var declarations to the + scop of the scope; discard unused function arguments or variables; discard + unused (named) inner functions. It also tries to merge assignments + following the var declaration into it. + +

    + If your code is very hand-optimized concerning var declarations, this + lifting variable declarations might actually increase size. For me it + helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also + note that (since it's not enabled by default) this operation isn't yet + heavily tested (please report if you find issues!). +

    +

    + Note that although it might increase the image size (on jQuery it gains + 865 bytes, 243 after gzip) it's technically more correct: in certain + situations, dead code removal might drop variable declarations, which + would not happen if the variables are lifted in advance. +

    +

    + Here's an example of what it does: +

  • +
+ + + + + +
function f(a, b, c, d, e) {
+    var q;
+    var w;
+    w = 10;
+    q = 20;
+    for (var i = 1; i < 10; ++i) {
+        var boo = foo(a);
+    }
+    for (var i = 0; i < 1; ++i) {
+        var boo = bar(c);
+    }
+    function foo(){ ... }
+    function bar(){ ... }
+    function baz(){ ... }
+}
+
+// transforms into ==>
+
+function f(a, b, c) {
+    var i, boo, w = 10, q = 20;
+    for (i = 1; i < 10; ++i) {
+        boo = foo(a);
+    }
+    for (i = 0; i < 1; ++i) {
+        boo = bar(c);
+    }
+    function foo() { ... }
+    function bar() { ... }
+}
+
+ + +
    +
  • pro.ast_mangle(ast, options) – generates a new AST containing mangled + (compressed) variable and function names. It supports the following + options: + +
      +
    • toplevel – mangle toplevel names (by default we don't touch them). +
    • +
    • except – an array of names to exclude from compression. +
    • +
    • defines – an object with properties named after symbols to + replace (see the --define option for the script) and the values + representing the AST replacement value. + +
    • +
    + +
  • +
  • pro.ast_squeeze(ast, options) – employs further optimizations designed + to reduce the size of the code that gen_code would generate from the + AST. Returns a new AST. options can be a hash; the supported options + are: + +
      +
    • make_seqs (default true) which will cause consecutive statements in a + block to be merged using the "sequence" (comma) operator + +
    • +
    • dead_code (default true) which will remove unreachable code. + +
    • +
    + +
  • +
  • pro.gen_code(ast, options) – generates JS code from the AST. By + default it's minified, but using the options argument you can get nicely + formatted output. options is, well, optional :-) and if you pass it it + must be an object and supports the following properties (below you can see + the default values): + +
      +
    • beautify: false – pass true if you want indented output +
    • +
    • indent_start: 0 (only applies when beautify is true) – initial + indentation in spaces +
    • +
    • indent_level: 4 (only applies when beautify is true) -- + indentation level, in spaces (pass an even number) +
    • +
    • quote_keys: false – if you pass true it will quote all keys in + literal objects +
    • +
    • space_colon: false (only applies when beautify is true) – wether + to put a space before the colon in object literals +
    • +
    • ascii_only: false – pass true if you want to encode non-ASCII + characters as \uXXXX. +
    • +
    • inline_script: false – pass true to escape occurrences of + </script in strings +
    • +
    + +
  • +
+ + +
+ +
+ +
+

1.4.2 Beautifier shortcoming – no more comments

+
+ + +

+The beautifier can be used as a general purpose indentation tool. It's +useful when you want to make a minified file readable. One limitation, +though, is that it discards all comments, so you don't really want to use it +to reformat your code, unless you don't have, or don't care about, comments. +

+

+In fact it's not the beautifier who discards comments — they are dumped at +the parsing stage, when we build the initial AST. Comments don't really +make sense in the AST, and while we could add nodes for them, it would be +inconvenient because we'd have to add special rules to ignore them at all +the processing stages. +

+
+ +
+ +
+

1.4.3 Use as a code pre-processor

+
+ + +

+The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

+

+The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

+ + + +
CLAUSE1: if (typeof DEVMODE === 'undefined') {
+    DEVMODE = true;
+}
+
+CLAUSE2: function init() {
+    if (DEVMODE) {
+        console.log("init() called");
+    }
+    ....
+    DEVMODE &amp;&amp; console.log("init() complete");
+}
+
+CLAUSE3: function reportDeviceStatus(device) {
+    var DEVMODE = device.mode, DEVNAME = device.name;
+    if (DEVMODE === 'open') {
+        ....
+    }
+}
+
+ + +

+When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

+

+If the above code is processed by UglifyJS with an argument of +--define DEVMODE=false then UglifyJS will replace DEVMODE with the +boolean constant value false within CLAUSE1 and CLAUSE2, but it +will leave CLAUSE3 as it stands because there DEVMODE resolves to +a validly declared variable. +

+

+And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

+

+In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

+

+It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

+
+
+ +
+ +
+

1.5 Compression – how good is it?

+
+ + +

+Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

+

+We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

+ + ++ + + + + + + + + + +
FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
+ + +
+ +
+ +
+

1.6 Bugs?

+
+ + +

+Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

+

+DynarchLIB was started in times when there was no good JS minifier. +Therefore I was quite religious about trying to write short code manually, +and as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a += 10 : b = 20”, though the more readable version would clearly be to use +“if/else”. +

+

+Since the parser/compressor runs fine on DL and jQuery, I'm quite confident +that it's solid enough for production use. If you can identify any bugs, +I'd love to hear about them (use the Google Group or email me directly). +

+
+ +
+ +
+

1.7 Links

+
+ + + + + +
+ +
+ +
+

1.8 License

+
+ + +

+UglifyJS is released under the BSD license: +

+ + + +
Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
+Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+    * Redistributions of source code must retain the above
+      copyright notice, this list of conditions and the following
+      disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+ + +
+

Footnotes:

+
+

1 I even reported a few bugs and suggested some fixes in the original + parse-js library, and Marijn pushed fixes literally in minutes. +

+
+
+ +
+
+
+ +
+

Date: 2011-12-09 14:59:08 EET

+

Author: Mihai Bazon

+

Org version 7.7 with Emacs version 23

+Validate XHTML 1.0 + +
+ + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org new file mode 100644 index 00000000..4d01fdfd --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org @@ -0,0 +1,574 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+AUTHOR: Mihai Bazon +#+EMAIL: mihai.bazon@gmail.com + +* UglifyJS --- a JavaScript parser/compressor/beautifier + +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“”= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =--ascii= --- pass this argument to encode non-ASCII characters as + =\uXXXX= sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle names. + +- =-nmf= or =--no-mangle-functions= -- in case you want to mangle variable + names, but not touch function names. + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML =\n\n\n\n\n
\n\n
\n\n
\n

UglifyJS – a JavaScript parser/compressor/beautifier

\n\n\n\n\n
\n

1 UglifyJS — a JavaScript parser/compressor/beautifier

\n
\n\n\n

\nThis package implements a general-purpose JavaScript\nparser/compressor/beautifier toolkit. It is developed on NodeJS, but it\nshould work on any JavaScript platform supporting the CommonJS module system\n(and if your platform of choice doesn't support CommonJS, you can easily\nimplement it, or discard the exports.* lines from UglifyJS sources).\n

\n

\nThe tokenizer/parser generates an abstract syntax tree from JS code. You\ncan then traverse the AST to learn more about the code, or do various\nmanipulations on it. This part is implemented in parse-js.js and it's a\nport to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke.\n

\n

\n( See cl-uglify-js if you're looking for the Common Lisp version of\nUglifyJS. )\n

\n

\nThe second part of this package, implemented in process.js, inspects and\nmanipulates the AST generated by the parser to provide the following:\n

\n
    \n
  • ability to re-generate JavaScript code from the AST. Optionally\n indented—you can use this if you want to “beautify” a program that has\n been compressed, so that you can inspect the source. But you can also run\n our code generator to print out an AST without any whitespace, so you\n achieve compression as well.\n\n
  • \n
  • shorten variable names (usually to single characters). Our mangler will\n analyze the code and generate proper variable names, depending on scope\n and usage, and is smart enough to deal with globals defined elsewhere, or\n with eval() calls or with{} statements. In short, if eval() or\n with{} are used in some scope, then all variables in that scope and any\n variables in the parent scopes will remain unmangled, and any references\n to such variables remain unmangled as well.\n\n
  • \n
  • various small optimizations that may lead to faster code but certainly\n lead to smaller code. Where possible, we do the following:\n\n
      \n
    • foo[\"bar\"] ==> foo.bar\n\n
    • \n
    • remove block brackets {}\n\n
    • \n
    • join consecutive var declarations:\n var a = 10; var b = 20; ==> var a=10,b=20;\n\n
    • \n
    • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the\n replacement if the result occupies less bytes; for example 1/3 would\n translate to 0.333333333333, so in this case we don't replace it.\n\n
    • \n
    • consecutive statements in blocks are merged into a sequence; in many\n cases, this leaves blocks with a single statement, so then we can remove\n the block brackets.\n\n
    • \n
    • various optimizations for IF statements:\n\n
        \n
      • if (foo) bar(); else baz(); ==> foo?bar():baz();\n
      • \n
      • if (!foo) bar(); else baz(); ==> foo?baz():bar();\n
      • \n
      • if (foo) bar(); ==> foo&&bar();\n
      • \n
      • if (!foo) bar(); ==> foo||bar();\n
      • \n
      • if (foo) return bar(); else return baz(); ==> return foo?bar():baz();\n
      • \n
      • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n\n
      • \n
      \n\n
    • \n
    • remove some unreachable code and warn about it (code that follows a\n return, throw, break or continue statement, except\n function/variable declarations).\n\n
    • \n
    • act a limited version of a pre-processor (c.f. the pre-processor of\n C/C++) to allow you to safely replace selected global symbols with\n specified values. When combined with the optimisations above this can\n make UglifyJS operate slightly more like a compilation process, in\n that when certain symbols are replaced by constant values, entire code\n blocks may be optimised away as unreachable.\n
    • \n
    \n\n
  • \n
\n\n\n\n
\n\n
\n

1.1 Unsafe transformations

\n
\n\n\n

\nThe following transformations can in theory break code, although they're\nprobably safe in most practical cases. To enable them you need to pass the\n--unsafe flag.\n

\n\n
\n\n
\n

1.1.1 Calls involving the global Array constructor

\n
\n\n\n

\nThe following transformations occur:\n

\n\n\n\n
new Array(1, 2, 3, 4)  => [1,2,3,4]\nArray(a, b, c)         => [a,b,c]\nnew Array(5)           => Array(5)\nnew Array(a)           => Array(a)\n
\n\n\n

\nThese are all safe if the Array name isn't redefined. JavaScript does allow\none to globally redefine Array (and pretty much everything, in fact) but I\npersonally don't see why would anyone do that.\n

\n

\nUglifyJS does handle the case where Array is redefined locally, or even\nglobally but with a function or var declaration. Therefore, in the\nfollowing cases UglifyJS doesn't touch calls or instantiations of Array:\n

\n\n\n\n
// case 1.  globally declared variable\n  var Array;\n  new Array(1, 2, 3);\n  Array(a, b);\n\n  // or (can be declared later)\n  new Array(1, 2, 3);\n  var Array;\n\n  // or (can be a function)\n  new Array(1, 2, 3);\n  function Array() { ... }\n\n// case 2.  declared in a function\n  (function(){\n    a = new Array(1, 2, 3);\n    b = Array(5, 6);\n    var Array;\n  })();\n\n  // or\n  (function(Array){\n    return Array(5, 6, 7);\n  })();\n\n  // or\n  (function(){\n    return new Array(1, 2, 3, 4);\n    function Array() { ... }\n  })();\n\n  // etc.\n
\n\n\n
\n\n
\n\n
\n

1.1.2 obj.toString() ==> obj+“”

\n
\n\n\n
\n
\n\n
\n\n
\n

1.2 Install (NPM)

\n
\n\n\n

\nUglifyJS is now available through NPM — npm install uglify-js should do\nthe job.\n

\n
\n\n
\n\n
\n

1.3 Install latest code from GitHub

\n
\n\n\n\n\n\n
## clone the repository\nmkdir -p /where/you/wanna/put/it\ncd /where/you/wanna/put/it\ngit clone git://github.com/mishoo/UglifyJS.git\n\n## make the module available to Node\nmkdir -p ~/.node_libraries/\ncd ~/.node_libraries/\nln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js\n\n## and if you want the CLI script too:\nmkdir -p ~/bin\ncd ~/bin\nln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs\n  # (then add ~/bin to your $PATH if it's not there already)\n
\n\n\n
\n\n
\n\n
\n

1.4 Usage

\n
\n\n\n

\nThere is a command-line tool that exposes the functionality of this library\nfor your shell-scripting needs:\n

\n\n\n\n
uglifyjs [ options... ] [ filename ]\n
\n\n\n

\nfilename should be the last argument and should name the file from which\nto read the JavaScript code. If you don't specify it, it will read code\nfrom STDIN.\n

\n

\nSupported options:\n

\n
    \n
  • -b or --beautify — output indented code; when passed, additional\n options control the beautifier:\n\n
      \n
    • -i N or --indent N — indentation level (number of spaces)\n\n
    • \n
    • -q or --quote-keys — quote keys in literal objects (by default,\n only keys that cannot be identifier names will be quotes).\n\n
    • \n
    \n\n
  • \n
  • --ascii — pass this argument to encode non-ASCII characters as\n \\uXXXX sequences. By default UglifyJS won't bother to do it and will\n output Unicode characters instead. (the output is always encoded in UTF8,\n but if you pass this option you'll only get ASCII).\n\n
  • \n
  • -nm or --no-mangle — don't mangle names.\n\n
  • \n
  • -nmf or --no-mangle-functions – in case you want to mangle variable\n names, but not touch function names.\n\n
  • \n
  • -ns or --no-squeeze — don't call ast_squeeze() (which does various\n optimizations that result in smaller, less readable code).\n\n
  • \n
  • -mt or --mangle-toplevel — mangle names in the toplevel scope too\n (by default we don't do this).\n\n
  • \n
  • --no-seqs — when ast_squeeze() is called (thus, unless you pass\n --no-squeeze) it will reduce consecutive statements in blocks into a\n sequence. For example, \"a = 10; b = 20; foo();\" will be written as\n \"a=10,b=20,foo();\". In various occasions, this allows us to discard the\n block brackets (since the block becomes a single statement). This is ON\n by default because it seems safe and saves a few hundred bytes on some\n libs that I tested it on, but pass --no-seqs to disable it.\n\n
  • \n
  • --no-dead-code — by default, UglifyJS will remove code that is\n obviously unreachable (code that follows a return, throw, break or\n continue statement and is not a function/variable declaration). Pass\n this option to disable this optimization.\n\n
  • \n
  • -nc or --no-copyright — by default, uglifyjs will keep the initial\n comment tokens in the generated code (assumed to be copyright information\n etc.). If you pass this it will discard it.\n\n
  • \n
  • -o filename or --output filename — put the result in filename. If\n this isn't given, the result goes to standard output (or see next one).\n\n
  • \n
  • --overwrite — if the code is read from a file (not from STDIN) and you\n pass --overwrite then the output will be written in the same file.\n\n
  • \n
  • --ast — pass this if you want to get the Abstract Syntax Tree instead\n of JavaScript as output. Useful for debugging or learning more about the\n internals.\n\n
  • \n
  • -v or --verbose — output some notes on STDERR (for now just how long\n each operation takes).\n\n
  • \n
  • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace\n all instances of the specified symbol where used as an identifier\n (except where symbol has properly declared by a var declaration or\n use as function parameter or similar) with the specified value. This\n argument may be specified multiple times to define multiple\n symbols - if no value is specified the symbol will be replaced with\n the value true, or you can specify a numeric value (such as\n 1024), a quoted string value (such as =\"object\"= or\n ='https://github.com'), or the name of another symbol or keyword (such as =null or document).\n This allows you, for example, to assign meaningful names to key\n constant values but discard the symbolic names in the uglified\n version for brevity/efficiency, or when used wth care, allows\n UglifyJS to operate as a form of conditional compilation\n whereby defining appropriate values may, by dint of the constant\n folding and dead code removal features above, remove entire\n superfluous code blocks (e.g. completely remove instrumentation or\n trace code for production use).\n Where string values are being defined, the handling of quotes are\n likely to be subject to the specifics of your command shell\n environment, so you may need to experiment with quoting styles\n depending on your platform, or you may find the option\n --define-from-module more suitable for use.\n\n
  • \n
  • -define-from-module SOMEMODULE — will load the named module (as\n per the NodeJS require() function) and iterate all the exported\n properties of the module defining them as symbol names to be defined\n (as if by the --define option) per the name of each property\n (i.e. without the module name prefix) and given the value of the\n property. This is a much easier way to handle and document groups of\n symbols to be defined rather than a large number of --define\n options.\n\n
  • \n
  • --unsafe — enable other additional optimizations that are known to be\n unsafe in some contrived situations, but could still be generally useful.\n For now only these:\n\n
      \n
    • foo.toString() ==> foo+\"\"\n
    • \n
    • new Array(x,…) ==> [x,…]\n
    • \n
    • new Array(x) ==> Array(x)\n\n
    • \n
    \n\n
  • \n
  • --max-line-len (default 32K characters) — add a newline after around\n 32K characters. I've seen both FF and Chrome croak when all the code was\n on a single line of around 670K. Pass –max-line-len 0 to disable this\n safety feature.\n\n
  • \n
  • --reserved-names — some libraries rely on certain names to be used, as\n pointed out in issue #92 and #81, so this option allow you to exclude such\n names from the mangler. For example, to keep names require and $super\n intact you'd specify –reserved-names \"require,$super\".\n\n
  • \n
  • --inline-script – when you want to include the output literally in an\n HTML <script> tag you can use this option to prevent </script from\n showing up in the output.\n\n
  • \n
  • --lift-vars – when you pass this, UglifyJS will apply the following\n transformations (see the notes in API, ast_lift_variables):\n\n
      \n
    • put all var declarations at the start of the scope\n
    • \n
    • make sure a variable is declared only once\n
    • \n
    • discard unused function arguments\n
    • \n
    • discard unused inner (named) functions\n
    • \n
    • finally, try to merge assignments into that one var declaration, if\n possible.\n
    • \n
    \n\n
  • \n
\n\n\n\n
\n\n
\n

1.4.1 API

\n
\n\n\n

\nTo use the library from JavaScript, you'd do the following (example for\nNodeJS):\n

\n\n\n\n
var jsp = require(\"uglify-js\").parser;\nvar pro = require(\"uglify-js\").uglify;\n\nvar orig_code = \"... JS code here\";\nvar ast = jsp.parse(orig_code); // parse code and get the initial AST\nast = pro.ast_mangle(ast); // get a new AST with mangled names\nast = pro.ast_squeeze(ast); // get an AST with compression optimizations\nvar final_code = pro.gen_code(ast); // compressed code here\n
\n\n\n

\nThe above performs the full compression that is possible right now. As you\ncan see, there are a sequence of steps which you can apply. For example if\nyou want compressed output but for some reason you don't want to mangle\nvariable names, you would simply skip the line that calls\npro.ast_mangle(ast).\n

\n

\nSome of these functions take optional arguments. Here's a description:\n

\n
    \n
  • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST.\n strict_semicolons is optional and defaults to false. If you pass\n true then the parser will throw an error when it expects a semicolon and\n it doesn't find it. For most JS code you don't want that, but it's useful\n if you want to strictly sanitize your code.\n\n
  • \n
  • pro.ast_lift_variables(ast) – merge and move var declarations to the\n scop of the scope; discard unused function arguments or variables; discard\n unused (named) inner functions. It also tries to merge assignments\n following the var declaration into it.\n\n

    \n If your code is very hand-optimized concerning var declarations, this\n lifting variable declarations might actually increase size. For me it\n helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also\n note that (since it's not enabled by default) this operation isn't yet\n heavily tested (please report if you find issues!).\n

    \n

    \n Note that although it might increase the image size (on jQuery it gains\n 865 bytes, 243 after gzip) it's technically more correct: in certain\n situations, dead code removal might drop variable declarations, which\n would not happen if the variables are lifted in advance.\n

    \n

    \n Here's an example of what it does:\n

  • \n
\n\n\n\n\n\n
function f(a, b, c, d, e) {\n    var q;\n    var w;\n    w = 10;\n    q = 20;\n    for (var i = 1; i < 10; ++i) {\n        var boo = foo(a);\n    }\n    for (var i = 0; i < 1; ++i) {\n        var boo = bar(c);\n    }\n    function foo(){ ... }\n    function bar(){ ... }\n    function baz(){ ... }\n}\n\n// transforms into ==>\n\nfunction f(a, b, c) {\n    var i, boo, w = 10, q = 20;\n    for (i = 1; i < 10; ++i) {\n        boo = foo(a);\n    }\n    for (i = 0; i < 1; ++i) {\n        boo = bar(c);\n    }\n    function foo() { ... }\n    function bar() { ... }\n}\n
\n\n\n
    \n
  • pro.ast_mangle(ast, options) – generates a new AST containing mangled\n (compressed) variable and function names. It supports the following\n options:\n\n
      \n
    • toplevel – mangle toplevel names (by default we don't touch them).\n
    • \n
    • except – an array of names to exclude from compression.\n
    • \n
    • defines – an object with properties named after symbols to\n replace (see the --define option for the script) and the values\n representing the AST replacement value.\n\n
    • \n
    \n\n
  • \n
  • pro.ast_squeeze(ast, options) – employs further optimizations designed\n to reduce the size of the code that gen_code would generate from the\n AST. Returns a new AST. options can be a hash; the supported options\n are:\n\n
      \n
    • make_seqs (default true) which will cause consecutive statements in a\n block to be merged using the \"sequence\" (comma) operator\n\n
    • \n
    • dead_code (default true) which will remove unreachable code.\n\n
    • \n
    \n\n
  • \n
  • pro.gen_code(ast, options) – generates JS code from the AST. By\n default it's minified, but using the options argument you can get nicely\n formatted output. options is, well, optional :-) and if you pass it it\n must be an object and supports the following properties (below you can see\n the default values):\n\n
      \n
    • beautify: false – pass true if you want indented output\n
    • \n
    • indent_start: 0 (only applies when beautify is true) – initial\n indentation in spaces\n
    • \n
    • indent_level: 4 (only applies when beautify is true) --\n indentation level, in spaces (pass an even number)\n
    • \n
    • quote_keys: false – if you pass true it will quote all keys in\n literal objects\n
    • \n
    • space_colon: false (only applies when beautify is true) – wether\n to put a space before the colon in object literals\n
    • \n
    • ascii_only: false – pass true if you want to encode non-ASCII\n characters as \\uXXXX.\n
    • \n
    • inline_script: false – pass true to escape occurrences of\n </script in strings\n
    • \n
    \n\n
  • \n
\n\n\n
\n\n
\n\n
\n

1.4.2 Beautifier shortcoming – no more comments

\n
\n\n\n

\nThe beautifier can be used as a general purpose indentation tool. It's\nuseful when you want to make a minified file readable. One limitation,\nthough, is that it discards all comments, so you don't really want to use it\nto reformat your code, unless you don't have, or don't care about, comments.\n

\n

\nIn fact it's not the beautifier who discards comments — they are dumped at\nthe parsing stage, when we build the initial AST. Comments don't really\nmake sense in the AST, and while we could add nodes for them, it would be\ninconvenient because we'd have to add special rules to ignore them at all\nthe processing stages.\n

\n
\n\n
\n\n
\n

1.4.3 Use as a code pre-processor

\n
\n\n\n

\nThe --define option can be used, particularly when combined with the\nconstant folding logic, as a form of pre-processor to enable or remove\nparticular constructions, such as might be used for instrumenting\ndevelopment code, or to produce variations aimed at a specific\nplatform.\n

\n

\nThe code below illustrates the way this can be done, and how the\nsymbol replacement is performed.\n

\n\n\n\n
CLAUSE1: if (typeof DEVMODE === 'undefined') {\n    DEVMODE = true;\n}\n\nCLAUSE2: function init() {\n    if (DEVMODE) {\n        console.log(\"init() called\");\n    }\n    ....\n    DEVMODE &amp;&amp; console.log(\"init() complete\");\n}\n\nCLAUSE3: function reportDeviceStatus(device) {\n    var DEVMODE = device.mode, DEVNAME = device.name;\n    if (DEVMODE === 'open') {\n        ....\n    }\n}\n
\n\n\n

\nWhen the above code is normally executed, the undeclared global\nvariable DEVMODE will be assigned the value true (see CLAUSE1)\nand so the init() function (CLAUSE2) will write messages to the\nconsole log when executed, but in CLAUSE3 a locally declared\nvariable will mask access to the DEVMODE global symbol.\n

\n

\nIf the above code is processed by UglifyJS with an argument of\n--define DEVMODE=false then UglifyJS will replace DEVMODE with the\nboolean constant value false within CLAUSE1 and CLAUSE2, but it\nwill leave CLAUSE3 as it stands because there DEVMODE resolves to\na validly declared variable.\n

\n

\nAnd more so, the constant-folding features of UglifyJS will recognise\nthat the if condition of CLAUSE1 is thus always false, and so will\nremove the test and body of CLAUSE1 altogether (including the\notherwise slightly problematical statement false = true; which it\nwill have formed by replacing DEVMODE in the body). Similarly,\nwithin CLAUSE2 both calls to console.log() will be removed\naltogether.\n

\n

\nIn this way you can mimic, to a limited degree, the functionality of\nthe C/C++ pre-processor to enable or completely remove blocks\ndepending on how certain symbols are defined - perhaps using UglifyJS\nto generate different versions of source aimed at different\nenvironments\n

\n

\nIt is recommmended (but not made mandatory) that symbols designed for\nthis purpose are given names consisting of UPPER_CASE_LETTERS to\ndistinguish them from other (normal) symbols and avoid the sort of\nclash that CLAUSE3 above illustrates.\n

\n
\n
\n\n
\n\n
\n

1.5 Compression – how good is it?

\n
\n\n\n

\nHere are updated statistics. (I also updated my Google Closure and YUI\ninstallations).\n

\n

\nWe're still a lot better than YUI in terms of compression, though slightly\nslower. We're still a lot faster than Closure, and compression after gzip\nis comparable.\n

\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
\n\n\n
\n\n
\n\n
\n

1.6 Bugs?

\n
\n\n\n

\nUnfortunately, for the time being there is no automated test suite. But I\nran the compressor manually on non-trivial code, and then I tested that the\ngenerated code works as expected. A few hundred times.\n

\n

\nDynarchLIB was started in times when there was no good JS minifier.\nTherefore I was quite religious about trying to write short code manually,\nand as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a\n= 10 : b = 20”, though the more readable version would clearly be to use\n“if/else”.\n

\n

\nSince the parser/compressor runs fine on DL and jQuery, I'm quite confident\nthat it's solid enough for production use. If you can identify any bugs,\nI'd love to hear about them (use the Google Group or email me directly).\n

\n
\n\n
\n\n
\n

1.7 Links

\n
\n\n\n\n\n\n
\n\n
\n\n
\n

1.8 License

\n
\n\n\n

\nUglifyJS is released under the BSD license:\n

\n\n\n\n
Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n
\n\n\n
\n

Footnotes:

\n
\n

1 I even reported a few bugs and suggested some fixes in the original\n parse-js library, and Marijn pushed fixes literally in minutes.\n

\n
\n
\n\n
\n
\n
\n\n
\n

Date: 2011-12-09 14:59:08 EET

\n

Author: Mihai Bazon

\n

Org version 7.7 with Emacs version 23

\nValidate XHTML 1.0\n\n
\n\n\n", + "readmeFilename": "README.html", + "bugs": { + "url": "https://github.com/mishoo/UglifyJS/issues" + }, + "homepage": "https://github.com/mishoo/UglifyJS", + "_id": "uglify-js@1.2.5", + "_from": "uglify-js@1.2.5" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json~ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json~ new file mode 100644 index 00000000..e4cb23d5 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json~ @@ -0,0 +1,24 @@ +{ + "name" : "uglify-js", + + "description" : "JavaScript parser and compressor/beautifier toolkit", + + "author" : { + "name" : "Mihai Bazon", + "email" : "mihai.bazon@gmail.com", + "url" : "http://mihai.bazon.net/blog" + }, + + "version" : "1.2.3", + + "main" : "./uglify-js.js", + + "bin" : { + "uglifyjs" : "./bin/uglifyjs" + }, + + "repository": { + "type": "git", + "url": "git@github.com:mishoo/UglifyJS.git" + } +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/beautify.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/beautify.js new file mode 100755 index 00000000..f19369e3 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/beautify.js @@ -0,0 +1,28 @@ +#! /usr/bin/env node + +global.sys = require("sys"); +var fs = require("fs"); + +var jsp = require("../lib/parse-js"); +var pro = require("../lib/process"); + +var filename = process.argv[2]; +fs.readFile(filename, "utf8", function(err, text){ + try { + var ast = time_it("parse", function(){ return jsp.parse(text); }); + ast = time_it("mangle", function(){ return pro.ast_mangle(ast); }); + ast = time_it("squeeze", function(){ return pro.ast_squeeze(ast); }); + var gen = time_it("generate", function(){ return pro.gen_code(ast, false); }); + sys.puts(gen); + } catch(ex) { + sys.debug(ex.stack); + sys.debug(sys.inspect(ex)); + sys.debug(JSON.stringify(ex)); + } +}); + +function time_it(name, cont) { + var t1 = new Date().getTime(); + try { return cont(); } + finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); } +}; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/testparser.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/testparser.js new file mode 100755 index 00000000..02c19a9c --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/testparser.js @@ -0,0 +1,403 @@ +#! /usr/bin/env node + +var parseJS = require("../lib/parse-js"); +var sys = require("sys"); + +// write debug in a very straightforward manner +var debug = function(){ + sys.log(Array.prototype.slice.call(arguments).join(', ')); +}; + +ParserTestSuite(function(i, input, desc){ + try { + parseJS.parse(input); + debug("ok " + i + ": " + desc); + } catch(e){ + debug("FAIL " + i + " " + desc + " (" + e + ")"); + } +}); + +function ParserTestSuite(callback){ + var inps = [ + ["var abc;", "Regular variable statement w/o assignment"], + ["var abc = 5;", "Regular variable statement with assignment"], + ["/* */;", "Multiline comment"], + ['/** **/;', 'Double star multiline comment'], + ["var f = function(){;};", "Function expression in var assignment"], + ['hi; // moo\n;', 'single line comment'], + ['var varwithfunction;', 'Dont match keywords as substrings'], // difference between `var withsomevar` and `"str"` (local search and lits) + ['a + b;', 'addition'], + ["'a';", 'single string literal'], + ["'a\\n';", 'single string literal with escaped return'], + ['"a";', 'double string literal'], + ['"a\\n";', 'double string literal with escaped return'], + ['"var";', 'string is a keyword'], + ['"variable";', 'string starts with a keyword'], + ['"somevariable";', 'string contains a keyword'], + ['"somevar";', 'string ends with a keyword'], + ['500;', 'int literal'], + ['500.;', 'float literal w/o decimals'], + ['500.432;', 'float literal with decimals'], + ['.432432;', 'float literal w/o int'], + ['(a,b,c);', 'parens and comma'], + ['[1,2,abc];', 'array literal'], + ['var o = {a:1};', 'object literal unquoted key'], + ['var o = {"b":2};', 'object literal quoted key'], // opening curly may not be at the start of a statement... + ['var o = {c:c};', 'object literal keyname is identifier'], + ['var o = {a:1,"b":2,c:c};', 'object literal combinations'], + ['var x;\nvar y;', 'two lines'], + ['var x;\nfunction n(){; }', 'function def'], + ['var x;\nfunction n(abc){; }', 'function def with arg'], + ['var x;\nfunction n(abc, def){ ;}', 'function def with args'], + ['function n(){ "hello"; }', 'function def with body'], + ['/a/;', 'regex literal'], + ['/a/b;', 'regex literal with flag'], + ['/a/ / /b/;', 'regex div regex'], + ['a/b/c;', 'triple division looks like regex'], + ['+function(){/regex/;};', 'regex at start of function body'], + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=86 + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=430 + + // first tests for the lexer, should also parse as program (when you append a semi) + + // comments + ['//foo!@#^&$1234\nbar;', 'single line comment'], + ['/* abcd!@#@$* { } && null*/;', 'single line multi line comment'], + ['/*foo\nbar*/;','multi line comment'], + ['/*x*x*/;','multi line comment with *'], + ['/**/;','empty comment'], + // identifiers + ["x;",'1 identifier'], + ["_x;",'2 identifier'], + ["xyz;",'3 identifier'], + ["$x;",'4 identifier'], + ["x$;",'5 identifier'], + ["_;",'6 identifier'], + ["x5;",'7 identifier'], + ["x_y;",'8 identifier'], + ["x+5;",'9 identifier'], + ["xyz123;",'10 identifier'], + ["x1y1z1;",'11 identifier'], + ["foo\\u00D8bar;",'12 identifier unicode escape'], + //["foo�bar;",'13 identifier unicode embedded (might fail)'], + // numbers + ["5;", '1 number'], + ["5.5;", '2 number'], + ["0;", '3 number'], + ["0.0;", '4 number'], + ["0.001;", '5 number'], + ["1.e2;", '6 number'], + ["1.e-2;", '7 number'], + ["1.E2;", '8 number'], + ["1.E-2;", '9 number'], + [".5;", '10 number'], + [".5e3;", '11 number'], + [".5e-3;", '12 number'], + ["0.5e3;", '13 number'], + ["55;", '14 number'], + ["123;", '15 number'], + ["55.55;", '16 number'], + ["55.55e10;", '17 number'], + ["123.456;", '18 number'], + ["1+e;", '20 number'], + ["0x01;", '22 number'], + ["0XCAFE;", '23 number'], + ["0x12345678;", '24 number'], + ["0x1234ABCD;", '25 number'], + ["0x0001;", '26 number'], + // strings + ["\"foo\";", '1 string'], + ["\'foo\';", '2 string'], + ["\"x\";", '3 string'], + ["\'\';", '4 string'], + ["\"foo\\tbar\";", '5 string'], + ["\"!@#$%^&*()_+{}[]\";", '6 string'], + ["\"/*test*/\";", '7 string'], + ["\"//test\";", '8 string'], + ["\"\\\\\";", '9 string'], + ["\"\\u0001\";", '10 string'], + ["\"\\uFEFF\";", '11 string'], + ["\"\\u10002\";", '12 string'], + ["\"\\x55\";", '13 string'], + ["\"\\x55a\";", '14 string'], + ["\"a\\\\nb\";", '15 string'], + ['";"', '16 string: semi in a string'], + ['"a\\\nb";', '17 string: line terminator escape'], + // literals + ["null;", "null"], + ["true;", "true"], + ["false;", "false"], + // regex + ["/a/;", "1 regex"], + ["/abc/;", "2 regex"], + ["/abc[a-z]*def/g;", "3 regex"], + ["/\\b/;", "4 regex"], + ["/[a-zA-Z]/;", "5 regex"], + + // program tests (for as far as they havent been covered above) + + // regexp + ["/foo(.*)/g;", "another regexp"], + // arrays + ["[];", "1 array"], + ["[ ];", "2 array"], + ["[1];", "3 array"], + ["[1,2];", "4 array"], + ["[1,2,,];", "5 array"], + ["[1,2,3];", "6 array"], + ["[1,2,3,,,];", "7 array"], + // objects + ["{};", "1 object"], + ["({x:5});", "2 object"], + ["({x:5,y:6});", "3 object"], + ["({x:5,});", "4 object"], + ["({if:5});", "5 object"], + ["({ get x() {42;} });", "6 object"], + ["({ set y(a) {1;} });", "7 object"], + // member expression + ["o.m;", "1 member expression"], + ["o['m'];", "2 member expression"], + ["o['n']['m'];", "3 member expression"], + ["o.n.m;", "4 member expression"], + ["o.if;", "5 member expression"], + // call and invoke expressions + ["f();", "1 call/invoke expression"], + ["f(x);", "2 call/invoke expression"], + ["f(x,y);", "3 call/invoke expression"], + ["o.m();", "4 call/invoke expression"], + ["o['m'];", "5 call/invoke expression"], + ["o.m(x);", "6 call/invoke expression"], + ["o['m'](x);", "7 call/invoke expression"], + ["o.m(x,y);", "8 call/invoke expression"], + ["o['m'](x,y);", "9 call/invoke expression"], + ["f(x)(y);", "10 call/invoke expression"], + ["f().x;", "11 call/invoke expression"], + + // eval + ["eval('x');", "1 eval"], + ["(eval)('x');", "2 eval"], + ["(1,eval)('x');", "3 eval"], + ["eval(x,y);", "4 eval"], + // new expression + ["new f();", "1 new expression"], + ["new o;", "2 new expression"], + ["new o.m;", "3 new expression"], + ["new o.m(x);", "4 new expression"], + ["new o.m(x,y);", "5 new expression"], + // prefix/postfix + ["++x;", "1 pre/postfix"], + ["x++;", "2 pre/postfix"], + ["--x;", "3 pre/postfix"], + ["x--;", "4 pre/postfix"], + ["x ++;", "5 pre/postfix"], + ["x /* comment */ ++;", "6 pre/postfix"], + ["++ /* comment */ x;", "7 pre/postfix"], + // unary operators + ["delete x;", "1 unary operator"], + ["void x;", "2 unary operator"], + ["+ x;", "3 unary operator"], + ["-x;", "4 unary operator"], + ["~x;", "5 unary operator"], + ["!x;", "6 unary operator"], + // meh + ["new Date++;", "new date ++"], + ["+x++;", " + x ++"], + // expression expressions + ["1 * 2;", "1 expression expressions"], + ["1 / 2;", "2 expression expressions"], + ["1 % 2;", "3 expression expressions"], + ["1 + 2;", "4 expression expressions"], + ["1 - 2;", "5 expression expressions"], + ["1 << 2;", "6 expression expressions"], + ["1 >>> 2;", "7 expression expressions"], + ["1 >> 2;", "8 expression expressions"], + ["1 * 2 + 3;", "9 expression expressions"], + ["(1+2)*3;", "10 expression expressions"], + ["1*(2+3);", "11 expression expressions"], + ["xy;", "13 expression expressions"], + ["x<=y;", "14 expression expressions"], + ["x>=y;", "15 expression expressions"], + ["x instanceof y;", "16 expression expressions"], + ["x in y;", "17 expression expressions"], + ["x&y;", "18 expression expressions"], + ["x^y;", "19 expression expressions"], + ["x|y;", "20 expression expressions"], + ["x+y>>= y;", "1 assignment"], + ["x <<= y;", "2 assignment"], + ["x = y;", "3 assignment"], + ["x += y;", "4 assignment"], + ["x /= y;", "5 assignment"], + // comma + ["x, y;", "comma"], + // block + ["{};", "1 block"], + ["{x;};", "2 block"], + ["{x;y;};", "3 block"], + // vars + ["var x;", "1 var"], + ["var x,y;", "2 var"], + ["var x=1,y=2;", "3 var"], + ["var x,y=2;", "4 var"], + // empty + [";", "1 empty"], + ["\n;", "2 empty"], + // expression statement + ["x;", "1 expression statement"], + ["5;", "2 expression statement"], + ["1+2;", "3 expression statement"], + // if + ["if (c) x; else y;", "1 if statement"], + ["if (c) x;", "2 if statement"], + ["if (c) {} else {};", "3 if statement"], + ["if (c1) if (c2) s1; else s2;", "4 if statement"], + // while + ["do s; while (e);", "1 while statement"], + ["do { s; } while (e);", "2 while statement"], + ["while (e) s;", "3 while statement"], + ["while (e) { s; };", "4 while statement"], + // for + ["for (;;) ;", "1 for statement"], + ["for (;c;x++) x;", "2 for statement"], + ["for (i;i> 1; +var c = 8 >>> 1; \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue34.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue34.js new file mode 100644 index 00000000..022f7a31 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue34.js @@ -0,0 +1,3 @@ +var a = {}; +a["this"] = 1; +a["that"] = 2; \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue4.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue4.js new file mode 100644 index 00000000..0b761037 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue4.js @@ -0,0 +1,3 @@ +var a = 2e3; +var b = 2e-3; +var c = 2e-5; \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue48.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue48.js new file mode 100644 index 00000000..031e85b3 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue48.js @@ -0,0 +1 @@ +var s, i; s = ''; i = 0; \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue50.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue50.js new file mode 100644 index 00000000..060f9df8 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue50.js @@ -0,0 +1,9 @@ +function bar(a) { + try { + foo(); + } catch(e) { + alert("Exception caught (foo not defined)"); + } + alert(a); // 10 in FF, "[object Error]" in IE +} +bar(10); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue53.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue53.js new file mode 100644 index 00000000..4f8b32f1 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue53.js @@ -0,0 +1 @@ +x = (y, z) diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue54.1.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue54.1.js new file mode 100644 index 00000000..967052e8 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue54.1.js @@ -0,0 +1,3 @@ +foo.toString(); +a.toString(16); +b.toString.call(c); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue68.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue68.js new file mode 100644 index 00000000..14054d01 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue68.js @@ -0,0 +1,5 @@ +function f() { + if (a) return; + g(); + function g(){} +}; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue69.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue69.js new file mode 100644 index 00000000..d25ecd67 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue69.js @@ -0,0 +1 @@ +[(a,b)] diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue9.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue9.js new file mode 100644 index 00000000..61588614 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue9.js @@ -0,0 +1,4 @@ +var a = { + a: 1, + b: 2, // <-- trailing comma +}; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/mangle.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/mangle.js new file mode 100644 index 00000000..c271a26d --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/mangle.js @@ -0,0 +1,5 @@ +(function() { + var x = function fun(a, fun, b) { + return fun; + }; +}()); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/null_string.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/null_string.js new file mode 100644 index 00000000..a675b1c5 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/null_string.js @@ -0,0 +1 @@ +var nullString = "\0" \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/strict-equals.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/strict-equals.js new file mode 100644 index 00000000..b631f4c3 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/strict-equals.js @@ -0,0 +1,3 @@ +typeof a === 'string' +b + "" !== c + "" +d < e === f < g diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/var.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/var.js new file mode 100644 index 00000000..609a35d2 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/var.js @@ -0,0 +1,3 @@ +// var declarations after each other should be combined +var a = 1; +var b = 2; \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/whitespace.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/whitespace.js new file mode 100644 index 00000000..6a15c464 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/whitespace.js @@ -0,0 +1,21 @@ +function id(a) { + // Form-Feed + // Vertical Tab + // No-Break Space + ᠎// Mongolian Vowel Separator +  // En quad +  // Em quad +  // En space +  // Em space +  // Three-Per-Em Space +  // Four-Per-Em Space +  // Six-Per-Em Space +  // Figure Space +  // Punctuation Space +  // Thin Space +  // Hair Space +  // Narrow No-Break Space +  // Medium Mathematical Space +  // Ideographic Space + return a; +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/with.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/with.js new file mode 100644 index 00000000..de266ed5 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/with.js @@ -0,0 +1,2 @@ +with({}) { +}; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/scripts.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/scripts.js new file mode 100644 index 00000000..5d334ff7 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/scripts.js @@ -0,0 +1,55 @@ +var fs = require('fs'), + uglify = require('../../uglify-js'), + jsp = uglify.parser, + nodeunit = require('nodeunit'), + path = require('path'), + pro = uglify.uglify; + +var Script = process.binding('evals').Script; + +var scriptsPath = __dirname; + +function compress(code) { + var ast = jsp.parse(code); + ast = pro.ast_mangle(ast); + ast = pro.ast_squeeze(ast, { no_warnings: true }); + ast = pro.ast_squeeze_more(ast); + return pro.gen_code(ast); +}; + +var testDir = path.join(scriptsPath, "compress", "test"); +var expectedDir = path.join(scriptsPath, "compress", "expected"); + +function getTester(script) { + return function(test) { + var testPath = path.join(testDir, script); + var expectedPath = path.join(expectedDir, script); + var content = fs.readFileSync(testPath, 'utf-8'); + var outputCompress = compress(content); + + // Check if the noncompressdata is larger or same size as the compressed data + test.ok(content.length >= outputCompress.length); + + // Check that a recompress gives the same result + var outputReCompress = compress(content); + test.equal(outputCompress, outputReCompress); + + // Check if the compressed output is what is expected + var expected = fs.readFileSync(expectedPath, 'utf-8'); + test.equal(outputCompress, expected.replace(/(\r?\n)+$/, "")); + + test.done(); + }; +}; + +var tests = {}; + +var scripts = fs.readdirSync(testDir); +for (var i in scripts) { + var script = scripts[i]; + if (/\.js$/.test(script)) { + tests[script] = getTester(script); + } +} + +module.exports = nodeunit.testCase(tests); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js new file mode 100644 index 00000000..256ad1c9 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js @@ -0,0 +1,13 @@ +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +var test_code = "var JSON;JSON||(JSON={});"; + +var ast = jsp.parse(test_code, false, false); +var nonembed_token_code = pro.gen_code(ast); +ast = jsp.parse(test_code, false, true); +var embed_token_code = pro.gen_code(ast); + +console.log("original: " + test_code); +console.log("no token: " + nonembed_token_code); +console.log(" token: " + embed_token_code); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js new file mode 100644 index 00000000..2c6257eb --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js @@ -0,0 +1,22315 @@ +/* Modernizr 2.0.6 (Custom Build) | MIT & BSD + * Build: http://www.modernizr.com/download/#-iepp + */ +;window.Modernizr=function(a,b,c){function w(a,b){return!!~(""+a).indexOf(b)}function v(a,b){return typeof a===b}function u(a,b){return t(prefixes.join(a+";")+(b||""))}function t(a){j.cssText=a}var d="2.0.6",e={},f=b.documentElement,g=b.head||b.getElementsByTagName("head")[0],h="modernizr",i=b.createElement(h),j=i.style,k,l=Object.prototype.toString,m={},n={},o={},p=[],q,r={}.hasOwnProperty,s;!v(r,c)&&!v(r.call,c)?s=function(a,b){return r.call(a,b)}:s=function(a,b){return b in a&&v(a.constructor.prototype[b],c)};for(var x in m)s(m,x)&&(q=x.toLowerCase(),e[q]=m[x](),p.push((e[q]?"":"no-")+q));t(""),i=k=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.3", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( !array ) { + return -1; + } + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
a"; + + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
t
"; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + + // Support interoperable removal of hyphenated or camelcased keys + if ( !thisCache[ name ] ) { + name = jQuery.camelCase( name ); + } + + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + nodeHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + hooks = boolHook; + + // Use nodeHook if available( IE6/7 ) + } else if ( nodeHook ) { + hooks = nodeHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + jQuery.attr( elem, name, "" ); + elem.removeAttribute( name ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + 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( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabindex propHook to attrHooks for back-compat +jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode; + return jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return (ret.nodeValue = value + ""); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.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( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = jQuery.nodeName( elem, "input" ) ? elem.type : "", + val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.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( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.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( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /
", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + col: [ 2, "", "
" ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + */ + +(function() { + this.loggly = function(opts) { + this.user_agent = get_agent(); + this.browser_size = get_size(); + log_methods = {'error': 5, 'warn': 4, 'info': 3, 'debug': 2, 'log': 1}; + if (!opts.url) throw new Error("Please include a Loggly HTTP URL."); + if (!opts.level) { + this.level = log_methods['info']; + } else { + this.level = log_methods[opts.level]; + } + this.log = function(data) { + if (log_methods['log'] == this.level) { + opts.data = data; + janky(opts); + } + }; + this.debug = function(data) { + if (log_methods['debug'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.info = function(data) { + if (log_methods['info'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.warn = function(data) { + if (log_methods['warn'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.error = function(data) { + if (log_methods['error'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + }; + this.janky = function(opts) { + janky._form(function(iframe, form) { + form.setAttribute("action", opts.url); + form.setAttribute("method", "post"); + janky._input(iframe, form, opts.data); + form.submit(); + setTimeout(function(){ + document.body.removeChild(iframe); + }, 2000); + }); + }; + this.janky._form = function(cb) { + var iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + iframe.style.display = "none"; + setTimeout(function() { + var form = iframe.contentWindow.document.createElement("form"); + iframe.contentWindow.document.body.appendChild(form); + cb(iframe, form); + }, 0); + }; + this.janky._input = function(iframe, form, data) { + var inp = iframe.contentWindow.document.createElement("input"); + inp.setAttribute("type", "hidden"); + inp.setAttribute("name", "source"); + inp.value = "castor " + data; + form.appendChild(inp); + }; + this.get_agent = function () { + return navigator.appCodeName + navigator.appName + navigator.appVersion; + }; + this.get_size = function () { + var width = 0; var height = 0; + if( typeof( window.innerWidth ) == 'number' ) { + width = window.innerWidth; height = window.innerHeight; + } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { + width = document.documentElement.clientWidth; height = document.documentElement.clientHeight; + } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { + width = document.body.clientWidth; height = document.body.clientHeight; + } + return {'height': height, 'width': width}; + }; +})(); + + +jsworld={};jsworld.formatIsoDateTime=function(a,b){if(typeof a==="undefined")a=new Date;if(typeof b==="undefined")b=false;var c=jsworld.formatIsoDate(a)+" "+jsworld.formatIsoTime(a);if(b){var d=a.getHours()-a.getUTCHours();var e=Math.abs(d);var f=a.getUTCMinutes();var g=a.getMinutes();if(g!=f&&f<30&&d<0)e--;if(g!=f&&f>30&&d>0)e--;var h;if(g!=f)h=":30";else h=":00";var i;if(e<10)i="0"+e+h;else i=""+e+h;if(d<0)i="-"+i;else i="+"+i;c=c+i}return c};jsworld.formatIsoDate=function(a){if(typeof a==="undefined")a=new Date;var b=a.getFullYear();var c=a.getMonth()+1;var d=a.getDate();return b+"-"+jsworld._zeroPad(c,2)+"-"+jsworld._zeroPad(d,2)};jsworld.formatIsoTime=function(a){if(typeof a==="undefined")a=new Date;var b=a.getHours();var c=a.getMinutes();var d=a.getSeconds();return jsworld._zeroPad(b,2)+":"+jsworld._zeroPad(c,2)+":"+jsworld._zeroPad(d,2)};jsworld.parseIsoDateTime=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)(\d\d)(\d\d)[T ](\d\d)(\d\d)(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d)(\d\d)(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date/time string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);var f=parseInt(b[4],10);var g=parseInt(b[5],10);var h=parseInt(b[6],10);if(d<1||d>12||e<1||e>31||f<0||f>23||g<0||g>59||h<0||h>59)throw"Error: Invalid ISO-8601 date/time value";var i=new Date(c,d-1,e,f,g,h);if(i.getDate()!=e||i.getMonth()+1!=d)throw"Error: Invalid date";return i};jsworld.parseIsoDate=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)(\d\d)(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);if(d<1||d>12||e<1||e>31)throw"Error: Invalid ISO-8601 date value";var f=new Date(c,d-1,e);if(f.getDate()!=e||f.getMonth()+1!=d)throw"Error: Invalid date";return f};jsworld.parseIsoTime=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d):(\d\d):(\d\d)/);if(b===null)b=a.match(/^(\d\d)(\d\d)(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date/time string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);if(c<0||c>23||d<0||d>59||e<0||e>59)throw"Error: Invalid ISO-8601 time value";return new Date(0,0,0,c,d,e)};jsworld._trim=function(a){var b=" \n\r\t\f \u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";for(var c=0;c=0;c--){if(b.indexOf(a.charAt(c))===-1){a=a.substring(0,c+1);break}}return b.indexOf(a.charAt(0))===-1?a:""};jsworld._isNumber=function(a){if(typeof a=="number")return true;if(typeof a!="string")return false;var b=a+"";return/^-?(\d+|\d*\.\d+)$/.test(b)};jsworld._isInteger=function(a){if(typeof a!="number"&&typeof a!="string")return false;var b=a+"";return/^-?\d+$/.test(b)};jsworld._isFloat=function(a){if(typeof a!="number"&&typeof a!="string")return false;var b=a+"";return/^-?\.\d+?$/.test(b)};jsworld._hasOption=function(a,b){if(typeof a!="string"||typeof b!="string")return false;if(b.indexOf(a)!=-1)return true;else return false};jsworld._stringReplaceAll=function(a,b,c){var d;if(b.length==1&&c.length==1){d="";for(var e=0;e0){if(d.length>0)g=parseInt(d.shift(),10);if(isNaN(g))throw"Error: Invalid grouping";if(g==-1){e=a.substring(0,f)+e;break}f-=g;if(f<1){e=a.substring(0,f+g)+e;break}e=c+a.substring(f,f+g)+e}return e};jsworld._formatFractionPart=function(a,b){for(var c=0;a.length0)return a;else throw"Empty or no string"};if(a==null||typeof a!="object")throw"Error: Invalid/missing locale properties";if(typeof a.decimal_point!="string")throw"Error: Invalid/missing decimal_point property";this.decimal_point=a.decimal_point;if(typeof a.thousands_sep!="string")throw"Error: Invalid/missing thousands_sep property";this.thousands_sep=a.thousands_sep;if(typeof a.grouping!="string")throw"Error: Invalid/missing grouping property";this.grouping=a.grouping;if(typeof a.int_curr_symbol!="string")throw"Error: Invalid/missing int_curr_symbol property";if(!/[A-Za-z]{3}.?/.test(a.int_curr_symbol))throw"Error: Invalid int_curr_symbol property";this.int_curr_symbol=a.int_curr_symbol;if(typeof a.currency_symbol!="string")throw"Error: Invalid/missing currency_symbol property";this.currency_symbol=a.currency_symbol;if(typeof a.frac_digits!="number"&&a.frac_digits<0)throw"Error: Invalid/missing frac_digits property";this.frac_digits=a.frac_digits;if(a.mon_decimal_point===null||a.mon_decimal_point==""){if(this.frac_digits>0)throw"Error: Undefined mon_decimal_point property";else a.mon_decimal_point=""}if(typeof a.mon_decimal_point!="string")throw"Error: Invalid/missing mon_decimal_point property";this.mon_decimal_point=a.mon_decimal_point;if(typeof a.mon_thousands_sep!="string")throw"Error: Invalid/missing mon_thousands_sep property";this.mon_thousands_sep=a.mon_thousands_sep;if(typeof a.mon_grouping!="string")throw"Error: Invalid/missing mon_grouping property";this.mon_grouping=a.mon_grouping;if(typeof a.positive_sign!="string")throw"Error: Invalid/missing positive_sign property";this.positive_sign=a.positive_sign;if(typeof a.negative_sign!="string")throw"Error: Invalid/missing negative_sign property";this.negative_sign=a.negative_sign;if(a.p_cs_precedes!==0&&a.p_cs_precedes!==1)throw"Error: Invalid/missing p_cs_precedes property, must be 0 or 1";this.p_cs_precedes=a.p_cs_precedes;if(a.n_cs_precedes!==0&&a.n_cs_precedes!==1)throw"Error: Invalid/missing n_cs_precedes, must be 0 or 1";this.n_cs_precedes=a.n_cs_precedes;if(a.p_sep_by_space!==0&&a.p_sep_by_space!==1&&a.p_sep_by_space!==2)throw"Error: Invalid/missing p_sep_by_space property, must be 0, 1 or 2";this.p_sep_by_space=a.p_sep_by_space;if(a.n_sep_by_space!==0&&a.n_sep_by_space!==1&&a.n_sep_by_space!==2)throw"Error: Invalid/missing n_sep_by_space property, must be 0, 1, or 2";this.n_sep_by_space=a.n_sep_by_space;if(a.p_sign_posn!==0&&a.p_sign_posn!==1&&a.p_sign_posn!==2&&a.p_sign_posn!==3&&a.p_sign_posn!==4)throw"Error: Invalid/missing p_sign_posn property, must be 0, 1, 2, 3 or 4";this.p_sign_posn=a.p_sign_posn;if(a.n_sign_posn!==0&&a.n_sign_posn!==1&&a.n_sign_posn!==2&&a.n_sign_posn!==3&&a.n_sign_posn!==4)throw"Error: Invalid/missing n_sign_posn property, must be 0, 1, 2, 3 or 4";this.n_sign_posn=a.n_sign_posn;if(typeof a.int_frac_digits!="number"&&a.int_frac_digits<0)throw"Error: Invalid/missing int_frac_digits property";this.int_frac_digits=a.int_frac_digits;if(a.int_p_cs_precedes!==0&&a.int_p_cs_precedes!==1)throw"Error: Invalid/missing int_p_cs_precedes property, must be 0 or 1";this.int_p_cs_precedes=a.int_p_cs_precedes;if(a.int_n_cs_precedes!==0&&a.int_n_cs_precedes!==1)throw"Error: Invalid/missing int_n_cs_precedes property, must be 0 or 1";this.int_n_cs_precedes=a.int_n_cs_precedes;if(a.int_p_sep_by_space!==0&&a.int_p_sep_by_space!==1&&a.int_p_sep_by_space!==2)throw"Error: Invalid/missing int_p_sep_by_spacev, must be 0, 1 or 2";this.int_p_sep_by_space=a.int_p_sep_by_space;if(a.int_n_sep_by_space!==0&&a.int_n_sep_by_space!==1&&a.int_n_sep_by_space!==2)throw"Error: Invalid/missing int_n_sep_by_space property, must be 0, 1, or 2";this.int_n_sep_by_space=a.int_n_sep_by_space;if(a.int_p_sign_posn!==0&&a.int_p_sign_posn!==1&&a.int_p_sign_posn!==2&&a.int_p_sign_posn!==3&&a.int_p_sign_posn!==4)throw"Error: Invalid/missing int_p_sign_posn property, must be 0, 1, 2, 3 or 4";this.int_p_sign_posn=a.int_p_sign_posn;if(a.int_n_sign_posn!==0&&a.int_n_sign_posn!==1&&a.int_n_sign_posn!==2&&a.int_n_sign_posn!==3&&a.int_n_sign_posn!==4)throw"Error: Invalid/missing int_n_sign_posn property, must be 0, 1, 2, 3 or 4";this.int_n_sign_posn=a.int_n_sign_posn;if(a==null||typeof a!="object")throw"Error: Invalid/missing time locale properties";try{this.abday=this._parseList(a.abday,7)}catch(b){throw"Error: Invalid abday property: "+b}try{this.day=this._parseList(a.day,7)}catch(b){throw"Error: Invalid day property: "+b}try{this.abmon=this._parseList(a.abmon,12)}catch(b){throw"Error: Invalid abmon property: "+b}try{this.mon=this._parseList(a.mon,12)}catch(b){throw"Error: Invalid mon property: "+b}try{this.d_fmt=this._validateFormatString(a.d_fmt)}catch(b){throw"Error: Invalid d_fmt property: "+b}try{this.t_fmt=this._validateFormatString(a.t_fmt)}catch(b){throw"Error: Invalid t_fmt property: "+b}try{this.d_t_fmt=this._validateFormatString(a.d_t_fmt)}catch(b){throw"Error: Invalid d_t_fmt property: "+b}try{var c=this._parseList(a.am_pm,2);this.am=c[0];this.pm=c[1]}catch(b){this.am="";this.pm=""}this.getAbbreviatedWeekdayName=function(a){if(typeof a=="undefined"||a===null)return this.abday;if(!jsworld._isInteger(a)||a<0||a>6)throw"Error: Invalid weekday argument, must be an integer [0..6]";return this.abday[a]};this.getWeekdayName=function(a){if(typeof a=="undefined"||a===null)return this.day;if(!jsworld._isInteger(a)||a<0||a>6)throw"Error: Invalid weekday argument, must be an integer [0..6]";return this.day[a]};this.getAbbreviatedMonthName=function(a){if(typeof a=="undefined"||a===null)return this.abmon;if(!jsworld._isInteger(a)||a<0||a>11)throw"Error: Invalid month argument, must be an integer [0..11]";return this.abmon[a]};this.getMonthName=function(a){if(typeof a=="undefined"||a===null)return this.mon;if(!jsworld._isInteger(a)||a<0||a>11)throw"Error: Invalid month argument, must be an integer [0..11]";return this.mon[a]};this.getDecimalPoint=function(){return this.decimal_point};this.getCurrencySymbol=function(){return this.currency_symbol};this.getIntCurrencySymbol=function(){return this.int_curr_symbol.substring(0,3)};this.currencySymbolPrecedes=function(){if(this.p_cs_precedes==1)return true;else return false};this.intCurrencySymbolPrecedes=function(){if(this.int_p_cs_precedes==1)return true;else return false};this.getMonetaryDecimalPoint=function(){return this.mon_decimal_point};this.getFractionalDigits=function(){return this.frac_digits};this.getIntFractionalDigits=function(){return this.int_frac_digits}};jsworld.NumericFormatter=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.format=function(a,b){if(typeof a=="string")a=jsworld._trim(a);if(!jsworld._isNumber(a))throw"Error: The input is not a number";var c=parseFloat(a,10);var d=jsworld._getPrecision(b);if(d!=-1)c=Math.round(c*Math.pow(10,d))/Math.pow(10,d);var e=jsworld._splitNumber(String(c));var f;if(c===0)f="0";else f=jsworld._hasOption("^",b)?e.integer:jsworld._formatIntegerPart(e.integer,this.lc.grouping,this.lc.thousands_sep);var g=d!=-1?jsworld._formatFractionPart(e.fraction,d):e.fraction;var h=g.length?f+this.lc.decimal_point+g:f;if(jsworld._hasOption("~",b)||c===0){return h}else{if(jsworld._hasOption("+",b)||c<0){if(c>0)return"+"+h;else if(c<0)return"-"+h;else return h}else{return h}}}};jsworld.DateTimeFormatter=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance.";this.lc=a;this.formatDate=function(a){var b=null;if(typeof a=="string"){try{b=jsworld.parseIsoDate(a)}catch(c){b=jsworld.parseIsoDateTime(a)}}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.d_fmt)};this.formatTime=function(a){var b=null;if(typeof a=="string"){try{b=jsworld.parseIsoTime(a)}catch(c){b=jsworld.parseIsoDateTime(a)}}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.t_fmt)};this.formatDateTime=function(a){var b=null;if(typeof a=="string"){b=jsworld.parseIsoDateTime(a)}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.d_t_fmt)};this._applyFormatting=function(a,b){b=b.replace(/%%/g,"%");b=b.replace(/%a/g,this.lc.abday[a.getDay()]);b=b.replace(/%A/g,this.lc.day[a.getDay()]);b=b.replace(/%b/g,this.lc.abmon[a.getMonth()]);b=b.replace(/%B/g,this.lc.mon[a.getMonth()]);b=b.replace(/%d/g,jsworld._zeroPad(a.getDate(),2));b=b.replace(/%e/g,jsworld._spacePad(a.getDate(),2));b=b.replace(/%F/g,a.getFullYear()+"-"+jsworld._zeroPad(a.getMonth()+1,2)+"-"+jsworld._zeroPad(a.getDate(),2));b=b.replace(/%h/g,this.lc.abmon[a.getMonth()]);b=b.replace(/%H/g,jsworld._zeroPad(a.getHours(),2));b=b.replace(/%I/g,jsworld._zeroPad(this._hours12(a.getHours()),2));b=b.replace(/%k/g,a.getHours());b=b.replace(/%l/g,this._hours12(a.getHours()));b=b.replace(/%m/g,jsworld._zeroPad(a.getMonth()+1,2));b=b.replace(/%n/g,"\n");b=b.replace(/%M/g,jsworld._zeroPad(a.getMinutes(),2));b=b.replace(/%p/g,this._getAmPm(a.getHours()));b=b.replace(/%P/g,this._getAmPm(a.getHours()).toLocaleLowerCase());b=b.replace(/%R/g,jsworld._zeroPad(a.getHours(),2)+":"+jsworld._zeroPad(a.getMinutes(),2));b=b.replace(/%S/g,jsworld._zeroPad(a.getSeconds(),2));b=b.replace(/%T/g,jsworld._zeroPad(a.getHours(),2)+":"+jsworld._zeroPad(a.getMinutes(),2)+":"+jsworld._zeroPad(a.getSeconds(),2));b=b.replace(/%w/g,this.lc.day[a.getDay()]);b=b.replace(/%y/g,(new String(a.getFullYear())).substring(2));b=b.replace(/%Y/g,a.getFullYear());b=b.replace(/%Z/g,"");b=b.replace(/%[a-zA-Z]/g,"");return b};this._hours12=function(a){if(a===0)return 12;else if(a>12)return a-12;else return a};this._getAmPm=function(a){if(a===0||a>12)return this.lc.pm;else return this.lc.am}};jsworld.MonetaryFormatter=function(a,b,c){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.currencyFractionDigits={AFN:0,ALL:0,AMD:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,COP:0,CRC:0,DJF:0,GNF:0,GYD:0,HUF:0,IDR:0,IQD:0,IRR:0,ISK:0,JOD:3,JPY:0,KMF:0,KRW:0,KWD:3,LAK:0,LBP:0,LYD:3,MGA:0,MMK:0,MNT:0,MRO:0,MUR:0,OMR:3,PKR:0,PYG:0,RSD:0,RWF:0,SLL:0,SOS:0,STD:0,SYP:0,TND:3,TWD:0,TZS:0,UGX:0,UZS:0,VND:0,VUV:0,XAF:0,XOF:0,XPF:0,YER:0,ZMK:0};if(typeof b=="string"){this.currencyCode=b.toUpperCase();var d=this.currencyFractionDigits[this.currencyCode];if(typeof d!="number")d=2;this.lc.frac_digits=d;this.lc.int_frac_digits=d}else{this.currencyCode=this.lc.int_curr_symbol.substring(0,3).toUpperCase()}this.intSep=this.lc.int_curr_symbol.charAt(3);if(this.currencyCode==this.lc.int_curr_symbol.substring(0,3)){this.internationalFormatting=false;this.curSym=this.lc.currency_symbol}else{if(typeof c=="string"){this.curSym=c;this.internationalFormatting=false}else{this.internationalFormatting=true}}this.getCurrencySymbol=function(){return this.curSym};this.currencySymbolPrecedes=function(a){if(typeof a=="string"&&a=="i"){if(this.lc.int_p_cs_precedes==1)return true;else return false}else{if(this.internationalFormatting){if(this.lc.int_p_cs_precedes==1)return true;else return false}else{if(this.lc.p_cs_precedes==1)return true;else return false}}};this.getDecimalPoint=function(){return this.lc.mon_decimal_point};this.getFractionalDigits=function(a){if(typeof a=="string"&&a=="i"){return this.lc.int_frac_digits}else{if(this.internationalFormatting)return this.lc.int_frac_digits;else return this.lc.frac_digits}};this.format=function(a,b){var c;if(typeof a=="string"){a=jsworld._trim(a);c=parseFloat(a);if(typeof c!="number"||isNaN(c))throw"Error: Amount string not a number"}else if(typeof a=="number"){c=a}else{throw"Error: Amount not a number"}var d=jsworld._getPrecision(b);if(d==-1){if(this.internationalFormatting||jsworld._hasOption("i",b))d=this.lc.int_frac_digits;else d=this.lc.frac_digits}c=Math.round(c*Math.pow(10,d))/Math.pow(10,d);var e=jsworld._splitNumber(String(c));var f;if(c===0)f="0";else f=jsworld._hasOption("^",b)?e.integer:jsworld._formatIntegerPart(e.integer,this.lc.mon_grouping,this.lc.mon_thousands_sep);var g;if(d==-1){if(this.internationalFormatting||jsworld._hasOption("i",b))g=jsworld._formatFractionPart(e.fraction,this.lc.int_frac_digits);else g=jsworld._formatFractionPart(e.fraction,this.lc.frac_digits)}else{g=jsworld._formatFractionPart(e.fraction,d)}var h;if(this.lc.frac_digits>0||g.length)h=f+this.lc.mon_decimal_point+g;else h=f;if(jsworld._hasOption("~",b)){return h}else{var i=jsworld._hasOption("!",b)?true:false;var j=c<0?"-":"+";if(this.internationalFormatting||jsworld._hasOption("i",b)){if(i)return this._formatAsInternationalCurrencyWithNoSym(j,h);else return this._formatAsInternationalCurrency(j,h)}else{if(i)return this._formatAsLocalCurrencyWithNoSym(j,h);else return this._formatAsLocalCurrency(j,h)}}};this._formatAsLocalCurrency=function(a,b){if(a=="+"){if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return"("+b+this.curSym+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return"("+this.curSym+b+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return"("+b+" "+this.curSym+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return"("+this.curSym+" "+b+")"}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b+" "+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+" "+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+" "+b+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+this.curSym+b}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.curSym+b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.curSym+" "+b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.curSym+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.curSym+b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+" "+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign+" "+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+this.curSym+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.curSym+this.lc.positive_sign+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.curSym+this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.curSym+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.curSym+" "+this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return"("+b+this.curSym+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return"("+this.curSym+b+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return"("+b+" "+this.curSym+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return"("+this.curSym+" "+b+")"}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b+" "+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+" "+b+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+this.curSym+b}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.curSym+b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.curSym+" "+b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.curSym+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.curSym+b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+" "+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign+" "+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+this.curSym+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.curSym+this.lc.negative_sign+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.curSym+this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.curSym+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.curSym+" "+this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsInternationalCurrency=function(a,b){if(a=="+"){if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return"("+b+this.currencyCode+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return"("+this.currencyCode+b+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return"("+b+this.intSep+this.currencyCode+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return"("+this.currencyCode+this.intSep+b+")"}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b+this.intSep+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+this.intSep+b+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.currencyCode+b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.intSep+b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.currencyCode+b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign+this.intSep+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.intSep+this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return"("+b+this.currencyCode+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return"("+this.currencyCode+b+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return"("+b+this.intSep+this.currencyCode+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return"("+this.currencyCode+this.intSep+b+")"}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b+this.intSep+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+this.intSep+b+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.currencyCode+b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.intSep+b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.currencyCode+b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign+this.intSep+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.intSep+this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsLocalCurrencyWithNoSym=function(a,b){if(a=="+"){if(this.lc.p_sign_posn===0){return"("+b+")"}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.n_sign_posn===0){return"("+b+")"}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsInternationalCurrencyWithNoSym=function(a,b){if(a=="+"){if(this.lc.int_p_sign_posn===0){return"("+b+")"}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.int_n_sign_posn===0){return"("+b+")"}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC_MONETARY definition"}};jsworld.NumericParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.parse=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=jsworld._trim(a);b=jsworld._stringReplaceAll(a,this.lc.thousands_sep,"");b=jsworld._stringReplaceAll(b,this.lc.decimal_point,".");if(jsworld._isNumber(b))return parseFloat(b,10);else throw"Parse error: Invalid number string"}};jsworld.DateTimeParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance.";this.lc=a;this.parseTime=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.t_fmt,a);var c=false;if(b.hour!==null&&b.minute!==null&&b.second!==null){c=true}else if(b.hourAmPm!==null&&b.am!==null&&b.minute!==null&&b.second!==null){if(b.am){b.hour=parseInt(b.hourAmPm,10)}else{if(b.hourAmPm==12)b.hour=0;else b.hour=parseInt(b.hourAmPm,10)+12}c=true}if(c)return jsworld._zeroPad(b.hour,2)+":"+jsworld._zeroPad(b.minute,2)+":"+jsworld._zeroPad(b.second,2);else throw"Parse error: Invalid/ambiguous time string"};this.parseDate=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.d_fmt,a);var c=false;if(b.year!==null&&b.month!==null&&b.day!==null){c=true}if(c)return jsworld._zeroPad(b.year,4)+"-"+jsworld._zeroPad(b.month,2)+"-"+jsworld._zeroPad(b.day,2);else throw"Parse error: Invalid date string"};this.parseDateTime=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.d_t_fmt,a);var c=false;var d=false;if(b.hour!==null&&b.minute!==null&&b.second!==null){c=true}else if(b.hourAmPm!==null&&b.am!==null&&b.minute!==null&&b.second!==null){if(b.am){b.hour=parseInt(b.hourAmPm,10)}else{if(b.hourAmPm==12)b.hour=0;else b.hour=parseInt(b.hourAmPm,10)+12}c=true}if(b.year!==null&&b.month!==null&&b.day!==null){d=true}if(d&&c)return jsworld._zeroPad(b.year,4)+"-"+jsworld._zeroPad(b.month,2)+"-"+jsworld._zeroPad(b.day,2)+" "+jsworld._zeroPad(b.hour,2)+":"+jsworld._zeroPad(b.minute,2)+":"+jsworld._zeroPad(b.second,2);else throw"Parse error: Invalid/ambiguous date/time string"};this._extractTokens=function(a,b){var c={year:null,month:null,day:null,hour:null,hourAmPm:null,am:null,minute:null,second:null,weekday:null};while(a.length>0){if(a.charAt(0)=="%"&&a.charAt(1)!=""){var d=a.substring(0,2);if(d=="%%"){b=b.substring(1)}else if(d=="%a"){for(var e=0;e31)throw"Parse error: Unrecognised day of the month (%e)";b=b.substring(f.length)}else if(d=="%F"){if(/^\d\d\d\d/.test(b)){c.year=parseInt(b.substring(0,4),10);b=b.substring(4)}else{throw"Parse error: Unrecognised date (%F)"}if(jsworld._stringStartsWith(b,"-"))b=b.substring(1);else throw"Parse error: Unrecognised date (%F)";if(/^0[1-9]|1[0-2]/.test(b)){c.month=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised date (%F)";if(jsworld._stringStartsWith(b,"-"))b=b.substring(1);else throw"Parse error: Unrecognised date (%F)";if(/^0[1-9]|[1-2][0-9]|3[0-1]/.test(b)){c.day=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised date (%F)"}else if(d=="%H"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised hour (%H)"}else if(d=="%I"){if(/^0[1-9]|1[0-2]/.test(b)){c.hourAmPm=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised hour (%I)"}else if(d=="%k"){var g=b.match(/^(\d{1,2})/);c.hour=parseInt(g,10);if(isNaN(c.hour)||c.hour<0||c.hour>23)throw"Parse error: Unrecognised hour (%k)";b=b.substring(g.length)}else if(d=="%l"){var g=b.match(/^(\d{1,2})/);c.hourAmPm=parseInt(g,10);if(isNaN(c.hourAmPm)||c.hourAmPm<1||c.hourAmPm>12)throw"Parse error: Unrecognised hour (%l)";b=b.substring(g.length)}else if(d=="%m"){if(/^0[1-9]|1[0-2]/.test(b)){c.month=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised month (%m)"}else if(d=="%M"){if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised minute (%M)"}else if(d=="%n"){if(b.charAt(0)=="\n")b=b.substring(1);else throw"Parse error: Unrecognised new line (%n)"}else if(d=="%p"){if(jsworld._stringStartsWith(b,this.lc.am)){c.am=true;b=b.substring(this.lc.am.length)}else if(jsworld._stringStartsWith(b,this.lc.pm)){c.am=false;b=b.substring(this.lc.pm.length)}else throw"Parse error: Unrecognised AM/PM value (%p)"}else if(d=="%P"){if(jsworld._stringStartsWith(b,this.lc.am.toLowerCase())){c.am=true;b=b.substring(this.lc.am.length)}else if(jsworld._stringStartsWith(b,this.lc.pm.toLowerCase())){c.am=false;b=b.substring(this.lc.pm.length)}else throw"Parse error: Unrecognised AM/PM value (%P)"}else if(d=="%R"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%R)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%R)";if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%R)"}else if(d=="%S"){if(/^[0-5][0-9]/.test(b)){c.second=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised second (%S)"}else if(d=="%T"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%T)";if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%T)";if(/^[0-5][0-9]/.test(b)){c.second=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)"}else if(d=="%w"){if(/^\d/.test(b)){c.weekday=parseInt(b.substring(0,1),10);b=b.substring(1)}else throw"Parse error: Unrecognised weekday number (%w)"}else if(d=="%y"){if(/^\d\d/.test(b)){var h=parseInt(b.substring(0,2),10);if(h>50)c.year=1900+h;else c.year=2e3+h;b=b.substring(2)}else throw"Parse error: Unrecognised year (%y)"}else if(d=="%Y"){if(/^\d\d\d\d/.test(b)){c.year=parseInt(b.substring(0,4),10);b=b.substring(4)}else throw"Parse error: Unrecognised year (%Y)"}else if(d=="%Z"){if(a.length===0)break}a=a.substring(2)}else{if(a.charAt(0)!=b.charAt(0))throw'Parse error: Unexpected symbol "'+b.charAt(0)+'" in date/time string';a=a.substring(1);b=b.substring(1)}}return c}};jsworld.MonetaryParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.parse=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._detectCurrencySymbolType(a);var c,d;if(b=="local"){c="local";d=a.replace(this.lc.getCurrencySymbol(),"")}else if(b=="int"){c="int";d=a.replace(this.lc.getIntCurrencySymbol(),"")}else if(b=="none"){c="local";d=a}else throw"Parse error: Internal assert failure";d=jsworld._stringReplaceAll(d,this.lc.mon_thousands_sep,"");d=d.replace(this.lc.mon_decimal_point,".");d=d.replace(/\s*/g,"");d=this._removeLocalNonNegativeSign(d,c);d=this._normaliseNegativeSign(d,c);if(jsworld._isNumber(d))return parseFloat(d,10);else throw"Parse error: Invalid currency amount string"};this._detectCurrencySymbolType=function(a){if(this.lc.getCurrencySymbol().length>this.lc.getIntCurrencySymbol().length){if(a.indexOf(this.lc.getCurrencySymbol())!=-1)return"local";else if(a.indexOf(this.lc.getIntCurrencySymbol())!=-1)return"int";else return"none"}else{if(a.indexOf(this.lc.getIntCurrencySymbol())!=-1)return"int";else if(a.indexOf(this.lc.getCurrencySymbol())!=-1)return"local";else return"none"}};this._removeLocalNonNegativeSign=function(a,b){a=a.replace(this.lc.positive_sign,"");if((b=="local"&&this.lc.p_sign_posn===0||b=="int"&&this.lc.int_p_sign_posn===0)&&/\(\d+\.?\d*\)/.test(a)){a=a.replace("(","");a=a.replace(")","")}return a};this._normaliseNegativeSign=function(a,b){a=a.replace(this.lc.negative_sign,"-");if(b=="local"&&this.lc.n_sign_posn===0||b=="int"&&this.lc.int_n_sign_posn===0){if(/^\(\d+\.?\d*\)$/.test(a)){a=a.replace("(","");a=a.replace(")","");return"-"+a}}if(b=="local"&&this.lc.n_sign_posn==2||b=="int"&&this.lc.int_n_sign_posn==2){if(/^\d+\.?\d*-$/.test(a)){a=a.replace("-","");return"-"+a}}if(b=="local"&&this.lc.n_cs_precedes===0&&this.lc.n_sign_posn==3||b=="local"&&this.lc.n_cs_precedes===0&&this.lc.n_sign_posn==4||b=="int"&&this.lc.int_n_cs_precedes===0&&this.lc.int_n_sign_posn==3||b=="int"&&this.lc.int_n_cs_precedes===0&&this.lc.int_n_sign_posn==4){if(/^\d+\.?\d*-$/.test(a)){a=a.replace("-","");return"-"+a}}return a}} + + +if(typeof POSIX_LC == "undefined") var POSIX_LC = {}; + +POSIX_LC.en_US = { + "decimal_point" : ".", + "thousands_sep" : ",", + "grouping" : "3", + "abday" : ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], + "day" : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], + "abmon" : ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], + "mon" : ["January","February","March","April","May","June","July","August","September","October","November","December"], + "d_fmt" : "%m/%e/%y", + "t_fmt" : "%I:%M:%S %p", + "d_t_fmt" : "%B %e, %Y %I:%M:%S %p %Z", + "am_pm" : ["AM","PM"], + "int_curr_symbol" : "USD ", + "currency_symbol" : "\u0024", + "mon_decimal_point" : ".", + "mon_thousands_sep" : ",", + "mon_grouping" : "3", + "positive_sign" : "", + "negative_sign" : "-", + "int_frac_digits" : 2, + "frac_digits" : 2, + "p_cs_precedes" : 1, + "n_cs_precedes" : 1, + "p_sep_by_space" : 0, + "n_sep_by_space" : 0, + "p_sign_posn" : 1, + "n_sign_posn" : 1, + "int_p_cs_precedes" : 1, + "int_n_cs_precedes" : 1, + "int_p_sep_by_space" : 0, + "int_n_sep_by_space" : 0, + "int_p_sign_posn" : 1, + "int_n_sign_posn" : 1 +} + +if(typeof POSIX_LC == "undefined") var POSIX_LC = {}; + +POSIX_LC.fr_FR = { + "decimal_point" : ",", + "thousands_sep" : "\u00a0", + "grouping" : "3", + "abday" : ["dim.","lun.","mar.", + "mer.","jeu.","ven.", + "sam."], + "day" : ["dimanche","lundi","mardi", + "mercredi","jeudi","vendredi", + "samedi"], + "abmon" : ["janv.","f\u00e9vr.","mars", + "avr.","mai","juin", + "juil.","ao\u00fbt","sept.", + "oct.","nov.","d\u00e9c."], + "mon" : ["janvier","f\u00e9vrier","mars", + "avril","mai","juin", + "juillet","ao\u00fbt","septembre", + "octobre","novembre","d\u00e9cembre"], + "d_fmt" : "%d/%m/%y", + "t_fmt" : "%H:%M:%S", + "d_t_fmt" : "%e %B %Y %H:%M:%S %Z", + "am_pm" : ["AM","PM"], + "int_curr_symbol" : "EUR ", + "currency_symbol" : "\u20ac", + "mon_decimal_point" : ",", + "mon_thousands_sep" : "\u00a0", + "mon_grouping" : "3", + "positive_sign" : "", + "negative_sign" : "-", + "int_frac_digits" : 2, + "frac_digits" : 2, + "p_cs_precedes" : 0, + "n_cs_precedes" : 0, + "p_sep_by_space" : 1, + "n_sep_by_space" : 1, + "p_sign_posn" : 1, + "n_sign_posn" : 1, + "int_p_cs_precedes" : 0, + "int_n_cs_precedes" : 0, + "int_p_sep_by_space" : 1, + "int_n_sep_by_space" : 1, + "int_p_sign_posn" : 1, + "int_n_sign_posn" : 1 +}; + +/** https://github.com/csnover/js-iso8601 */(function(n,f){var u=n.parse,c=[1,4,5,6,7,10,11];n.parse=function(t){var i,o,a=0;if(o=/^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(t)){for(var v=0,r;r=c[v];++v)o[r]=+o[r]||0;o[2]=(+o[2]||1)-1,o[3]=+o[3]||1,o[8]!=="Z"&&o[9]!==f&&(a=o[10]*60+o[11],o[9]==="+"&&(a=0-a)),i=n.UTC(o[1],o[2],o[3],o[4],o[5]+a,o[6],o[7])}else i=u?u(t):NaN;return i}})(Date) + +/*! + * geo-location-javascript v0.4.3 + * http://code.google.com/p/geo-location-javascript/ + * + * Copyright (c) 2009 Stan Wiechers + * Licensed under the MIT licenses. + * + * Revision: $Rev: 68 $: + * Author: $Author: whoisstan $: + * Date: $Date: 2010-02-15 13:42:19 +0100 (Mon, 15 Feb 2010) $: + */ +var geo_position_js=function() { + + var pub = {}; + var provider=null; + + pub.getCurrentPosition = function(successCallback,errorCallback,options) + { + provider.getCurrentPosition(successCallback, errorCallback,options); + } + + pub.init = function() + { + try + { + if (typeof(geo_position_js_simulator)!="undefined") + { + provider=geo_position_js_simulator; + } + else if (typeof(bondi)!="undefined" && typeof(bondi.geolocation)!="undefined") + { + provider=bondi.geolocation; + } + else if (typeof(navigator.geolocation)!="undefined") + { + provider=navigator.geolocation; + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + function _successCallback(p) + { + //for mozilla geode,it returns the coordinates slightly differently + if(typeof(p.latitude)!="undefined") + { + successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude,longitude:p.longitude}}); + } + else + { + successCallback(p); + } + } + provider.getCurrentPosition(_successCallback,errorCallback,options); + } + } + else if(typeof(window.google)!="undefined" && typeof(google.gears)!="undefined") + { + provider=google.gears.factory.create('beta.geolocation'); + } + else if ( typeof(Mojo) !="undefined" && typeof(Mojo.Service.Request)!="Mojo.Service.Request") + { + provider=true; + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + + parameters={}; + if(options) + { + //http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition + if (options.enableHighAccuracy && options.enableHighAccuracy==true) + { + parameters.accuracy=1; + } + if (options.maximumAge) + { + parameters.maximumAge=options.maximumAge; + } + if (options.responseTime) + { + if(options.responseTime<5) + { + parameters.responseTime=1; + } + else if (options.responseTime<20) + { + parameters.responseTime=2; + } + else + { + parameters.timeout=3; + } + } + } + + + r=new Mojo.Service.Request('palm://com.palm.location', { + method:"getCurrentPosition", + parameters:parameters, + onSuccess: function(p){successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude, longitude:p.longitude,heading:p.heading}});}, + onFailure: function(e){ + if (e.errorCode==1) + { + errorCallback({code:3,message:"Timeout"}); + } + else if (e.errorCode==2) + { + errorCallback({code:2,message:"Position Unavailable"}); + } + else + { + errorCallback({code:0,message:"Unknown Error: webOS-code"+errorCode}); + } + } + }); + } + + } + else if (typeof(device)!="undefined" && typeof(device.getServiceObject)!="undefined") + { + provider=device.getServiceObject("Service.Location", "ILocation"); + + //override default method implementation + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + function callback(transId, eventCode, result) { + if (eventCode == 4) + { + errorCallback({message:"Position unavailable", code:2}); + } + else + { + //no timestamp of location given? + successCallback({timestamp:null, coords: {latitude:result.ReturnValue.Latitude, longitude:result.ReturnValue.Longitude, altitude:result.ReturnValue.Altitude,heading:result.ReturnValue.Heading}}); + } + } + //location criteria + var criteria = new Object(); + criteria.LocationInformationClass = "BasicLocationInformation"; + //make the call + provider.ILocation.GetLocation(criteria,callback); + } + } + } + catch (e){ + alert("error="+e); + if(typeof(console)!="undefined") + { + console.log(e); + } + return false; + } + return provider!=null; + } + + + return pub; +}(); +// Couldn't get unminified version to work , go here for docs => https://github.com/iamnoah/writeCapture +(function(E,a){var j=a.document;function A(Q){var Z=j.createElement("div");j.body.insertBefore(Z,null);E.replaceWith(Z,'\n
\n
\n
\n \n\n
\n
\n \n
\n

'); + __out.push(__sanitize(t('Invite Link'))); + __out.push(' '); + __out.push(__sanitize(USER.referral_url)); + __out.push('

\n\n \n\n
\n\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/login": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('
\n\t

'); + __out.push(__sanitize(t('Sign In'))); + __out.push('

\n\t
\n\t\t
\n\n\t\t\t
\n\t\t\t\t\n\t\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t
\n\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t\n\t\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t
\n\n\t\t\t
\n\n
\n\n

'); + __out.push(__sanitize(t('Forgot Password?'))); + __out.push('

\n\n\t\t
\n\t
\n
\n\n
\n
\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/modules/credit_card": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var printCard; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + if (this.cards === "new") { + __out.push('\n
\n
\n
\n
\n
\n
\n \n \n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n
\n \n \n
\n
\n
\n \n \n
\n
\n
\n \n \n
\n
\n
\n \n
\n
\n
\n'); + } else { + __out.push('\n '); + printCard = __bind(function(card, index) { + var exp, style; + __out.push('\n
\n '); + style = "background-position:-173px"; + __out.push('\n '); + if (card.get("card_type") === "Visa") { + style = "background-position:0px"; + } + __out.push('\n '); + if (card.get("card_type") === "MasterCard") { + style = "background-position:-42px"; + } + __out.push('\n '); + if (card.get("card_type") === "American Express") { + style = "background-position:-130px"; + } + __out.push('\n '); + if (card.get("card_type") === "Discover Card") { + style = "background-position:-85px"; + } + __out.push('\n
\n
\n ****'); + __out.push(__sanitize(card.get("card_number"))); + __out.push('\n \n '); + if (card.get("card_expiration")) { + __out.push('\n '); + __out.push(__sanitize(t('Expiry'))); + __out.push('\n '); + exp = card.get('card_expiration').split('-'); + __out.push('\n '); + __out.push(__sanitize("" + exp[0] + "-" + exp[1])); + __out.push('\n '); + } + __out.push('\n \n \n \n '); + if (card.get("default")) { + __out.push('\n ('); + __out.push(__sanitize(t('default card'))); + __out.push(')\n '); + } + __out.push('\n '); + if (this.cards.length > 1 && !card.get("default")) { + __out.push('\n '); + __out.push(__sanitize(t('make default'))); + __out.push('\n '); + } + __out.push('\n \n '); + __out.push(__sanitize(t('Edit'))); + __out.push('\n \n '); + if (this.cards.length > 1) { + __out.push('\n '); + __out.push(__sanitize(t('Delete'))); + __out.push('\n '); + } + __out.push('\n
\n '); + _.each(this.cards.models, printCard); + __out.push('\n
\n
\n\n'); + } + __out.push('\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/modules/sub_header": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('
\n
'); + __out.push(__sanitize(this.heading)); + __out.push('
\n
\n '); + if (window.USER.first_name) { + __out.push('\n '); + __out.push(__sanitize(t('Hello Greeting', { + name: USER.first_name + }))); + __out.push('\n '); + } + __out.push('\n
\n
\n
\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/promotions": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var promo, _i, _len, _ref; + __out.push(require('templates/clients/modules/sub_header').call(this, { + heading: t("Promotions") + })); + __out.push('\n\n
\n
\n
\n \n \n
\n
\n \n \n\n \n
\n '); + if (this.promos.length > 0) { + __out.push('\n
\n

'); + __out.push(__sanitize(t('Your Available Promotions'))); + __out.push('

\n \n \n\n \n \n \n \n \n \n \n \n '); + _ref = this.promos; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + promo = _ref[_i]; + __out.push('\n \n \n \n \n \n \n '); + } + __out.push('\n \n
'); + __out.push(__sanitize(t('Code'))); + __out.push(''); + __out.push(__sanitize(t('Details'))); + __out.push(''); + __out.push(__sanitize(t('Starts'))); + __out.push(''); + __out.push(__sanitize(t('Expires'))); + __out.push('
'); + __out.push(__sanitize(promo.code)); + __out.push(''); + __out.push(__sanitize(promo.description)); + __out.push(''); + __out.push(__sanitize(app.helpers.formatDate(promo.starts_at, true, "America/Los_Angeles"))); + __out.push(''); + __out.push(__sanitize(app.helpers.formatDate(promo.ends_at, true, "America/Los_Angeles"))); + __out.push('
\n
\n '); + } else { + __out.push('\n\n

'); + __out.push(__sanitize(t('No Active Promotions'))); + __out.push('

\n '); + } + __out.push('\n\n
\n
\n
\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/request": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var showFavoriteLocation; + showFavoriteLocation = function(location, index) { + var alphabet; + __out.push('\n '); + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + __out.push('\n
\n '); + __out.push(__sanitize(location.nickname)); + return __out.push('\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n

'); + __out.push(__sanitize(t('Driver Name:'))); + __out.push('

\n

\n
\n

'); + __out.push(__sanitize(t('Driver #:'))); + __out.push('

\n

\n
\n

'); + __out.push(__sanitize(t('Pickup Address:'))); + __out.push('

\n

\n
\n ');
+      __out.push(__sanitize(t('Add to Favorite Locations')));
+      __out.push('\n
\n
\n

\n '); + __out.push(__sanitize(t('Nickname:'))); + __out.push('\n \n \n \n \n
\n
\n
\n
\n

'); + __out.push(__sanitize(t('Your last trip'))); + __out.push('

\n
\n \n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n \n \n
\n \n
\n \n
\n \n
\n \n\n
\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/shared/menu": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "translations/en": function(exports, require, module) {(function() { + exports.translations = { + "Uber": "Uber", + "Sign Up": "Sign Up", + "Ride Request": "Ride Request", + "Invite Friends": "Invite Friends", + "Promotions": "Promotions", + "Billing": "Billing", + "Settings": "Settings", + "Forgot Password?": "Forgot Password?", + "Password Recovery": "Password Recovery", + "Login": "Login", + "Trip Detail": "Trip Detail", + "Password Reset": "Password Reset", + "Confirm Email": "Confirm Email", + "Request Ride": "Request Ride", + "Credit Card Number": "Credit Card Number", + "month": "month", + "01-Jan": "01-Jan", + "02-Feb": "02-Feb", + "03-Mar": "03-Mar", + "04-Apr": "04-Apr", + "05-May": "05-May", + "06-Jun": "06-Jun", + "07-Jul": "07-Jul", + "08-Aug": "08-Aug", + "09-Sep": "09-Sep", + "10-Oct": "10-Oct", + "11-Nov": "11-Nov", + "12-Dec": "12-Dec", + "year": "year", + "CVV": "CVV", + "Category": "Category", + "personal": "personal", + "business": "business", + "Default Credit Card": "Default Credit Card", + "Add Credit Card": "Add Credit Card", + "Expiry": "Expiry", + "default card": "default card", + "make default": "make default", + "Edit": "Edit", + "Delete": "Delete", + "Expiry Month": "Expiry Month", + "Expiry Year": "Expiry Year", + "Unable to Verify Card": "Unable to verify card at this time. Please try again later.", + "Credit Card Update Succeeded": "Your card has been successfully updated!", + "Credit Card Update Failed": "We couldn't save your changes. Please try again in a few minutes.", + "Credit Card Delete Succeeded": "Your card has been deleted!", + "Credit Card Delete Failed": "We were unable to delete your card. Please try again later.", + "Credit Card Update Category Succeeded": "Successfully changed card category!", + "Credit Card Update Category Failed": "We couldn't change your card category. Please try again in a few minutes.", + "Credit Card Update Default Succeeded": "Successfully changed default card!", + "Credit Card Update Default Failed": "We couldn't change your default card. Please try again in a few minutes.", + "Hello Greeting": "Hello, <%= name %>", + "Card Ending in": "Card Ending in", + "Trip Map": "Trip Map", + "Amount": "Amount: <%= amount %>", + "Last Attempt to Bill": "Last Attempt to Bill: <%= date %>", + "Charge": "Charge", + "Uber Credit Balance Note": "Your account has an UberCredit balance of <%= amount %>. When billing for trips, we'll deplete your UberCredit balance before applying charges to your credit card.", + "Please Add Credit Card": "Please add a credit card to bill your outstanding charges.", + "Credit Cards": "Credit Cards", + "add a new credit card": "add a new credit card", + "Account Balance": "Account Balance", + "Arrears": "Arrears", + "Billing Succeeded": "Your card was successfully billed.", + "Confirm Email Succeeded": "Successfully confirmed email token, redirecting to log in page...", + "Confirm Email Failed": "Unable to confirm email. Please contact support@uber.com if this problem persists.", + "Email Already Confirmed": "Your email address has already been confirmed, redirecting to log in page...", + "Credit Card Added": "Credit Card Added", + "No Credit Card": "No Credit Card", + "Mobile Number Confirmed": "Mobile Number Confirmed", + "No Confirmed Mobile": "No Confirmed Mobile", + "E-mail Address Confirmed": "E-mail Address Confirmed", + "No Confirmed E-mail": "No Confirmed E-mail", + 'Reply to sign up text': 'Reply "GO" to the text message you received at sign up.', + "Resend text message": "Resend text message", + "Click sign up link": "Click the link in the email you received at sign up.", + "Resend email": "Resend email", + "Add a credit card to ride": "Add a credit card and you'll be ready to ride Uber.", + "Your Most Recent Trip": "Your Most Recent Trip", + "details": "details", + "Your Trip History ": "Your Trip History ", + "Status": "Status", + "Here's how it works:": "Here's how it works:", + "Show all trips": "Show all trips", + "Set your location:": "Set your location:", + "App search for address": "iPhone/Android app: fix the pin or search for an address", + "SMS text address": "SMS: text your address to UBRCAB (827222)", + "Confirm pickup request": "Confirm your pickup request", + "Uber sends ETA": "Uber will send you an ETA (usually within 5-10 minutes)", + "Car arrives": "When your car is arriving, Uber will inform you again.", + "Ride to destination": "Hop in the car and tell the driver your destination.", + "Thank your driver": "That’s it! Please thank your driver but remember that your tip is included and no cash is necessary.", + "Trip started here": "Trip started here", + "Trip ended here": "Trip ended here", + "Sending Email": "Sending email...", + "Resend Email Succeeded": "We just sent the email. Please click on the confirmation link you recieve.", + "Resend Email Failed": "There was an error sending the email. Please contact support if the problem persists.", + "Resend Text Succeeded": 'We just sent the text message. Please reply "GO" to the message you recieve. It may take a few minutes for the message to reach you phone.', + "Resend Text Failed": "There was an error sending the text message. Please contact support if the problem persists.", + "Password Reset Error": "There was an error processing your password reset request.", + "New Password": "New Password", + "Forgot Password": "Forgot Password", + "Forgot Password Error": "Your email address could not be found. Please make sure to use the same email address you used when you signed up.", + "Forgot Password Success": "Please check your email for a link to reset your password.", + "Forgot Password Enter Email": 'Enter your email address and Uber will send you a link to reset your password. If you remember your password, you can sign in here.', + "Invite friends": "Invite friends", + "Give $ Get $": "Give $10, Get $10", + "Give $ Get $ Description": "Every friend you invite to Uber gets $10 of Uber credit. After someone you’ve invited takes his/her first ride, you get $10 of Uber credits too!", + "What are you waiting for?": "So, what are you waiting for? Invite away!", + "Tweet": "Tweet", + "Invite Link": "Email or IM this link to your friends:", + "Email Address": "Email Address", + "Reset Password": "Reset Password", + "Enter Promotion Code": "If you have a promotion code, enter it here:", + "Your Active Promotions": "Your Active Promotions", + "Code": "Code", + "Details": "Details", + "Trips Remaining": "Trips Remaining", + "Expires": "Expires", + "No Active Promotions": "There are no active promotions on your account.", + "Your Available Promotions": "Your Available Promotions", + "Where do you want us to pick you up?": "Where do you want us to pick you up?", + "Address to search": "Address to search", + "Search": "Search", + "Driver Name:": "Driver Name:", + "Driver #:": "Driver #:", + "Pickup Address:": "Pickup Address:", + "Add to Favorite Locations": "Add to Favorite Locations", + "Star": "Star", + "Nickname:": "Nickname:", + "Add": "Add", + "Your last trip": "Your last trip", + "Please rate your driver:": "Please rate your driver:", + "Comments: (optional)": "Comments: (optional)", + "Rate Trip": "Rate Trip", + "Pickup time:": "Pickup time:", + "Miles:": "Miles:", + "Trip time:": "Trip time:", + "Fare:": "Fare:", + "Favorite Locations": "Favorite Locations", + "Search Results": "Search Results", + "You have no favorite locations saved.": "You have no favorite locations saved.", + "Loading...": "Loading...", + "Request Pickup": "Request Pickup", + "Cancel Pickup": "Cancel Pickup", + "Requesting Closest Driver": "Requesting the closest driver to pick you up...", + "En Route": "You are currently en route...", + "Rate Last Trip": "Please rate your trip to make another request", + "Rate Before Submitting": "Please rate your trip before submitting the form", + "Address too short": "Address too short", + "or did you mean": "or did you mean", + "Search Address Failed": "Unable to find the given address. Please enter another address close to your location.", + "Sending pickup request...": "Sending pickup request...", + "Cancel Request Prompt": "Are you sure you want to cancel your request?", + "Cancel Request Arrived Prompt": 'Are you sure you want to cancel your request? Your driver has arrived so there is a $10 cancellation fee. It may help to call your driver now', + "Favorite Location Nickname Length Error": "Nickname has to be atleast 3 characters", + "Favorite Location Save Succeeded": "Location Saved!", + "Favorite Location Save Failed": "Unable to save your location. Please try again later.", + "Favorite Location Title": "Favorite Location <%= id %>", + "Search Location Title": "Search Location <%= id %>", + "ETA Message": "ETA: Around <%= minutes %> Minutes", + "Nearest Cab Message": "The closest driver is approximately <%= minutes %> minute(s) away", + "Arrival ETA Message": "Your Uber will arrive in about <%= minutes %> minute(s)", + "Arriving Now Message": "Your Uber is arriving now...", + "Rating Driver Failed": "Unable to contact server. Please try again later or email support if this issue persists.", + "Account Information": "Account Information", + "Mobile Phone Information": "Mobile Phone Information", + "settings": "settings", + "Information": "Information", + "Picture": "Picture", + "Change password": "Change password", + "Your current Picture": "Your current Picture", + "Your Favorite Locations": "Your Favorite Locations", + "You have no favorite locations saved.": "You have no favorite locations saved.", + "Purpose of Mobile": "We send text messages to your mobile phone to tell you when your driver is arriving. You can also request trips using text messages.", + "Country": "Country", + "Mobile Number": "Mobile Number", + "Submit": "Submit", + "Favorite Location": "Favorite Location", + "No Approximate Address": "Could not find an approximate address", + "Address:": "Address:", + "Information Update Succeeded": "Your information has been updated!", + "Information Update Failed": "We couldn't update your information. Please try again in few minutes or contact support if the problem persists.", + "Location Delete Succeeded": "Location deleted!", + "Location Delete Failed": "We were unable to delete your favorite location. Please try again later or contact support of the issue persists.", + "Location Edit Succeeded": "Changes Saved!", + "Location Edit Failed": "We couldn't save your changes. Please try again in a few minutes.", + "Picture Update Succeeded": "Your picture has been updated!", + "Picture Update Failed": "We couldn't change your picture. Please try again in a few minutes.", + "Personal Information": "Personal Information", + "Mobile Phone Number": "Mobile Phone Number", + "Payment Information": "Payment Information", + "Purpose of Credit Card": "We keep your credit card on file so that your trip go as fast as possible. You will not be charged until you take a trip.", + "Your card will not be charged until you take a trip.": "Your card will not be charged until you take a trip.", + "Credit Card Number": "Credit Card Number", + "Expiration Date": "Expiration Date", + "Promotion Code": "Promotion Code", + "Enter Promo Here": "If you have a code for a promotion, invitation or group deal, you can enter it here.", + "Promotion Code Input Label": "Promotion, Invite or Groupon Code (optional)", + "Terms and Conditions": "Terms and Conditions", + "HELP": "HELP", + "STOP": "STOP", + "Legal Information": "Legal Information", + "Sign Up Agreement": "By signing up, I agree to the Uber <%= terms_link %> and <%= privacy_link %> and understand that Uber is a request tool, not a transportation carrier.", + "Sign Up Agreement Error": "You must agree to the Uber Terms and Conditions and Privacy Policy to continue.", + "Message and Data Rates Disclosure": "Message and Data Rates May Apply. Reply <%= help_string %> to 827-222 for help. Reply <%= stop_string %> to 827-222 to stop texts. For additional assistance, visit support.uber.com or call (866) 576-1039. Supported Carriers: AT&T, Sprint, Verizon, and T-Mobile.", + "I Agree": "I agree to the Terms & Conditions and Privacy Policy", + "Security Code": "Security Code", + "Type of Card": "Type of Card", + "Personal": "Personal", + "Business": "Business", + "Code": "Code", + "Zip or Postal Code": "Zip or Postal Code", + "Your Trip": "Your Trip", + "Trip Info": "Trip Info", + "Request a fare review": "Request a fare review", + "Fare Review Submitted": "Your fare review has been submitted. We'll get back to you soon about your request. Sorry for any inconvenience this may have caused!", + "Fair Price Consideration": "We're committed to delivering Uber service at a fair price. Before requesting a fare review, please consider:", + "Your Fare Calculation": "Your Fare Calculation", + "Charges": "Charges", + "Discounts": "Discounts", + "Total Charge": "Total Charge", + "Uber pricing information": "Uber pricing information", + "Uber Pricing Information Message": "<%= learn_link %> is published on our website.", + "GPS Point Capture Disclosure": "Due to a finite number of GPS point captures, corners on your trip map may appear cut off or rounded. These minor inaccuracies result in a shorter measured distance, which always results in a cheaper trip.", + "Fare Review Note": "Please elaborate on why this trip requires a fare review. Your comments below will help us better establish the correct price for your trip:", + "Fare Review Error": "There was an error submitting the review. Please ensure that you have a message.", + "Sign In": "Sign In" + }; +}).call(this); +}, "translations/fr": function(exports, require, module) {(function() { + exports.translations = { + "Uber": "Uber", + "Sign Up": "Inscription", + "Ride Request": "Passer une Commande", + "Invite Friends": "Inviter vos Amis", + "Promotions": "Promotions", + "Billing": "Paiement", + "Settings": "Paramètres", + "Forgot Password?": "Mot de passe oublié ?", + "Password Recovery": "Récupération du mot de passe", + "Login": "Connexion", + "Trip Detail": "Détail de la Course", + "Password Reset": "Réinitialisation du mot de passe", + "Confirm Email": "Confirmation de l’e-mail", + "Request Ride": "Passer une Commande", + "Credit Card Number": "Numéro de Carte de Crédit", + "month": "mois", + "01-Jan": "01-Jan", + "02-Feb": "02-Fév", + "03-Mar": "03-Mar", + "04-Apr": "04-Avr", + "05-May": "05-Mai", + "06-Jun": "06-Juin", + "07-Jul": "07-Jui", + "08-Aug": "08-Aoû", + "09-Sep": "09-Sep", + "10-Oct": "10-Oct", + "11-Nov": "11-Nov", + "12-Dec": "12-Déc", + "year": "année", + "CVV": "Code de Sécurité", + "Category": "Type", + "personal": "personnel", + "business": "entreprise", + "Default Credit Card": "Carte par Défaut", + "Add Credit Card": "Ajouter une Carte", + "Expiry": "Expire", + "default card": "carte par défaut", + "make default": "choisir par défaut", + "Edit": "Modifier", + "Delete": "Supprimer", + "Expiry Month": "Mois d’Expiration", + "Expiry Year": "Année d’Expiration", + "Unable to Verify Card": "Impossible de vérifier la carte pour le moment. Merci de réessayer un peu plus tard.", + "Credit Card Update Succeeded": "Votre carte a été mise à jour avec succès !", + "Credit Card Update Failed": "Nous ne pouvons enregistrer vos changements. Merci de réessayer dans quelques minutes.", + "Credit Card Delete Succeeded": "Votre carte a été supprimée !", + "Credit Card Delete Failed": "Nous n’avons pas été en mesure de supprimer votre carte. Merci de réessayer plus tard.", + "Credit Card Update Category Succeeded": "Changement de catégorie de carte réussi !", + "Credit Card Update Category Failed": "Nous ne pouvons pas changer la catégorie de votre carte. Merci de réessayer dans quelques minutes.", + "Credit Card Update Default Succeeded": "Carte par défaut changée avec succès !", + "Credit Card Update Default Failed": "Nous ne pouvons pas changer votre carte par défaut. Merci de réessayer dans quelques minutes.", + "Hello Greeting": "Bonjour, <%= name %>", + "Card Ending in": "La carte expire dans", + "Trip Map": "Carte des Courses", + "Amount": "Montant: <%= amount %>", + "Last Attempt to Bill": "Dernière tentative de prélèvement : <%= date %>", + "Charge": "Débit", + "Uber Credit Balance Note": "Votre compte a un solde de <%= amount %> UberCredits. Lorsque nous facturons des courses, nous réduirons votre solde d’UberCredits avant de prélever votre carte de crédit.", + "Please Add Credit Card": "Merci d’ajouter une carte de crédit pour que nous puissions vous facturer.", + "Credit Cards": "Cartes de crédit", + "add a new credit card": "Ajouter une nouvelle carte de crédit", + "Account Balance": "Solde du compte", + "Arrears": "Arriérés", + "Billing Succeeded": "Votre carte a été correctement débitée.", + "Confirm Email Succeeded": "L’adresse e-mail a bien été validée, vous êtes redirigé vers le tableau de bord...", + "Confirm Email Failed": "Impossible de confirmer l’adresse e-mail. Merci de contacter support@uber.com si le problème persiste.", + "Credit Card Added": "Carte de crédit ajoutée", + "No Credit Card": "Pas de carte de crédit", + "Mobile Number Confirmed": "Numéro de téléphone confirmé", + "No Confirmed Mobile": "Pas de numéro de téléphone confirmé", + "E-mail Address Confirmed": "Adresse e-mail confirmée", + "No Confirmed E-mail": "Pas d’adresse e-mail confirmée", + 'Reply to sign up text': 'Répondre "GO" au SMS que vous avez reçu à l’inscription.', + "Resend text message": "Renvoyer le SMS", + "Click sign up link": "Cliquez sur le lien contenu dans l’e-mail reçu à l’inscription.", + "Resend email": "Renvoyer l’e-mail", + "Add a credit card to ride": "Ajouter une carte de crédit et vous serez prêt à voyager avec Uber.", + "Your Most Recent Trip": "Votre course la plus récente", + "details": "détails", + "Your Trip History": "Historique de votre trajet", + "Status": "Statut", + "Here's how it works:": "Voici comment ça marche :", + "Show all trips": "Montrer toutes les courses", + "Set your location:": "Définir votre position :", + "App search for address": "Application iPhone/Android : positionner la punaise ou rechercher une adresse", + "SMS text address": "SMS : envoyez votre adresse à UBRCAB (827222)", + "Confirm pickup request": "Validez la commande", + "Uber sends ETA": "Uber envoie un temps d’attente estimé (habituellement entre 5 et 10 minutes)", + "Car arrives": "Lorsque votre voiture arrive, Uber vous en informera encore..", + "Ride to destination": "Montez dans la voiture et donnez votre destination au chauffeur.", + "Thank your driver": "C’est tout ! Remerciez le chauffeur mais souvenez-vous que les pourboires sont compris et qu’il n’est pas nécessaire d’avoir du liquide sur soi.", + "Trip started here": "La course a commencé ici.", + "Trip ended here": "La course s’est terminée ici.", + "Sending Email": "Envoi de l’e-mail...", + "Resend Email Succeeded": "Nous venons d’envoyer l’e-mail. Merci de cliquer sur le lien de confirmation que vous avez reçu.", + "Resend Email Failed": "Il y a eu un problème lors de l’envoi de l’email. Merci de contacter le support si le problème persiste.", + "Resend Text Succeeded": 'Nous venons d’envoyer le SMS. Merci de répondre "GO" au message que vous avez reçu. Il se peut que cela prenne quelques minutes pour que le message arrive sur votre téléphone.', + "Resend Text Failed": "Il y a eu un problème lors de l’envoi du SMS. Merci de contacter le support si le problème persiste.", + "Password Reset Error": "Il y a eu une error lors de la réinitialisation de votre mot de passe.", + "New Password:": "Nouveau mot de passe:", + "Forgot Password Error": "Votre nom d’utilisateur / adresse email ne peut être trouvé. Merci d’utiliser la même qu’à l’inscription.", + "Forgot Password Success": "Merci de consulter votre boîte mail pour suivre la demande de ‘réinitialisation de mot de passe.", + "Forgot Password Enter Email": "Merci de saisir votre adresse email et nous vous enverrons un lien vous permettant de réinitialiser votre mot de passe :", + "Invite friends": "Inviter vos amis", + "Give $ Get $": "Donnez $10, Recevez $10", + "Give $ Get $ Description": "Chaque ami que vous invitez à Uber recevra $10 de crédits Uber. Dès lors qu’une personne que vous aurez invité aura utilisé Uber pour la première, vous recevrez $10 de crédits Uber également !", + "What are you waiting for?": "N’attendez plus ! Lancez les invitations !", + "Tweet": "Tweeter", + "Invite Link": "Envoyez ce lien par email ou messagerie instantanée à vos amis :", + "Enter Promotion Code": "Si vous avez un code promo, saisissez-le ici:", + "Your Active Promotions": "Vos Codes Promos Actifs", + "Code": "Code", + "Details": "Détails", + "Trips Remaining": "Courses restantes", + "Expires": "Expire", + "No Active Promotions": "Vous n’avez pas de code promo actif.", + "Your Available Promotions": "Votres Promos Disponibles", + "Where do you want us to pick you up?": "Où souhaitez-vous que nous vous prenions en charge ?", + "Address to search": "Adresse à rechercher", + "Search": "Chercher", + "Driver Name:": "Nom du chauffeur:", + "Driver #:": "# Chauffeur:", + "Pickup Address:": "Lieu de prise en charge:", + "Add to Favorite Locations": "Ajoutez aux Lieux Favoris", + "Star": "Étoiles", + "Nickname:": "Pseudo", + "Add": "Ajouter", + "Your last trip": "Votre dernière course", + "Please rate your driver:": "Merci de noter votre chauffeur :", + "Comments: (optional)": "Commentaires: (optionnel)", + "Rate Trip": "Notez votre course", + "Pickup time:": "Heure de Prise en Charge :", + "Miles:": "Kilomètres :", + "Trip time:": "Temps de course :", + "Fare:": "Tarif :", + "Favorite Locations": "Lieux Favoris", + "Search Results": "Résultats", + "You have no favorite locations saved.": "Vous n’avez pas de lieux de prise en charge favoris.", + "Loading...": "Chargement...", + "Request Pickup": "Commander ici", + "Cancel Pickup": "Annuler", + "Requesting Closest Driver": "Nous demandons au chauffeur le plus proche de vous prendre en charge...", + "En Route": "Vous êtes actuellement en route...", + "Rate Last Trip": "Merci de noter votre précédent trajet pour faire une autre course.", + "Rate Before Submitting": "Merci de noter votre trajet avant de le valider.", + "Address too short": "L’adresse est trop courte", + "or did you mean": "ou vouliez-vous dire", + "Search Address Failed": "Impossible de trouver l’adresse spécifiée. Merci de saisir une autre adresse proche de l’endroit où vous vous trouvez.", + "Sending pickup request...": "Envoi de la demande de prise en charge...", + "Cancel Request Prompt": "Voulez-vous vraiment annuler votre demande ?", + "Cancel Request Arrived Prompt": 'Voulez-vous vraiment annuler votre demande ? Votre chauffeur est arrivé, vous serez donc facturé de $10 de frais d’annulation. Il pourrait être utile que vous appeliez votre chauffeur maintenant.', + "Favorite Location Nickname Length Error": "Le pseudo doit faire au moins 3 caractères de long", + "Favorite Location Save Succeeded": "Adresse enregistrée !", + "Favorite Location Save Failed": "Impossible d’enregistrer votre adresse. Merci de réessayer ultérieurement.", + "Favorite Location Title": "Adresse favorie <%= id %>", + "Search Location Title": "Recherche d’adresse <%= id %>", + "ETA Message": "Temps d’attente estimé: environ <%= minutes %> minutes", + "Nearest Cab Message": "Le chauffeur le plus proche sera là dans <%= minutes %> minute(s)", + "Arrival ETA Message": "Votre chauffeur arrivera dans <%= minutes %> minute(s)", + "Arriving Now Message": "Votre chauffeur est en approche...", + "Rating Driver Failed": "Impossible de contacter le serveur. Merci de réessayer ultérieurement ou de contacter le support si le problème persiste.", + "settings": "Paramètres", + "Information": "Information", + "Picture": "Photo", + "Change password": "Modifier votre mot de passe", + "Your current Picture": "Votre photo", + "Your Favorite Locations": "Vos lieux favoris", + "You have no favorite locations saved.": "Vous n’avez pas de lieu favori", + "Account Information": "Informations Personnelles", + "Mobile Phone Information": "Informations de Mobile", + "Change Your Password": "Changez votre mot de passe.", + "Country": "Pays", + "Language": "Langue", + "Favorite Location": "Lieu favori", + "No Approximate Address": "Impossible de trouver une adresse même approximative", + "Address:": "Adresse :", + "Information Update Succeeded": "Vos informations ont été mises à jour !", + "Information Update Failed": "Nous n’avons pas pu mettre à jour vos informations. Merci de réessayer dans quelques instants ou de contacter le support si le problème persiste.", + "Location Delete Succeeded": "Adresse supprimée !", + "Location Delete Failed": "Nous n’avons pas pu supprimée votre adresse favorie. Merci de réessayer plus tard ou de contacter le support si le problème persiste.", + "Location Edit Succeeded": "Modifications sauvegardées !", + "Location Edit Failed": "Nous n’avons pas pu sauvegarder vos modifications. Merci de réessayer dans quelques minutes.", + "Picture Update Succeeded": "Votre photo a été mise à jour !", + "Picture Update Failed": "Nous n’avons pas pu mettre à jour votre photo. Merci de réessayer dans quelques instants.", + "Personal Information": "Informations Personnelles", + "Mobile Phone Number": "Numéro de Téléphone Portable", + "Payment Information": "Informations de Facturation", + "Your card will not be charged until you take a trip.": "Votre carte ne sera pas débitée avant votre premier trajet.", + "Card Number": "Numéro de Carte", + "Promotion Code Input Label": "Code promo, code d’invitation ou “deal” acheté en ligne (optionnel)", + "Terms and Conditions": "Conditions Générales", + "HELP": "HELP", + "STOP": "STOP", + "Sign Up Agreement": "En souscrivant, j’accepte les <%= terms_link %> et <%= privacy_link %> et comprends qu’Uber est un outil de commande de chauffeur, et non un transporteur.", + "Sign Up Agreement Error": "Vous devez accepter les Conditions Générales d’utilisation d’Uber Terms and Conditions et la Politique de Confidentialité pour continuer.", + "Message and Data Rates Disclosure": "Les frais d’envoi de SMS et de consommation de données peuvent s’appliquer. Répondez <%= help_string %> au 827-222 pour obtenir de l’aide. Répondez <%= stop_string %> au 827-222 pour ne plus recevoir de SMS. Pour plus d’aide, visitez support.uber.com ou appelez le (866) 576-1039. Opérateurs supportés: AT&T, Sprint, Verizon, T-Mobile, Orange, SFR et Bouygues Telecom.", + "Zip/Postal Code": "Code Postal", + "Expiration Date": "Date D'expiration", + "Security Code": "Code de Sécurité", + "Type of Card": "Type", + "Personal": "Personnel", + "Business": "Entreprise", + "Promotion Code": "Code Promo", + "Legal Information": "Mentions Légales", + "I Agree": "J'accepte.", + "Your Trip": "Votre Course", + "Trip Info": "Informations de la Course", + "Request a fare review": "Demander un contrôle du tarif", + "Fare Review Submitted": "Votre demande de contrôle du tarif a été soumis. Nous reviendrons vers vous rapidement concernant cette demande. Nous nous excusons pour les dérangements éventuellement occasionnés !", + "Fair Price Consideration": "Nous nous engageons à proposer Uber à un tarif juste. Avant de demander un contrôle du tarif, merci de prendre en compte :", + "Your Fare Calculation": "Calcul du Prix", + "Charges": "Coûts", + "Discounts": "Réductions", + "Total Charge": "Coût total", + "Uber pricing information": "Information sur les prix d’Uber", + "Uber Pricing Information Message": "<%= learn_link %> est disponible sur notre site web.", + "GPS Point Capture Disclosure": "A cause d’un nombre limité de coordonnées GPS sauvegardées, les angles de votre trajet sur la carte peuvent apparaître coupés ou arrondis. Ces légères incohérences débouchent sur des distances mesurées plus courtes, ce qui implique toujours un prix du trajet moins élevé.", + "Fare Review Note": "Merci de nous expliquer pourquoi le tarif de cette course nécessite d’être contrôlé. Vos commentaires ci-dessous nous aideront à établir un prix plus juste si nécessaire :", + "Fare Review Error": "Il y a eu une erreur lors de l’envoi de la demande. Assurez-vous d’avoir bien ajouté une description à votre demande." + }; +}).call(this); +}, "views/clients/billing": function(exports, require, module) {(function() { + var clientsBillingTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsBillingTemplate = require('templates/clients/billing'); + exports.ClientsBillingView = (function() { + __extends(ClientsBillingView, UberView); + function ClientsBillingView() { + ClientsBillingView.__super__.constructor.apply(this, arguments); + } + ClientsBillingView.prototype.id = 'billing_view'; + ClientsBillingView.prototype.className = 'view_container'; + ClientsBillingView.prototype.events = { + 'click a#add_card': 'addCard', + 'click .charge_arrear': 'chargeArrear' + }; + ClientsBillingView.prototype.render = function() { + this.RefreshUserInfo(__bind(function() { + var cards, newForm; + this.HideSpinner(); + $(this.el).html(clientsBillingTemplate()); + if (USER.payment_gateway.payment_profiles.length === 0) { + newForm = new app.views.clients.modules.creditcard; + $(this.el).find("#add_card_wrapper").html(newForm.render(0).el); + } else { + cards = new app.views.clients.modules.creditcard; + $("#cards").html(cards.render("all").el); + } + return this.delegateEvents(); + }, this)); + return this; + }; + ClientsBillingView.prototype.addCard = function(e) { + var newCard; + e.preventDefault(); + newCard = new app.views.clients.modules.creditcard; + $('#cards').append(newCard.render("new").el); + return $("a#add_card").hide(); + }; + ClientsBillingView.prototype.chargeArrear = function(e) { + var $el, arrearId, attrs, cardId, options, tryCharge; + e.preventDefault(); + $(".error_message").text(""); + $el = $(e.currentTarget); + arrearId = $el.attr('id'); + cardId = $el.parent().find('#card_to_charge').val(); + this.ShowSpinner('submit'); + tryCharge = new app.models.clientbills({ + id: arrearId + }); + attrs = { + payment_profile_id: cardId, + dataType: 'json' + }; + options = { + success: __bind(function(data, textStatus, jqXHR) { + $el.parent().find(".success_message").text(t("Billing Succeeded")); + $el.hide(); + return $el.parent().find('#card_to_charge').hide(); + }, this), + error: __bind(function(jqXHR, status, errorThrown) { + return $el.parent().find(".error_message").text(JSON.parse(status.responseText).error); + }, this), + complete: __bind(function() { + return this.HideSpinner(); + }, this) + }; + return tryCharge.save(attrs, options); + }; + return ClientsBillingView; + })(); +}).call(this); +}, "views/clients/confirm_email": function(exports, require, module) {(function() { + var clientsConfirmEmailTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsConfirmEmailTemplate = require('templates/clients/confirm_email'); + exports.ClientsConfirmEmailView = (function() { + __extends(ClientsConfirmEmailView, UberView); + function ClientsConfirmEmailView() { + ClientsConfirmEmailView.__super__.constructor.apply(this, arguments); + } + ClientsConfirmEmailView.prototype.id = 'confirm_email_view'; + ClientsConfirmEmailView.prototype.className = 'view_container'; + ClientsConfirmEmailView.prototype.render = function(token) { + var attrs; + $(this.el).html(clientsConfirmEmailTemplate()); + attrs = { + data: { + email_token: token + }, + success: __bind(function(data, textStatus, jqXHR) { + var show_dashboard; + this.HideSpinner(); + show_dashboard = function() { + return app.routers.clients.navigate('!/dashboard', true); + }; + if (data.status === 'OK') { + $('.success_message').show(); + return _.delay(show_dashboard, 3000); + } else if (data.status === 'ALREADY_COMFIRMED') { + $('.already_confirmed_message').show(); + return _.delay(show_dashboard, 3000); + } else { + return $('.error_message').show(); + } + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('.error_message').show(); + }, this), + complete: function(status) { + return $('#attempt_text').hide(); + }, + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/self" + }; + $.ajax(attrs); + this.ShowSpinner('submit'); + return this; + }; + return ClientsConfirmEmailView; + })(); +}).call(this); +}, "views/clients/dashboard": function(exports, require, module) {(function() { + var clientsDashboardTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsDashboardTemplate = require('templates/clients/dashboard'); + exports.ClientsDashboardView = (function() { + var displayFirstTrip; + __extends(ClientsDashboardView, UberView); + function ClientsDashboardView() { + this.showAllTrips = __bind(this.showAllTrips, this); + this.render = __bind(this.render, this); + ClientsDashboardView.__super__.constructor.apply(this, arguments); + } + ClientsDashboardView.prototype.id = 'dashboard_view'; + ClientsDashboardView.prototype.className = 'view_container'; + ClientsDashboardView.prototype.events = { + 'click a.confirmation': 'confirmationClick', + 'click #resend_email': 'resendEmail', + 'click #resend_mobile': 'resendMobile', + 'click #show_all_trips': 'showAllTrips' + }; + ClientsDashboardView.prototype.render = function() { + var displayPage, downloadTrips; + this.HideSpinner(); + displayPage = __bind(function() { + $(this.el).html(clientsDashboardTemplate()); + this.confirmationsSetup(); + return this.RequireMaps(__bind(function() { + if (USER.trips.models[0]) { + if (!USER.trips.models[0].get("points")) { + return USER.trips.models[0].fetch({ + data: { + relationships: 'points' + }, + success: __bind(function() { + this.CacheData("USERtrips", USER.trips); + return displayFirstTrip(); + }, this) + }); + } else { + return displayFirstTrip(); + } + } + }, this)); + }, this); + downloadTrips = __bind(function() { + return this.DownloadUserTrips(displayPage, false, 10); + }, this); + this.RefreshUserInfo(downloadTrips); + return this; + }; + displayFirstTrip = __bind(function() { + var bounds, endPos, map, myOptions, path, polyline, startPos; + myOptions = { + zoom: 12, + mapTypeId: google.maps.MapTypeId.ROADMAP, + zoomControl: false, + rotateControl: false, + panControl: false, + mapTypeControl: false, + scrollwheel: false + }; + if (USER.trips.length === 10) { + $("#show_all_trips").show(); + } + if (USER.trips.length > 0) { + map = new google.maps.Map(document.getElementById("trip_details_map"), myOptions); + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(USER.trips.models[0].get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + map.fitBounds(bounds); + startPos = new google.maps.Marker({ + position: _.first(path), + map: map, + title: t('Trip started here'), + icon: 'https://uber-static.s3.amazonaws.com/marker_start.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: map, + title: t('Trip ended here'), + icon: 'https://uber-static.s3.amazonaws.com/marker_end.png' + }); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + return polyline.setMap(map); + } + }, ClientsDashboardView); + ClientsDashboardView.prototype.confirmationsSetup = function() { + var blink, cardForm, element, _ref, _ref2, _ref3, _ref4, _ref5; + blink = function(element) { + var opacity; + opacity = 0.5; + if (element.css('opacity') === "0.5") { + opacity = 1.0; + } + return element.fadeTo(2000, opacity, function() { + return blink(element); + }); + }; + if (((_ref = window.USER) != null ? (_ref2 = _ref.payment_gateway) != null ? (_ref3 = _ref2.payment_profiles) != null ? _ref3.length : void 0 : void 0 : void 0) === 0) { + element = $('#confirmed_credit_card'); + cardForm = new app.views.clients.modules.creditcard; + $('#card.info').append(cardForm.render().el); + blink(element); + } + if (((_ref4 = window.USER) != null ? _ref4.confirm_email : void 0) === false) { + element = $('#confirmed_email'); + blink(element); + } + if ((((_ref5 = window.USER) != null ? _ref5.confirm_mobile : void 0) != null) === false) { + element = $('#confirmed_mobile'); + return blink(element); + } + }; + ClientsDashboardView.prototype.confirmationClick = function(e) { + e.preventDefault(); + $('.info').hide(); + $('#more_info').show(); + switch (e.currentTarget.id) { + case "card": + return $('#card.info').slideToggle(); + case "mobile": + return $('#mobile.info').slideToggle(); + case "email": + return $('#email.info').slideToggle(); + } + }; + ClientsDashboardView.prototype.resendEmail = function(e) { + var $el; + e.preventDefault(); + $el = $(e.currentTarget); + $el.removeAttr('href').prop({ + disabled: true + }); + $el.html(t("Sending Email")); + return $.ajax({ + type: 'GET', + url: API + '/users/request_confirm_email', + data: { + token: USER.token + }, + dataType: 'json', + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Resend Email Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.html(t("Resend Email Failed")); + }, this) + }); + }; + ClientsDashboardView.prototype.resendMobile = function(e) { + var $el; + e.preventDefault(); + $el = $(e.currentTarget); + $el.removeAttr('href').prop({ + disabled: true + }); + $el.html("Sending message..."); + return $.ajax({ + type: 'GET', + url: API + '/users/request_confirm_mobile', + data: { + token: USER.token + }, + dataType: 'json', + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Resend Text Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.html(t("Resend Text Failed")); + }, this) + }); + }; + ClientsDashboardView.prototype.showAllTrips = function(e) { + e.preventDefault(); + $(e.currentTarget).hide(); + return this.DownloadUserTrips(this.render, true, 1000); + }; + return ClientsDashboardView; + }).call(this); +}).call(this); +}, "views/clients/forgot_password": function(exports, require, module) {(function() { + var clientsForgotPasswordTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsForgotPasswordTemplate = require('templates/clients/forgot_password'); + exports.ClientsForgotPasswordView = (function() { + __extends(ClientsForgotPasswordView, UberView); + function ClientsForgotPasswordView() { + ClientsForgotPasswordView.__super__.constructor.apply(this, arguments); + } + ClientsForgotPasswordView.prototype.id = 'forgotpassword_view'; + ClientsForgotPasswordView.prototype.className = 'view_container modal_view_container'; + ClientsForgotPasswordView.prototype.events = { + "submit #password_reset": "passwordReset", + "click #password_reset_submit": "passwordReset", + "submit #forgot_password": "forgotPassword", + "click #forgot_password_submit": "forgotPassword" + }; + ClientsForgotPasswordView.prototype.render = function(token) { + this.HideSpinner(); + $(this.el).html(clientsForgotPasswordTemplate({ + token: token + })); + this.delegateEvents(); + return this; + }; + ClientsForgotPasswordView.prototype.forgotPassword = function(e) { + var attrs; + e.preventDefault(); + $('.success_message').hide(); + $(".error_message").hide(); + attrs = { + data: { + login: $("#login").val() + }, + success: __bind(function(data, textStatus, jqXHR) { + this.HideSpinner(); + $('.success_message').show(); + return $("#forgot_password").hide(); + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('.error_message').show(); + }, this), + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/forgot_password" + }; + $.ajax(attrs); + return this.ShowSpinner('submit'); + }; + ClientsForgotPasswordView.prototype.passwordReset = function(e) { + var attrs; + e.preventDefault(); + attrs = { + data: { + email_token: $("#token").val(), + password: $("#password").val() + }, + success: __bind(function(data, textStatus, jqXHR) { + this.HideSpinner(); + $.cookie('token', data.token); + amplify.store('USERjson', data); + app.refreshMenu(); + return location.hash = '!/dashboard'; + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('#error_reset').show(); + }, this), + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/self" + }; + $.ajax(attrs); + return this.ShowSpinner('submit'); + }; + return ClientsForgotPasswordView; + })(); +}).call(this); +}, "views/clients/invite": function(exports, require, module) {(function() { + var clientsInviteTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsInviteTemplate = require('templates/clients/invite'); + exports.ClientsInviteView = (function() { + __extends(ClientsInviteView, UberView); + function ClientsInviteView() { + ClientsInviteView.__super__.constructor.apply(this, arguments); + } + ClientsInviteView.prototype.id = 'invite_view'; + ClientsInviteView.prototype.className = 'view_container'; + ClientsInviteView.prototype.render = function() { + this.ReadUserInfo(); + this.HideSpinner(); + $(this.el).html(clientsInviteTemplate()); + console.log(screen); + return this; + }; + return ClientsInviteView; + })(); +}).call(this); +}, "views/clients/login": function(exports, require, module) {(function() { + var clientsLoginTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsLoginTemplate = require('templates/clients/login'); + exports.ClientsLoginView = (function() { + __extends(ClientsLoginView, UberView); + function ClientsLoginView() { + ClientsLoginView.__super__.constructor.apply(this, arguments); + } + ClientsLoginView.prototype.id = 'login_view'; + ClientsLoginView.prototype.className = 'view_container modal_view_container'; + ClientsLoginView.prototype.events = { + 'submit form': 'authenticate', + 'click button': 'authenticate' + }; + ClientsLoginView.prototype.initialize = function() { + _.bindAll(this, 'render'); + return this.render(); + }; + ClientsLoginView.prototype.render = function() { + this.HideSpinner(); + $(this.el).html(clientsLoginTemplate()); + this.delegateEvents(); + return this.place(); + }; + ClientsLoginView.prototype.authenticate = function(e) { + e.preventDefault(); + return $.ajax({ + type: 'POST', + url: API + '/auth/web_login/client', + data: { + login: $("#login").val(), + password: $("#password").val() + }, + dataType: 'json', + success: function(data, textStatus, jqXHR) { + $.cookie('user', JSON.stringify(data)); + $.cookie('token', data.token); + amplify.store('USERjson', data); + $('header').html(app.views.shared.menu.render().el); + return app.routers.clients.navigate('!/dashboard', true); + }, + error: function(jqXHR, textStatus, errorThrown) { + $.cookie('user', null); + $.cookie('token', null); + if (jqXHR.status === 403) { + $.cookie('redirected_user', JSON.stringify(JSON.parse(jqXHR.responseText).error_obj), { + domain: '.uber.com' + }); + window.location = 'http://partners.uber.com/'; + } + return $('.error_message').html(JSON.parse(jqXHR.responseText).error).hide().fadeIn(); + } + }); + }; + return ClientsLoginView; + })(); +}).call(this); +}, "views/clients/modules/credit_card": function(exports, require, module) {(function() { + var creditCardTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + creditCardTemplate = require('templates/clients/modules/credit_card'); + exports.CreditCardView = (function() { + __extends(CreditCardView, UberView); + function CreditCardView() { + CreditCardView.__super__.constructor.apply(this, arguments); + } + CreditCardView.prototype.id = 'creditcard_view'; + CreditCardView.prototype.className = 'module_container'; + CreditCardView.prototype.events = { + 'submit #credit_card_form': 'processNewCard', + 'click #new_card': 'processNewCard', + 'change #card_number': 'showCardType', + 'click .edit_card_show': 'showEditCard', + 'click .edit_card': 'editCard', + 'click .delete_card': 'deleteCard', + 'click .make_default': 'makeDefault', + 'change .use_case': 'saveUseCase' + }; + CreditCardView.prototype.initialize = function() { + return app.collections.paymentprofiles.bind("refresh", __bind(function() { + return this.RefreshUserInfo(__bind(function() { + this.render("all"); + return this.HideSpinner(); + }, this)); + }, this)); + }; + CreditCardView.prototype.render = function(cards) { + if (cards == null) { + cards = "new"; + } + if (cards === "all") { + app.collections.paymentprofiles.reset(USER.payment_gateway.payment_profiles); + cards = app.collections.paymentprofiles; + } + $(this.el).html(creditCardTemplate({ + cards: cards + })); + return this; + }; + CreditCardView.prototype.processNewCard = function(e) { + var $el, attrs, model, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $("#credit_card_form"); + $el.find('.error_message').html(""); + attrs = { + card_number: $el.find('#card_number').val(), + card_code: $el.find('#card_code').val(), + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + use_case: $el.find('#use_case').val(), + "default": $el.find('#default_check').prop("checked") + }; + options = { + statusCode: { + 200: __bind(function(e) { + this.HideSpinner(); + $('#cc_form_wrapper').hide(); + app.collections.paymentprofiles.trigger("refresh"); + $(this.el).remove(); + $("a#add_card").show(); + return $('section').html(app.views.clients.billing.render().el); + }, this), + 406: __bind(function(e) { + var error, errors, _i, _len, _ref, _results; + this.HideSpinner(); + errors = JSON.parse(e.responseText); + _ref = _.keys(errors); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + error = _ref[_i]; + _results.push(error === "top_of_form" ? $("#top_of_form").html(errors[error]) : $("#credit_card_form").find("#" + error).parent().find(".error_message").html(errors[error])); + } + return _results; + }, this), + 420: __bind(function(e) { + this.HideSpinner(); + return $("#top_of_form").html(t("Unable to Verify Card")); + }, this) + } + }; + this.ShowSpinner("submit"); + model = new app.models.paymentprofile; + model.save(attrs, options); + return app.collections.paymentprofiles.add(model); + }; + CreditCardView.prototype.showCardType = function(e) { + var $el, reAmerica, reDiscover, reMaster, reVisa, validCard; + reVisa = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/; + reMaster = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/; + reAmerica = /^6011-?\d{4}-?\d{4}-?\d{4}$/; + reDiscover = /^3[4,7]\d{13}$/; + $el = $("#card_logos"); + validCard = false; + if (e.currentTarget.value.match(reVisa)) { + validCard = true; + } else if (e.currentTarget.value.match(reMaster)) { + $el.css('background-position', "-60px"); + validCard = true; + } else if (e.currentTarget.value.match(reAmerica)) { + $el.css('background-position', "-120px"); + validCard = true; + } else if (e.currentTarget.value.match(reDiscover)) { + $el.css('background-position', "-180px"); + validCard = true; + } + if (validCard) { + $el.css('width', "60px"); + return $el.css('margin-left', "180px"); + } else { + $el.css('width', "250px"); + return $el.css('margin-left', "80px"); + } + }; + CreditCardView.prototype.showEditCard = function(e) { + var $el, id; + e.preventDefault(); + $el = $(e.currentTarget); + if ($el.html() === t("Edit")) { + id = $el.html(t("Cancel")).parents("tr").attr("id").substring(1); + return $("#e" + id).show(); + } else { + id = $el.html(t("Edit")).parents("tr").attr("id").substring(1); + return $("#e" + id).hide(); + } + }; + CreditCardView.prototype.editCard = function(e) { + var $el, attrs, id, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + $el.attr('disabled', 'disabled'); + this.ShowSpinner('submit'); + attrs = { + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + card_code: $el.find('#card_code').val() + }; + options = { + success: __bind(function(response) { + this.HideSpinner(); + this.ShowSuccess(t("Credit Card Update Succeeded")); + $("#e" + id).hide(); + $("#d" + id).find(".edit_card_show").html(t("Edit")); + return app.collections.paymentprofiles.trigger("refresh"); + }, this), + error: __bind(function(e) { + this.HideSpinner(); + this.ShowError(t("Credit Card Update Failed")); + return $el.removeAttr('disabled'); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + CreditCardView.prototype.deleteCard = function(e) { + var $el, id, options; + e.preventDefault(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + this.ClearGlobalStatus(); + this.ShowSpinner('submit'); + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Credit Card Delete Succeeded")); + $("form").hide(); + app.collections.paymentprofiles.trigger("refresh"); + return $('section').html(app.views.clients.billing.render().el); + }, this), + error: __bind(function(xhr, e) { + this.HideSpinner(); + return this.ShowError(t("Credit Card Delete Failed")); + }, this) + }; + return app.collections.paymentprofiles.models[id].destroy(options); + }; + CreditCardView.prototype.saveUseCase = function(e) { + var $el, attrs, id, options, use_case; + this.ClearGlobalStatus(); + $el = $(e.currentTarget); + use_case = $el.val(); + id = $el.parents("tr").attr("id").substring(1); + attrs = { + use_case: use_case + }; + options = { + success: __bind(function(response) { + return this.ShowSuccess(t("Credit Card Update Category Succeeded")); + }, this), + error: __bind(function(e) { + return this.ShowError(t("Credit Card Update Category Failed")); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + CreditCardView.prototype.makeDefault = function(e) { + var $el, attrs, id, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + attrs = { + "default": true + }; + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Credit Card Update Default Succeeded")); + return app.collections.paymentprofiles.trigger("refresh"); + }, this), + error: __bind(function(e) { + return this.ShowError(t("Credit Card Update Default Failed")); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + return CreditCardView; + })(); +}).call(this); +}, "views/clients/promotions": function(exports, require, module) {(function() { + var clientsPromotionsTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsPromotionsTemplate = require('templates/clients/promotions'); + exports.ClientsPromotionsView = (function() { + __extends(ClientsPromotionsView, UberView); + function ClientsPromotionsView() { + this.render = __bind(this.render, this); + ClientsPromotionsView.__super__.constructor.apply(this, arguments); + } + ClientsPromotionsView.prototype.id = 'promotions_view'; + ClientsPromotionsView.prototype.className = 'view_container'; + ClientsPromotionsView.prototype.events = { + 'submit form': 'submitPromo', + 'click button': 'submitPromo' + }; + ClientsPromotionsView.prototype.initialize = function() { + if (this.model) { + return this.RefreshUserInfo(this.render); + } + }; + ClientsPromotionsView.prototype.render = function() { + var renderTemplate; + this.ReadUserInfo(); + renderTemplate = __bind(function() { + $(this.el).html(clientsPromotionsTemplate({ + promos: window.USER.unexpired_client_promotions || [] + })); + return this.HideSpinner(); + }, this); + this.DownloadUserPromotions(renderTemplate); + return this; + }; + ClientsPromotionsView.prototype.submitPromo = function(e) { + var attrs, model, options, refreshTable; + e.preventDefault(); + this.ClearGlobalStatus(); + refreshTable = __bind(function() { + $('section').html(this.render().el); + return this.HideSpinner(); + }, this); + attrs = { + code: $('#code').val() + }; + options = { + success: __bind(function(response) { + this.HideSpinner(); + if (response.get('first_name')) { + return this.ShowSuccess("Your promotion has been applied in the form of an account credit. Click here to check your balance."); + } else { + this.ShowSuccess("Your promotion has successfully been applied"); + return this.RefreshUserInfo(this.render, true); + } + }, this), + statusCode: { + 400: __bind(function(e) { + this.ShowError(JSON.parse(e.responseText).error); + return this.HideSpinner(); + }, this) + } + }; + this.ShowSpinner("submit"); + model = new app.models.promotions; + return model.save(attrs, options); + }; + return ClientsPromotionsView; + })(); +}).call(this); +}, "views/clients/request": function(exports, require, module) {(function() { + var clientsRequestTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsRequestTemplate = require('templates/clients/request'); + exports.ClientsRequestView = (function() { + __extends(ClientsRequestView, UberView); + function ClientsRequestView() { + this.AjaxCall = __bind(this.AjaxCall, this); + this.AskDispatch = __bind(this.AskDispatch, this); + this.removeMarkers = __bind(this.removeMarkers, this); + this.displaySearchLoc = __bind(this.displaySearchLoc, this); + this.displayFavLoc = __bind(this.displayFavLoc, this); + this.showFavLoc = __bind(this.showFavLoc, this); + this.addToFavLoc = __bind(this.addToFavLoc, this); + this.removeCabs = __bind(this.removeCabs, this); + this.requestRide = __bind(this.requestRide, this); + this.rateTrip = __bind(this.rateTrip, this); + this.locationChange = __bind(this.locationChange, this); + this.panToLocation = __bind(this.panToLocation, this); + this.clickLocation = __bind(this.clickLocation, this); + this.searchLocation = __bind(this.searchLocation, this); + this.mouseoutLocation = __bind(this.mouseoutLocation, this); + this.mouseoverLocation = __bind(this.mouseoverLocation, this); + this.fetchTripDetails = __bind(this.fetchTripDetails, this); + this.submitRating = __bind(this.submitRating, this); + this.setStatus = __bind(this.setStatus, this); + this.initialize = __bind(this.initialize, this); + ClientsRequestView.__super__.constructor.apply(this, arguments); + } + ClientsRequestView.prototype.id = 'request_view'; + ClientsRequestView.prototype.className = 'view_container'; + ClientsRequestView.prototype.pollInterval = 2 * 1000; + ClientsRequestView.prototype.events = { + "submit #search_form": "searchAddress", + "click .locations_link": "locationLinkHandle", + "mouseover .location_row": "mouseoverLocation", + "mouseout .location_row": "mouseoutLocation", + "click .location_row": "clickLocation", + "click #search_location": "searchLocation", + "click #pickupHandle": "pickupHandle", + "click .stars": "rateTrip", + "submit #rating_form": "submitRating", + "click #addToFavButton": "showFavLoc", + "click #favLocNickname": "selectInputText", + "submit #favLoc_form": "addToFavLoc" + }; + ClientsRequestView.prototype.status = ""; + ClientsRequestView.prototype.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker.png"; + ClientsRequestView.prototype.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker.png"; + ClientsRequestView.prototype.initialize = function() { + var displayCabs; + displayCabs = __bind(function() { + return this.AskDispatch("NearestCab"); + }, this); + this.showCabs = _.throttle(displayCabs, this.pollInterval); + return this.numSearchToDisplay = 1; + }; + ClientsRequestView.prototype.setStatus = function(status) { + var autocomplete; + if (this.status === status) { + return; + } + try { + google.maps.event.trigger(this.map, 'resize'); + } catch (_e) {} + switch (status) { + case "init": + this.AskDispatch("StatusClient"); + this.status = "init"; + return this.ShowSpinner("load"); + case "ready": + this.HideSpinner(); + $(".panel").hide(); + $("#top_bar").fadeIn(); + $("#location_panel").fadeIn(); + $("#location_panel_control").fadeIn(); + $("#pickupHandle").attr("class", "button_green").fadeIn().find("span").html(t("Request Pickup")); + this.pickup_icon.setDraggable(true); + this.map.panTo(this.pickup_icon.getPosition()); + this.showCabs(); + try { + this.pickup_icon.setMap(this.map); + this.displayFavLoc(); + autocomplete = new google.maps.places.Autocomplete(document.getElementById('address'), { + types: ['geocode'] + }); + autocomplete.bindTo('bounds', this.map); + } catch (_e) {} + return this.status = "ready"; + case "searching": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#status_message").html(t("Requesting Closest Driver")); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "searching"; + case "waiting": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "waiting"; + case "arriving": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "arriving"; + case "riding": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").fadeIn().attr("class", "button_red").find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.status = "riding"; + return $("#status_message").html(t("En Route")); + case "rate": + this.HideSpinner(); + $(".panel").hide(); + $("#pickupHandle").fadeOut(); + $("#trip_completed_panel").fadeIn(); + $('#status_message').html(t("Rate Last Trip")); + return this.status = "rate"; + } + }; + ClientsRequestView.prototype.render = function() { + this.ReadUserInfo(); + this.HideSpinner(); + this.ShowSpinner("load"); + $(this.el).html(clientsRequestTemplate()); + this.cabs = []; + this.RequireMaps(__bind(function() { + var center, myOptions, streetViewPano; + center = new google.maps.LatLng(37.7749295, -122.4194155); + this.markers = []; + this.pickup_icon = new google.maps.Marker({ + position: center, + draggable: true, + clickable: true, + icon: this.pickupMarker + }); + this.geocoder = new google.maps.Geocoder(); + myOptions = { + zoom: 12, + center: center, + mapTypeId: google.maps.MapTypeId.ROADMAP, + rotateControl: false, + rotateControl: false, + panControl: false + }; + this.map = new google.maps.Map($(this.el).find("#map_wrapper_right")[0], myOptions); + if (this.status === "ready") { + this.pickup_icon.setMap(this.map); + } + if (geo_position_js.init()) { + geo_position_js.getCurrentPosition(__bind(function(data) { + var location; + location = new google.maps.LatLng(data.coords.latitude, data.coords.longitude); + this.pickup_icon.setPosition(location); + this.map.panTo(location); + return this.map.setZoom(16); + }, this)); + } + this.setStatus("init"); + streetViewPano = this.map.getStreetView(); + google.maps.event.addListener(streetViewPano, 'visible_changed', __bind(function() { + if (streetViewPano.getVisible()) { + this.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker_large.png"; + this.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker_large.png"; + } else { + this.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker.png"; + this.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker.png"; + } + this.pickup_icon.setIcon(this.pickupMarker); + return _.each(this.cabs, __bind(function(cab) { + return cab.setIcon(this.cabMarker); + }, this)); + }, this)); + if (this.status === "ready") { + return this.displayFavLoc(); + } + }, this)); + return this; + }; + ClientsRequestView.prototype.submitRating = function(e) { + var $el, message, rating; + e.preventDefault(); + $el = $(e.currentTarget); + rating = 0; + _(5).times(function(num) { + if ($el.find(".stars#" + (num + 1)).attr("src") === "/web/img/star_active.png") { + return rating = num + 1; + } + }); + if (rating === 0) { + $("#status_message").html("").html(t("Rate Before Submitting")); + } else { + this.ShowSpinner("submit"); + this.AskDispatch("RatingDriver", { + rating: rating + }); + } + message = $el.find("#comments").val().toString(); + if (message.length > 5) { + return this.AskDispatch("Feedback", { + message: message + }); + } + }; + ClientsRequestView.prototype.fetchTripDetails = function(id) { + var trip; + trip = new app.models.trip({ + id: id + }); + return trip.fetch({ + data: { + relationships: 'points,driver,city' + }, + dataType: 'json', + success: __bind(function() { + var bounds, endPos, path, polyline, startPos; + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(trip.get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + startPos = new google.maps.Marker({ + position: _.first(path), + map: this.map, + title: t("Trip started here"), + icon: 'https://uber-static.s3.amazonaws.com/carstart.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: this.map, + title: t("Trip ended here"), + icon: 'https://uber-static.s3.amazonaws.com/carstop.png' + }); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + polyline.setMap(this.map); + this.map.fitBounds(bounds); + $("#tripTime").html(app.helpers.parseDateTime(trip.get('pickup_local_time'), trip.get('city.timezone'))); + $("#tripDist").html(app.helpers.RoundNumber(trip.get('distance'), 2)); + $("#tripDur").html(app.helpers.FormatSeconds(trip.get('duration'))); + return $("#tripFare").html(app.helpers.FormatCurrency(trip.get('fare'))); + }, this) + }); + }; + ClientsRequestView.prototype.searchAddress = function(e) { + var $locationsDiv, address, alphabet, bounds, showResults; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + try { + e.preventDefault(); + } catch (_e) {} + $('.error_message').html(""); + $locationsDiv = $("
"); + address = $('#address').val(); + bounds = new google.maps.LatLngBounds(); + if (address.length < 5) { + $('#status_message').html(t("Address too short")).fadeIn(); + return false; + } + showResults = __bind(function(address, index) { + var first_cell, row, second_cell; + if (index < this.numSearchToDisplay) { + first_cell = "
" + address.formatted_address + "
" + (t('or did you mean')) + "
" + address.formatted_address + "
+ + + +
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
+ +Licence & copyright +----------------------- + +Copyright (c) 2013 Rod Vagg & NAN contributors (listed above). + +Native Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/nan.h b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/nan.h new file mode 100644 index 00000000..b3eb02db --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/nan.h @@ -0,0 +1,884 @@ +/********************************************************************************** + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2013 NAN contributors: + * - Rod Vagg + * - Benjamin Byholm + * - Trevor Norris + * + * MIT +no-false-attribs License + * + * Version 0.3.2 (current Node unstable: 0.11.6, Node stable: 0.10.17) + * + * ChangeLog: + * * 0.3.2 Aug 30 2013 + * - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent + * in NanAsyncWorker + * + * * 0.3.1 Aug 20 2013 + * - fix "not all control paths return a value" compile warning on some platforms + * + * * 0.3.0 Aug 19 2013 + * - Made NAN work with NPM + * - Lots of fixes to NanFromV8String, pulling in features from new Node core + * - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API + * - Added optional error number argument for NanThrowError() + * - Added NanInitPersistent() + * - Added NanReturnNull() and NanReturnEmptyString() + * - Added NanLocker and NanUnlocker + * - Added missing scopes + * - Made sure to clear disposed Persistent handles + * - Changed NanAsyncWorker to allocate error messages on the heap + * - Changed NanThrowError(Local) to NanThrowError(Handle) + * - Fixed leak in NanAsyncWorker when errmsg is used + * + * * 0.2.2 Aug 5 2013 + * - Fixed usage of undefined variable with node::BASE64 in NanFromV8String() + * + * * 0.2.1 Aug 5 2013 + * - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for + * NanFromV8String() + * + * * 0.2.0 Aug 5 2013 + * - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR, + * NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY + * - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS, + * _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS, + * _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS, + * _NAN_PROPERTY_QUERY_ARGS + * - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer + * - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT, + * NAN_WEAK_CALLBACK_DATA, NanMakeWeak + * - Renamed THROW_ERROR to _NAN_THROW_ERROR + * - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*) + * - Added NanBufferUse(char*, uint32_t) + * - Added NanNewContextHandle(v8::ExtensionConfiguration*, + * v8::Handle, v8::Handle) + * - Fixed broken NanCallback#GetFunction() + * - Added optional encoding and size arguments to NanFromV8String() + * - Added NanGetPointerSafe() and NanSetPointerSafe() + * - Added initial test suite (to be expanded) + * - Allow NanUInt32OptionValue to convert any Number object + * + * * 0.1.0 Jul 21 2013 + * - Added `NAN_GETTER`, `NAN_SETTER` + * - Added `NanThrowError` with single Local argument + * - Added `NanNewBufferHandle` with single uint32_t argument + * - Added `NanHasInstance(Persistent&, Handle)` + * - Added `Local NanCallback#GetFunction()` + * - Added `NanCallback#Call(int, Local[])` + * - Deprecated `NanCallback#Run(int, Local[])` in favour of Call + * + * See https://github.com/rvagg/nan for the latest update to this file + **********************************************************************************/ + +#ifndef NAN_H +#define NAN_H + +#include +#include +#include + +// some generic helpers + +template static inline bool NanSetPointerSafe(T *var, T val) { + if (var) { + *var = val; + return true; + } else { + return false; + } +} + +template static inline T NanGetPointerSafe( + T *var, + T fallback = reinterpret_cast(0)) { + if (var) { + return *var; + } else { + return fallback; + } +} + +#define NanSymbol(value) v8::String::NewSymbol(value) + +static inline bool NanBooleanOptionValue( + v8::Local optionsObj + , v8::Handle opt, bool def) { + + if (def) { + return optionsObj.IsEmpty() + || !optionsObj->Has(opt) + || optionsObj->Get(opt)->BooleanValue(); + } else { + return !optionsObj.IsEmpty() + && optionsObj->Has(opt) + && optionsObj->Get(opt)->BooleanValue(); + } +} + +static inline bool NanBooleanOptionValue( + v8::Local optionsObj + , v8::Handle opt) { + return NanBooleanOptionValue(optionsObj, opt, false); +} + +static inline uint32_t NanUInt32OptionValue( + v8::Local optionsObj + , v8::Handle opt + , uint32_t def) { + + return !optionsObj.IsEmpty() + && optionsObj->Has(opt) + && optionsObj->Get(opt)->IsNumber() + ? optionsObj->Get(opt)->Uint32Value() + : def; +} + +#if (NODE_MODULE_VERSION > 0x000B) +// Node 0.11+ (0.11.3 and below won't compile with these) + +static v8::Isolate* nan_isolate = v8::Isolate::GetCurrent(); + +# define _NAN_METHOD_ARGS const v8::FunctionCallbackInfo& args +# define NAN_METHOD(name) void name(_NAN_METHOD_ARGS) +# define _NAN_GETTER_ARGS const v8::PropertyCallbackInfo& args +# define NAN_GETTER(name) \ + void name(v8::Local property, _NAN_GETTER_ARGS) +# define _NAN_SETTER_ARGS const v8::PropertyCallbackInfo& args +# define NAN_SETTER(name) \ + void name( \ + v8::Local property \ + , v8::Local value \ + , _NAN_SETTER_ARGS) +# define _NAN_PROPERTY_GETTER_ARGS \ + const v8::PropertyCallbackInfo& args +# define NAN_PROPERTY_GETTER(name) \ + void name(v8::Local property \ + , _NAN_PROPERTY_GETTER_ARGS) +# define _NAN_PROPERTY_SETTER_ARGS \ + const v8::PropertyCallbackInfo& args +# define NAN_PROPERTY_SETTER(name) \ + void name(v8::Local property \ + , v8::Local value \ + , _NAN_PROPERTY_SETTER_ARGS) +# define _NAN_PROPERTY_ENUMERATOR_ARGS \ + const v8::PropertyCallbackInfo& args +# define NAN_PROPERTY_ENUMERATOR(name) \ + void name(_NAN_PROPERTY_ENUMERATOR_ARGS) +# define _NAN_PROPERTY_DELETER_ARGS \ + const v8::PropertyCallbackInfo& args +# define NAN_PROPERTY_DELETER(name) \ + void name( \ + v8::Local property \ + , _NAN_PROPERTY_DELETER_ARGS) +# define _NAN_PROPERTY_QUERY_ARGS \ + const v8::PropertyCallbackInfo& args +# define NAN_PROPERTY_QUERY(name) \ + void name(v8::Local property, _NAN_PROPERTY_QUERY_ARGS) +# define NanGetInternalFieldPointer(object, index) \ + object->GetAlignedPointerFromInternalField(index) +# define NanSetInternalFieldPointer(object, index, value) \ + object->SetAlignedPointerInInternalField(index, value) + +# define NAN_WEAK_CALLBACK(type, name) \ + void name( \ + v8::Isolate* isolate, \ + v8::Persistent* object, \ + type data) +# define NAN_WEAK_CALLBACK_OBJECT (*object) +# define NAN_WEAK_CALLBACK_DATA(type) ((type) data) + +# define NanScope() v8::HandleScope scope(nan_isolate) +# define NanLocker() v8::Locker locker(nan_isolate) +# define NanUnlocker() v8::Unlocker unlocker(nan_isolate) +# define NanReturnValue(value) return args.GetReturnValue().Set(value) +# define NanReturnUndefined() return +# define NanReturnNull() return args.GetReturnValue().SetNull() +# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString() +# define NanAssignPersistent(type, handle, obj) handle.Reset(nan_isolate, obj) +# define NanInitPersistent(type, name, obj) \ + v8::Persistent name(nan_isolate, obj) +# define NanObjectWrapHandle(obj) obj->handle() +# define NanMakeWeak(handle, parameter, callback) \ + handle.MakeWeak(nan_isolate, parameter, callback) + +# define _NAN_THROW_ERROR(fun, errmsg) \ + do { \ + NanScope(); \ + v8::ThrowException(fun(v8::String::New(errmsg))); \ + } while (0); + + inline static void NanThrowError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::Error, errmsg); + } + + inline static void NanThrowError(v8::Handle error) { + NanScope(); + v8::ThrowException(error); + } + + inline static void NanThrowError(const char *msg, const int errorNumber) { + v8::Local err = v8::Exception::Error(v8::String::New(msg)); + v8::Local obj = err.As(); + obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber)); + NanThrowError(err); + } + + inline static void NanThrowTypeError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); + } + + inline static void NanThrowRangeError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); + } + + template static inline void NanDispose(v8::Persistent &handle) { + handle.Dispose(nan_isolate); + handle.Clear(); + } + + static inline v8::Local NanNewBufferHandle ( + char *data, + size_t length, + node::smalloc::FreeCallback callback, + void *hint) { + return node::Buffer::New(data, length, callback, hint); + } + + static inline v8::Local NanNewBufferHandle ( + char *data, uint32_t size) { + return node::Buffer::New(data, size); + } + + static inline v8::Local NanNewBufferHandle (uint32_t size) { + return node::Buffer::New(size); + } + + static inline v8::Local NanBufferUse(char* data, uint32_t size) { + return node::Buffer::Use(data, size); + } + + template + inline v8::Local NanPersistentToLocal( + const v8::Persistent& persistent) { + if (persistent.IsWeak()) { + return v8::Local::New(nan_isolate, persistent); + } else { + return *reinterpret_cast*>( + const_cast*>(&persistent)); + } + } + + inline bool NanHasInstance( + v8::Persistent& function_template + , v8::Handle value) { + return NanPersistentToLocal(function_template)->HasInstance(value); + } + + static inline v8::Local NanNewContextHandle( + v8::ExtensionConfiguration* extensions = NULL, + v8::Handle tmpl = v8::Handle(), + v8::Handle obj = v8::Handle()) { + return v8::Local::New(nan_isolate, v8::Context::New( + nan_isolate, extensions, tmpl, obj)); + } + +#else +// Node 0.8 and 0.10 + +# define _NAN_METHOD_ARGS const v8::Arguments& args +# define NAN_METHOD(name) v8::Handle name(_NAN_METHOD_ARGS) +# define _NAN_GETTER_ARGS const v8::AccessorInfo &args +# define NAN_GETTER(name) \ + v8::Handle name(v8::Local property, _NAN_GETTER_ARGS) +# define _NAN_SETTER_ARGS const v8::AccessorInfo &args +# define NAN_SETTER(name) \ + void name( \ + v8::Local property \ + , v8::Local value \ + , _NAN_SETTER_ARGS) +# define _NAN_PROPERTY_GETTER_ARGS const v8::AccessorInfo& args +# define NAN_PROPERTY_GETTER(name) \ + v8::Handle name(v8::Local property \ + , _NAN_PROPERTY_GETTER_ARGS) +# define _NAN_PROPERTY_SETTER_ARGS const v8::AccessorInfo& args +# define NAN_PROPERTY_SETTER(name) \ + v8::Handle name(v8::Local property \ + , v8::Local value \ + , _NAN_PROPERTY_SETTER_ARGS) +# define _NAN_PROPERTY_ENUMERATOR_ARGS const v8::AccessorInfo& args +# define NAN_PROPERTY_ENUMERATOR(name) \ + v8::Handle name(_NAN_PROPERTY_ENUMERATOR_ARGS) +# define _NAN_PROPERTY_DELETER_ARGS const v8::AccessorInfo& args +# define NAN_PROPERTY_DELETER(name) \ + v8::Handle name( \ + v8::Local property \ + , _NAN_PROPERTY_DELETER_ARGS) +# define _NAN_PROPERTY_QUERY_ARGS const v8::AccessorInfo& args +# define NAN_PROPERTY_QUERY(name) \ + v8::Handle name( \ + v8::Local property \ + , _NAN_PROPERTY_QUERY_ARGS) + +# define NanGetInternalFieldPointer(object, index) \ + object->GetPointerFromInternalField(index) +# define NanSetInternalFieldPointer(object, index, value) \ + object->SetPointerInInternalField(index, value) +# define NAN_WEAK_CALLBACK(type, name) void name( \ + v8::Persistent object, \ + void *data) +# define NAN_WEAK_CALLBACK_OBJECT object +# define NAN_WEAK_CALLBACK_DATA(type) ((type) data) + +# define NanScope() v8::HandleScope scope +# define NanLocker() v8::Locker locker +# define NanUnlocker() v8::Unlocker unlocker +# define NanReturnValue(value) return scope.Close(value) +# define NanReturnUndefined() return v8::Undefined() +# define NanReturnNull() return v8::Null() +# define NanReturnEmptyString() return v8::String::Empty() +# define NanInitPersistent(type, name, obj) \ + v8::Persistent name = v8::Persistent::New(obj) +# define NanAssignPersistent(type, handle, obj) \ + handle = v8::Persistent::New(obj) +# define NanObjectWrapHandle(obj) obj->handle_ +# define NanMakeWeak(handle, parameters, callback) \ + handle.MakeWeak(parameters, callback) + +# define _NAN_THROW_ERROR(fun, errmsg) \ + do { \ + NanScope(); \ + return v8::ThrowException(fun(v8::String::New(errmsg))); \ + } while (0); + + inline static v8::Handle NanThrowError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::Error, errmsg); + } + + inline static v8::Handle NanThrowError( + v8::Handle error) { + NanScope(); + return v8::ThrowException(error); + } + + inline static v8::Handle NanThrowError( + const char *msg, + const int errorNumber) { + v8::Local err = v8::Exception::Error(v8::String::New(msg)); + v8::Local obj = err.As(); + obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber)); + return NanThrowError(err); + } + + inline static v8::Handle NanThrowTypeError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); + } + + inline static v8::Handle NanThrowRangeError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); + } + + template static inline void NanDispose(v8::Persistent &handle) { + handle.Dispose(); + handle.Clear(); + } + + static inline v8::Local NanNewBufferHandle ( + char *data, + size_t length, + node::Buffer::free_callback callback, + void *hint) { + return v8::Local::New( + node::Buffer::New(data, length, callback, hint)->handle_); + } + + static inline v8::Local NanNewBufferHandle ( + char *data, uint32_t size) { + return v8::Local::New(node::Buffer::New(data, size)->handle_); + } + + static inline v8::Local NanNewBufferHandle (uint32_t size) { + return v8::Local::New(node::Buffer::New(size)->handle_); + } + + static inline void FreeData(char *data, void *hint) { + delete[] data; + } + + static inline v8::Local NanBufferUse(char* data, uint32_t size) { + return v8::Local::New( + node::Buffer::New(data, size, FreeData, NULL)->handle_); + } + + template + inline v8::Local NanPersistentToLocal( + const v8::Persistent& persistent) { + if (persistent.IsWeak()) { + return v8::Local::New(persistent); + } else { + return *reinterpret_cast*>( + const_cast*>(&persistent)); + } + } + + inline bool NanHasInstance( + v8::Persistent& function_template + , v8::Handle value) { + return function_template->HasInstance(value); + } + + static inline v8::Local NanNewContextHandle( + v8::ExtensionConfiguration* extensions = NULL + , v8::Handle tmpl = + v8::Handle() + , v8::Handle obj = v8::Handle() + ) { + v8::Persistent ctx = + v8::Context::New(extensions, tmpl, obj); + v8::Local lctx = v8::Local::New(ctx); + ctx.Dispose(); + return lctx; + } + +#endif // node version + +class NanCallback { + public: + NanCallback(const v8::Local &fn) { + NanScope(); + v8::Local obj = v8::Object::New(); + obj->Set(NanSymbol("callback"), fn); + NanAssignPersistent(v8::Object, handle, obj); + } + + ~NanCallback() { + if (handle.IsEmpty()) return; + handle.Dispose(); + handle.Clear(); + } + + inline v8::Local GetFunction () { + return NanPersistentToLocal(handle)->Get(NanSymbol("callback")) + .As(); + } + + // deprecated + void Run(int argc, v8::Local argv[]) { + Call(argc, argv); + } + + void Call(int argc, v8::Local argv[]) { + NanScope(); + + v8::Local callback = NanPersistentToLocal(handle)-> + Get(NanSymbol("callback")).As(); + v8::TryCatch try_catch; + callback->Call(v8::Context::GetCurrent()->Global(), argc, argv); + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } + + private: + v8::Persistent handle; +}; + +/* abstract */ class NanAsyncWorker { +public: + NanAsyncWorker (NanCallback *callback) : callback(callback) { + request.data = this; + errmsg = NULL; + } + + virtual ~NanAsyncWorker () { + NanScope(); + + if (!persistentHandle.IsEmpty()) + NanDispose(persistentHandle); + if (callback) + delete callback; + if (errmsg) + delete errmsg; + } + + virtual void WorkComplete () { + NanScope(); + + if (errmsg == NULL) + HandleOKCallback(); + else + HandleErrorCallback(); + delete callback; + callback = NULL; + } + + virtual void Execute () =0; + + uv_work_t request; + +protected: + v8::Persistent persistentHandle; + NanCallback *callback; + const char *errmsg; + + void SavePersistent(const char *key, v8::Local &obj) { + NanScope(); + + v8::Local handle = NanPersistentToLocal(persistentHandle); + handle->Set(NanSymbol(key), obj); + } + + v8::Local GetFromPersistent(const char *key) { + NanScope(); + + v8::Local handle = NanPersistentToLocal(persistentHandle); + return handle->Get(NanSymbol(key)).As(); + } + + virtual void HandleOKCallback () { + NanScope(); + + callback->Call(0, NULL); + }; + + virtual void HandleErrorCallback () { + NanScope(); + + v8::Local argv[] = { + v8::Exception::Error(v8::String::New(errmsg)) + }; + callback->Call(1, argv); + } +}; + +inline void NanAsyncExecute (uv_work_t* req) { + NanAsyncWorker *worker = static_cast(req->data); + worker->Execute(); +} + +inline void NanAsyncExecuteComplete (uv_work_t* req) { + NanAsyncWorker* worker = static_cast(req->data); + worker->WorkComplete(); + delete worker; +} + +inline void NanAsyncQueueWorker (NanAsyncWorker* worker) { + uv_queue_work( + uv_default_loop() + , &worker->request + , NanAsyncExecute + , (uv_after_work_cb)NanAsyncExecuteComplete + ); +} + +//// Base 64 //// + +#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) + + +// Doesn't check for padding at the end. Can be 1-2 bytes over. +static inline size_t _nan_base64_decoded_size_fast(size_t size) { + size_t remainder = size % 4; + + size = (size / 4) * 3; + if (remainder) { + if (size == 0 && remainder == 1) { + // special case: 1-byte input cannot be decoded + size = 0; + } else { + // non-padded input, add 1 or 2 extra bytes + size += 1 + (remainder == 3); + } + } + + return size; +} + +template +static size_t _nan_base64_decoded_size(const TypeName* src, size_t size) { + if (size == 0) + return 0; + + if (src[size - 1] == '=') + size--; + if (size > 0 && src[size - 1] == '=') + size--; + + return _nan_base64_decoded_size_fast(size); +} + + +// supports regular and URL-safe base64 +static const int _nan_unbase64_table[] = + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + +#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)] + + +template +static size_t _nan_base64_decode(char* buf, + size_t len, + const TypeName* src, + const size_t srcLen) { + char a, b, c, d; + char* dst = buf; + char* dstEnd = buf + len; + const TypeName* srcEnd = src + srcLen; + + while (src < srcEnd && dst < dstEnd) { + int remaining = srcEnd - src; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining == 0 || *src == '=') break; + a = _nan_unbase64(*src++); + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 1 || *src == '=') break; + b = _nan_unbase64(*src++); + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (dst == dstEnd) break; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 2 || *src == '=') break; + c = _nan_unbase64(*src++); + + *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2); + if (dst == dstEnd) break; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 3 || *src == '=') break; + d = _nan_unbase64(*src++); + + *dst++ = ((c & 0x03) << 6) | (d & 0x3F); + } + + return dst - buf; +} + +//// HEX //// + +template +unsigned _nan_hex2bin(TypeName c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); + if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); + return static_cast(-1); +} + + +template +static size_t _nan_hex_decode(char* buf, + size_t len, + const TypeName* src, + const size_t srcLen) { + size_t i; + for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) { + unsigned a = _nan_hex2bin(src[i * 2 + 0]); + unsigned b = _nan_hex2bin(src[i * 2 + 1]); + if (!~a || !~b) return i; + buf[i] = a * 16 + b; + } + + return i; +} + +static bool _NanGetExternalParts( + v8::Handle val + , const char** data + , size_t* len) { + + if (node::Buffer::HasInstance(val)) { + *data = node::Buffer::Data(val.As()); + *len = node::Buffer::Length(val.As()); + return true; + + } + + assert(val->IsString()); + v8::Local str = v8::Local::New(val.As()); + + if (str->IsExternalAscii()) { + const v8::String::ExternalAsciiStringResource* ext; + ext = str->GetExternalAsciiStringResource(); + *data = ext->data(); + *len = ext->length(); + return true; + + } else if (str->IsExternal()) { + const v8::String::ExternalStringResource* ext; + ext = str->GetExternalStringResource(); + *data = reinterpret_cast(ext->data()); + *len = ext->length(); + return true; + } + + return false; +} + +namespace Nan { + enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; +} + +static inline char* NanFromV8String( + v8::Handle from + , enum Nan::Encoding encoding = Nan::UTF8 + , size_t *datalen = NULL + , char *buf = NULL + , size_t buflen = 0 + , int flags = v8::String::NO_NULL_TERMINATION + | v8::String::HINT_MANY_WRITES_EXPECTED) { + + NanScope(); + + size_t sz_; + size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION); + char *data = NULL; + size_t len; + bool is_extern = _NanGetExternalParts( + from + , const_cast(&data) + , &len); + + if (is_extern && !term_len) { + NanSetPointerSafe(datalen, len); + return data; + } + + v8::Local toStr = from->ToString(); + + char *to = buf; + + v8::String::AsciiValue value(toStr); + switch(encoding) { + case Nan::ASCII: +#if NODE_MODULE_VERSION < 0x0C + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } + NanSetPointerSafe( + datalen + , toStr->WriteAscii(to, 0, sz_ + term_len, flags)); + return to; +#endif + case Nan::BINARY: + case Nan::BUFFER: + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } +#if NODE_MODULE_VERSION < 0x0C + // TODO(isaacs): THIS IS AWFUL!!! + // AGREE(kkoopa) + { + uint16_t* twobytebuf = new uint16_t[sz_ + term_len]; + + size_t len = toStr->Write(twobytebuf, 0, sz_ + term_len, flags); + + for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) { + unsigned char *b = reinterpret_cast(&twobytebuf[i]); + to[i] = *b; + } + + NanSetPointerSafe(datalen, len); + + delete[] twobytebuf; + return to; + } +#else + NanSetPointerSafe( + datalen, + toStr->WriteOneByte( + reinterpret_cast(to) + , 0 + , sz_ + term_len + , flags)); + return to; +#endif + case Nan::UTF8: + sz_ = toStr->Utf8Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } + NanSetPointerSafe( + datalen + , toStr->WriteUtf8(to, sz_ + term_len, NULL, flags) - term_len); + return to; + case Nan::BASE64: + sz_ = _nan_base64_decoded_size(*value, toStr->Length()); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len); + } + NanSetPointerSafe( + datalen + , _nan_base64_decode(to, sz_, *value, value.length())); + if (term_len) { + to[sz_] = '\0'; + } + return to; + case Nan::UCS2: + { + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[(sz_ + term_len) * 2]; + } else { + assert(buflen >= (sz_ + term_len) * 2 && "too small buffer"); + } + + int bc = 2 * toStr->Write( + reinterpret_cast(to) + , 0 + , sz_ + term_len + , flags); + NanSetPointerSafe(datalen, bc); + return to; + } + case Nan::HEX: + sz_ = toStr->Length(); + assert(!(sz_ & 1) && "bad hex data"); + if (to == NULL) { + to = new char[sz_ / 2 + term_len]; + } else { + assert(buflen >= sz_ / 2 + term_len && "too small buffer"); + } + + NanSetPointerSafe( + datalen + , _nan_hex_decode(to, sz_ / 2, *value, value.length())); + if (term_len) { + to[sz_ / 2] = '\0'; + } + return to; + default: + assert(0 && "unknown encoding"); + } + return to; +} + +#endif diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/package.json new file mode 100644 index 00000000..34ba61a9 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/nan/package.json @@ -0,0 +1,36 @@ +{ + "name": "nan", + "version": "0.3.2", + "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility", + "main": ".index.js", + "repository": { + "type": "git", + "url": "git://github.com/rvagg/nan.git" + }, + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "Benjamin Byholm", + "email": "bbyholm@abo.fi", + "url": "https://github.com/kkoopa/" + }, + { + "name": "Trevor Norris", + "email": "trev.norris@gmail.com", + "url": "https://github.com/trevnorris" + } + ], + "license": "MIT", + "readme": "Native Abstractions for Node.js\n===============================\n\n**A header file filled with macro and utility goodness for making addon development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.**\n\n***Current version: 0.3.2*** *(See [nan.h](https://github.com/rvagg/nan/blob/master/nan.h) for changelog)*\n\n[![NPM](https://nodei.co/npm/nan.png?downloads=true&stars=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/)\n\nThanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle.\n\nThis project also contains some helper utilities that make addon development a bit more pleasant.\n\n * **[Usage](#usage)**\n * **[Example](#example)**\n * **[API](#api)**\n\n\n## Usage\n\nSimply add **NAN** as a dependency in the *package.json* of your Node addon:\n\n```js\n\"dependencies\": {\n ...\n \"nan\" : \"~0.3.1\"\n ...\n}\n```\n\nPull in the path to **NAN** in your *binding.gyp* so that you can use `#include \"nan.h\"` in your *.cpp*:\n\n```js\n\"include_dirs\" : [\n ...\n \"` when compiling your addon.\n\n\n## Example\n\nSee **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use.\n\nFor a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**.\n\nCompare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work).\n\nNote that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class.\n\n```c++\n// addon.cc\n#include \n#include \"nan.h\"\n// ...\n\nusing namespace v8;\n\nvoid InitAll(Handle exports) {\n exports->Set(NanSymbol(\"calculateSync\"),\n FunctionTemplate::New(CalculateSync)->GetFunction());\n\n exports->Set(NanSymbol(\"calculateAsync\"),\n FunctionTemplate::New(CalculateAsync)->GetFunction());\n}\n\nNODE_MODULE(addon, InitAll)\n```\n\n```c++\n// sync.h\n#include \n#include \"nan.h\"\n\nNAN_METHOD(CalculateSync);\n```\n\n```c++\n// sync.cc\n#include \n#include \"nan.h\"\n#include \"sync.h\"\n// ...\n\nusing namespace v8;\n\n// Simple synchronous access to the `Estimate()` function\nNAN_METHOD(CalculateSync) {\n NanScope();\n\n // expect a number as the first argument\n int points = args[0]->Uint32Value();\n double est = Estimate(points);\n\n NanReturnValue(Number::New(est));\n}\n```\n\n```c++\n// async.cc\n#include \n#include \"nan.h\"\n#include \"async.h\"\n\n// ...\n\nusing namespace v8;\n\nclass PiWorker : public NanAsyncWorker {\n public:\n PiWorker(NanCallback *callback, int points)\n : NanAsyncWorker(callback), points(points) {}\n ~PiWorker() {}\n\n // Executed inside the worker-thread.\n // It is not safe to access V8, or V8 data structures\n // here, so everything we need for input and output\n // should go on `this`.\n void Execute () {\n estimate = Estimate(points);\n }\n\n // Executed when the async work is complete\n // this function will be run inside the main event loop\n // so it is safe to use V8 again\n void HandleOKCallback () {\n NanScope();\n\n Local argv[] = {\n Local::New(Null())\n , Number::New(estimate)\n };\n\n callback->Call(2, argv);\n };\n\n private:\n int points;\n double estimate;\n};\n\n// Asynchronous access to the `Estimate()` function\nNAN_METHOD(CalculateAsync) {\n NanScope();\n\n int points = args[0]->Uint32Value();\n NanCallback *callback = new NanCallback(args[1].As());\n\n NanAsyncQueueWorker(new PiWorker(callback, points));\n NanReturnUndefined();\n}\n```\n\n\n## API\n\n * NAN_METHOD\n * NAN_GETTER\n * NAN_SETTER\n * NAN_PROPERTY_GETTER\n * NAN_PROPERTY_SETTER\n * NAN_PROPERTY_ENUMERATOR\n * NAN_PROPERTY_DELETER\n * NAN_PROPERTY_QUERY\n * NAN_WEAK_CALLBACK\n * NanReturnValue\n * NanReturnUndefined\n * NanReturnNull\n * NanReturnEmptyString\n * NanScope\n * NanLocker\n * NanUnlocker\n * NanGetInternalFieldPointer\n * NanSetInternalFieldPointer\n * NanObjectWrapHandle\n * NanMakeWeak\n * NanSymbol\n * NanGetPointerSafe\n * NanSetPointerSafe\n * NanFromV8String\n * NanBooleanOptionValue\n * NanUInt32OptionValue\n * NanThrowError, NanThrowTypeError, NanThrowRangeError, NanThrowError(Handle), NanThrowError(Handle, int)\n * NanNewBufferHandle(char *, size_t, FreeCallback, void *), NanNewBufferHandle(char *, uint32_t), NanNewBufferHandle(uint32_t)\n * NanBufferUse(char *, uint32_t)\n * NanNewContextHandle\n * NanHasInstance\n * NanPersistentToLocal\n * NanDispose\n * NanAssignPersistent\n * NanInitPersistent\n * NanCallback\n * NanAsyncWorker\n * NanAsyncQueueWorker\n\n\n### NAN_METHOD(methodname)\n\nUse `NAN_METHOD` to define your V8 accessible methods:\n\n```c++\n// .h:\nclass Foo : public node::ObjectWrap {\n ...\n\n static NAN_METHOD(Bar);\n static NAN_METHOD(Baz);\n}\n\n\n// .cc:\nNAN_METHOD(Foo::Bar) {\n ...\n}\n\nNAN_METHOD(Foo::Baz) {\n ...\n}\n```\n\nThe reason for this macro is because of the method signature change in 0.11:\n\n```c++\n// 0.10 and below:\nHandle name(const Arguments& args)\n\n// 0.11 and above\nvoid name(const FunctionCallbackInfo& args)\n```\n\nThe introduction of `FunctionCallbackInfo` brings additional complications:\n\n\n### NAN_GETTER(methodname)\n\nUse `NAN_GETTER` to declare your V8 accessible getters. You get a `Local` `property` and an appropriately typed `args` object that can act like the `args` argument to a `NAN_METHOD` call.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_GETTER`.\n\n\n### NAN_SETTER(methodname)\n\nUse `NAN_SETTER` to declare your V8 accessible setters. Same as `NAN_GETTER` but you also get a `Local` `value` object to work with.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_SETTER`.\n\n\n### NAN_PROPERTY_GETTER(cbname)\nUse `NAN_PROPERTY_GETTER` to declare your V8 accessible property getters. You get a `Local` `property` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_GETTER`.\n\n\n### NAN_PROPERTY_SETTER(cbname)\nUse `NAN_PROPERTY_SETTER` to declare your V8 accessible property setters. Same as `NAN_PROPERTY_GETTER` but you also get a `Local` `value` object to work with.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_SETTER`.\n\n\n### NAN_PROPERTY_ENUMERATOR(cbname)\nUse `NAN_PROPERTY_ENUMERATOR` to declare your V8 accessible property enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_PROPERTY_GETTER` call.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_ENUMERATOR`.\n\n\n### NAN_PROPERTY_DELETER(cbname)\nUse `NAN_PROPERTY_DELETER` to declare your V8 accessible property deleters. Same as `NAN_PROPERTY_GETTER`.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_DELETER`.\n\n\n### NAN_PROPERTY_QUERY(cbname)\nUse `NAN_PROPERTY_QUERY` to declare your V8 accessible property queries. Same as `NAN_PROPERTY_GETTER`.\n\nYou can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_QUERY`.\n\n\n### NAN_WEAK_CALLBACK(type, cbname)\n\nUse `NAN_WEAK_CALLBACK` to declare your V8 WeakReference callbacks. There is an object argument accessible through `NAN_WEAK_CALLBACK_OBJECT`. The `type` argument gives the type of the `data` argument, accessible through `NAN_WEAK_CALLBACK_DATA(type)`.\n\n```c++\nstatic NAN_WEAK_CALLBACK(BufferReference*, WeakCheck) {\n if (NAN_WEAK_CALLBACK_DATA(BufferReference*)->noLongerNeeded_) {\n delete NAN_WEAK_CALLBACK_DATA(BufferReference*);\n } else {\n // Still in use, revive, prevent GC\n NanMakeWeak(NAN_WEAK_CALLBACK_OBJECT, NAN_WEAK_CALLBACK_DATA(BufferReference*), &WeakCheck);\n }\n}\n\n```\n\n### NanReturnValue(Handle<Value>)\n\nUse `NanReturnValue` when you want to return a value from your V8 accessible method:\n\n```c++\nNAN_METHOD(Foo::Bar) {\n ...\n\n NanReturnValue(String::New(\"FooBar!\"));\n}\n```\n\nNo `return` statement required.\n\n\n### NanReturnUndefined()\n\nUse `NanReturnUndefined` when you don't want to return anything from your V8 accessible method:\n\n```c++\nNAN_METHOD(Foo::Baz) {\n ...\n\n NanReturnUndefined();\n}\n```\n\n\n### NanReturnNull()\n\nUse `NanReturnNull` when you want to return `Null` from your V8 accessible method:\n\n```c++\nNAN_METHOD(Foo::Baz) {\n ...\n\n NanReturnNull();\n}\n```\n\n\n### NanReturnEmptyString()\n\nUse `NanReturnEmptyString` when you want to return an empty `String` from your V8 accessible method:\n\n```c++\nNAN_METHOD(Foo::Baz) {\n ...\n\n NanReturnEmptyString();\n}\n```\n\n\n### NanScope()\n\nThe introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanScope()` necessary, use it in place of `HandleScope scope`:\n\n```c++\nNAN_METHOD(Foo::Bar) {\n NanScope();\n\n NanReturnValue(String::New(\"FooBar!\"));\n}\n```\n\n\n### NanLocker()\n\nThe introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanLocker()` necessary, use it in place of `Locker locker`:\n\n```c++\nNAN_METHOD(Foo::Bar) {\n NanLocker();\n ...\n NanUnlocker();\n}\n```\n\n\n### NanUnlocker()\n\nThe introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanUnlocker()` necessary, use it in place of `Unlocker unlocker`:\n\n```c++\nNAN_METHOD(Foo::Bar) {\n NanLocker();\n ...\n NanUnlocker();\n}\n```\n\n\n### void * NanGetInternalFieldPointer(Handle<Object>, int)\n\nGets a pointer to the internal field with at `index` from a V8 `Object` handle.\n\n```c++\nLocal obj;\n...\nNanGetInternalFieldPointer(obj, 0);\n```\n\n### void NanSetInternalFieldPointer(Handle<Object>, int, void *)\n\nSets the value of the internal field at `index` on a V8 `Object` handle.\n\n```c++\nstatic Persistent dataWrapperCtor;\n...\nLocal wrapper = NanPersistentToLocal(dataWrapperCtor)->NewInstance();\nNanSetInternalFieldPointer(wrapper, 0, this);\n```\n\n\n### Local<Object> NanObjectWrapHandle(Object)\n\nWhen you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`:\n\n```c++\nNanObjectWrapHandle(iterator)->Get(String::NewSymbol(\"end\"))\n```\n\n\n### NanMakeWeak(Persistent<T>, parameter, callback)\n\nMake a persistent reference weak.\n\n\n### String NanSymbol(char *)\n\nThis isn't strictly about compatibility, it's just an easier way to create string symbol objects (i.e. `String::NewSymbol(x)`), for getting and setting object properties, or names of objects.\n\n```c++\nbool foo = false;\nif (obj->Has(NanSymbol(\"foo\")))\n foo = optionsObj->Get(NanSymbol(\"foo\"))->BooleanValue()\n```\n\n\n### Type NanGetPointerSafe(Type *[, Type])\n\nA helper for getting values from optional pointers. If the pointer is `NULL`, the function returns the optional default value, which defaults to `0`. Otherwise, the function returns the value the pointer points to.\n\n```c++\nchar *plugh(uint32_t *optional) {\n char res[] = \"xyzzy\";\n uint32_t param = NanGetPointerSafe(optional, 0x1337);\n switch (param) {\n ...\n }\n NanSetPointerSafe(optional, 0xDEADBEEF);\n} \n```\n\n\n### bool NanSetPointerSafe(Type *, Type)\n\nA helper for setting optional argument pointers. If the pointer is `NULL`, the function simply return `false`. Otherwise, the value is assigned to the variable the pointer points to.\n\n```c++\nconst char *plugh(size_t *outputsize) {\n char res[] = \"xyzzy\";\n if !(NanSetPointerSafe(outputsize, strlen(res) + 1)) {\n ...\n }\n\n ...\n}\n```\n\n\n### char* NanFromV8String(Handle<Value>[, enum Nan::Encoding, size_t *, char *, size_t, int])\n\nWhen you want to convert a V8 `String` to a `char*` use `NanFromV8String`. It is possible to define an encoding that defaults to `Nan::UTF8` as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `String::HINT_MANY_WRITES_EXPECTED | String::NO_NULL_TERMINATION`.\nJust remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer:\n\n```c++\nsize_t count;\nchar* name = NanFromV8String(args[0]);\nchar* decoded = NanFromV8String(args[1], Nan::BASE64, &count, NULL, 0, String::HINT_MANY_WRITES_EXPECTED);\nchar param_copy[count];\nmemcpy(param_copy, decoded, count);\ndelete[] decoded;\n```\n\n\n### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool])\n\nWhen you have an \"options\" object that you need to fetch properties from, boolean options can be fetched with this pair. They check first if the object exists (`IsEmpty`), then if the object has the given property (`Has`) then they get and convert/coerce the property to a `bool`.\n\nThe optional last parameter is the *default* value, which is `false` if left off:\n\n```c++\n// `foo` is false unless the user supplies a truthy value for it\nbool foo = NanBooleanOptionValue(optionsObj, NanSymbol(\"foo\"));\n// `bar` is true unless the user supplies a falsy value for it\nbool bar = NanBooleanOptionValueDefTrue(optionsObj, NanSymbol(\"bar\"), true);\n```\n\n\n### uint32_t NanUInt32OptionValue(Handle<Value>, Handle<String>, uint32_t)\n\nSimilar to `NanBooleanOptionValue`, use `NanUInt32OptionValue` to fetch an integer option from your options object. Can be any kind of JavaScript `Number` and it will be coerced to an unsigned 32-bit integer.\n\nRequires all 3 arguments as a default is not optional:\n\n```c++\nuint32_t count = NanUInt32OptionValue(optionsObj, NanSymbol(\"count\"), 1024);\n```\n\n\n### NanThrowError(message), NanThrowTypeError(message), NanThrowRangeError(message), NanThrowError(Local<Value>), NanThrowError(Local<Value>, int)\n\nFor throwing `Error`, `TypeError` and `RangeError` objects. You should `return` this call:\n\n```c++\nreturn NanThrowError(\"you must supply a callback argument\");\n```\n\nCan also handle any custom object you may want to throw. If used with the error code argument, it will add the supplied error code to the error object as a property called `code`.\n\n\n### Local<Object> NanNewBufferHandle(char *, uint32_t), Local<Object> NanNewBufferHandle(uint32_t)\n\nThe `Buffer` API has changed a little in Node 0.11, this helper provides consistent access to `Buffer` creation:\n\n```c++\nNanNewBufferHandle((char*)value.data(), value.size());\n```\n\nCan also be used to initialize a `Buffer` with just a `size` argument.\n\nCan also be supplied with a `NAN_WEAK_CALLBACK` and a hint for the garbage collector, when dealing with weak references.\n\n\n### Local<Object> NanBufferUse(char*, uint32_t)\n\n`Buffer::New(char*, uint32_t)` prior to 0.11 would make a copy of the data.\nWhile it was possible to get around this, it required a shim by passing a\ncallback. So the new API `Buffer::Use(char*, uint32_t)` was introduced to remove\nneeding to use this shim.\n\n`NanBufferUse` uses the `char*` passed as the backing data, and will free the\nmemory automatically when the weak callback is called. Keep this in mind, as\ncareless use can lead to \"double free or corruption\" and other cryptic failures.\n\n\n### bool NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)\n\nCan be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent` handle for.\n\n\n### Local<Type> NanPersistentToLocal(Persistent<Type>&)\n\nAside from `FunctionCallbackInfo`, the biggest and most painful change to V8 in Node 0.11 is the many restrictions now placed on `Persistent` handles. They are difficult to assign and difficult to fetch the original value out of.\n\nUse `NanPersistentToLocal` to convert a `Persistent` handle back to a `Local` handle.\n\n```c++\nLocal handle = NanPersistentToLocal(persistentHandle);\n```\n\n\n### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>])\nCreates a new `Local` handle.\n\n```c++\nLocal ftmpl = FunctionTemplate::New();\nLocal otmpl = ftmpl->InstanceTemplate();\nLocal ctx = NanNewContextHandle(NULL, otmpl);\n```\n\n\n### void NanDispose(Persistent<T> &)\n\nUse `NanDispose` to dispose a `Persistent` handle.\n\n```c++\nNanDispose(persistentHandle);\n```\n\n\n### NanAssignPersistent(type, handle, object)\n\nUse `NanAssignPersistent` to assign a non-`Persistent` handle to a `Persistent` one. You can no longer just declare a `Persistent` handle and assign directly to it later, you have to `Reset` it in Node 0.11, so this makes it easier.\n\nIn general it is now better to place anything you want to protect from V8's garbage collector as properties of a generic `Object` and then assign that to a `Persistent`. This works in older versions of Node also if you use `NanAssignPersistent`:\n\n```c++\nPersistent persistentHandle;\n\n...\n\nLocal obj = Object::New();\nobj->Set(NanSymbol(\"key\"), keyHandle); // where keyHandle might be a Local\nNanAssignPersistent(Object, persistentHandle, obj)\n```\n\n\n### NanInitPersistent(type, name, object)\n\nUser `NanInitPersistent` to declare and initialize a new `Persistent` with the supplied object. The assignment operator for `Persistent` is no longer public in Node 0.11, so this macro makes it easier to declare and initializing a new `Persistent`. See NanAssignPersistent for more information.\n\n```c++\nLocal obj = Object::New();\nobj->Set(NanSymbol(\"key\"), keyHandle); // where keyHandle might be a Local\nNanInitPersistent(Object, persistentHandle, obj);\n```\n\n\n### NanCallback\n\nBecause of the difficulties imposed by the changes to `Persistent` handles in V8 in Node 0.11, creating `Persistent` versions of your `Local` handles is annoyingly tricky. `NanCallback` makes it easier by taking your `Local` handle, making it persistent until the `NanCallback` is deleted and even providing a handy `Call()` method to fetch and execute the callback `Function`.\n\n```c++\nLocal callbackHandle = callback = args[0].As();\nNanCallback *callback = new NanCallback(callbackHandle);\n// pass `callback` around and it's safe from GC until you:\ndelete callback;\n```\n\nYou can execute the callback like so:\n\n```c++\n// no arguments:\ncallback->Call(0, NULL);\n\n// an error argument:\nLocal argv[] = {\n Exception::Error(String::New(\"fail!\"))\n};\ncallback->Call(1, argv);\n\n// a success argument:\nLocal argv[] = {\n Local::New(Null()),\n String::New(\"w00t!\")\n};\ncallback->Call(2, argv);\n```\n\n`NanCallback` also has a `Local GetCallback()` method that you can use to fetch a local handle to the underlying callback function if you need it.\n\n\n### NanAsyncWorker\n\n`NanAsyncWorker` is an abstract class that you can subclass to have much of the annoying async queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the async work is in progress.\n\nSee a rough outline of the implementation:\n\n```c++\nclass NanAsyncWorker {\npublic:\n NanAsyncWorker (NanCallback *callback);\n\n // Clean up persistent handles and delete the *callback\n virtual ~NanAsyncWorker ();\n\n // Check the `char *errmsg` property and call HandleOKCallback()\n // or HandleErrorCallback depending on whether it has been set or not\n virtual void WorkComplete ();\n\n // You must implement this to do some async work. If there is an\n // error then allocate `errmsg` to to a message and the callback will\n // be passed that string in an Error object\n virtual void Execute ();\n\nprotected:\n // Set this if there is an error, otherwise it's NULL\n const char *errmsg;\n\n // Save a V8 object in a Persistent handle to protect it from GC\n void SavePersistent(const char *key, Local &obj);\n\n // Fetch a stored V8 object (don't call from within `Execute()`)\n Local GetFromPersistent(const char *key);\n\n // Default implementation calls the callback function with no arguments.\n // Override this to return meaningful data\n virtual void HandleOKCallback ();\n\n // Default implementation calls the callback function with an Error object\n // wrapping the `errmsg` string\n virtual void HandleErrorCallback ();\n};\n```\n\n\n### NanAsyncQueueWorker(NanAsyncWorker *)\n\n`NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`.\n\n### Contributors\n\nNAN is only possible due to the excellent work of the following contributors:\n\n\n\n\n\n
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
\n\nLicence & copyright\n-----------------------\n\nCopyright (c) 2013 Rod Vagg & NAN contributors (listed above).\n\nNative Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/rvagg/nan/issues" + }, + "homepage": "https://github.com/rvagg/nan", + "_id": "nan@0.3.2", + "_from": "nan@~0.3.0" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/.npmignore b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/.npmignore new file mode 100644 index 00000000..6bfffbb7 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/.npmignore @@ -0,0 +1,5 @@ +npm-debug.log +node_modules +.*.swp +.lock-* +build/ diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/Makefile b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/Makefile new file mode 100644 index 00000000..7496b6fc --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/Makefile @@ -0,0 +1,12 @@ +ALL_TESTS = $(shell find test/ -name '*.test.js') + +run-tests: + @./node_modules/.bin/mocha \ + -t 2000 \ + $(TESTFLAGS) \ + $(TESTS) + +test: + @$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests + +.PHONY: test diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/README.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/README.md new file mode 100644 index 00000000..4b39a2a7 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/README.md @@ -0,0 +1,28 @@ +# options.js # + +A very light-weight in-code option parsers for node.js. + +## License ## + +(The MIT License) + +Copyright (c) 2012 Einar Otto Stangvik <einaros@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/lib/options.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/lib/options.js new file mode 100644 index 00000000..4fc45e90 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/lib/options.js @@ -0,0 +1,86 @@ +/*! + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +var fs = require('fs'); + +function Options(defaults) { + var internalValues = {}; + var values = this.value = {}; + Object.keys(defaults).forEach(function(key) { + internalValues[key] = defaults[key]; + Object.defineProperty(values, key, { + get: function() { return internalValues[key]; }, + configurable: false, + enumerable: true + }); + }); + this.reset = function() { + Object.keys(defaults).forEach(function(key) { + internalValues[key] = defaults[key]; + }); + return this; + }; + this.merge = function(options, required) { + options = options || {}; + if (Object.prototype.toString.call(required) === '[object Array]') { + var missing = []; + for (var i = 0, l = required.length; i < l; ++i) { + var key = required[i]; + if (!(key in options)) { + missing.push(key); + } + } + if (missing.length > 0) { + if (missing.length > 1) { + throw new Error('options ' + + missing.slice(0, missing.length - 1).join(', ') + ' and ' + + missing[missing.length - 1] + ' must be defined'); + } + else throw new Error('option ' + missing[0] + ' must be defined'); + } + } + Object.keys(options).forEach(function(key) { + if (key in internalValues) { + internalValues[key] = options[key]; + } + }); + return this; + }; + this.copy = function(keys) { + var obj = {}; + Object.keys(defaults).forEach(function(key) { + if (keys.indexOf(key) !== -1) { + obj[key] = values[key]; + } + }); + return obj; + }; + this.read = function(filename, cb) { + if (typeof cb == 'function') { + var self = this; + fs.readFile(filename, function(error, data) { + if (error) return cb(error); + var conf = JSON.parse(data); + self.merge(conf); + cb(); + }); + } + else { + var conf = JSON.parse(fs.readFileSync(filename)); + this.merge(conf); + } + return this; + }; + this.isDefined = function(key) { + return typeof values[key] != 'undefined'; + }; + this.isDefinedAndNonNull = function(key) { + return typeof values[key] != 'undefined' && values[key] !== null; + }; + Object.freeze(values); + Object.freeze(this); +} + +module.exports = Options; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/package.json new file mode 100644 index 00000000..cbdc5c21 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/package.json @@ -0,0 +1,33 @@ +{ + "author": { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com", + "url": "http://2x.io" + }, + "name": "options", + "description": "A very light-weight in-code option parsers for node.js.", + "version": "0.0.5", + "repository": { + "type": "git", + "url": "git://github.com/einaros/options.js.git" + }, + "main": "lib/options", + "scripts": { + "test": "make test" + }, + "engines": { + "node": ">=0.4.0" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "latest" + }, + "readme": "# options.js #\n\nA very light-weight in-code option parsers for node.js.\n\n## License ##\n\n(The MIT License)\n\nCopyright (c) 2012 Einar Otto Stangvik <einaros@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/einaros/options.js/issues" + }, + "homepage": "https://github.com/einaros/options.js", + "_id": "options@0.0.5", + "_from": "options@>=0.0.5" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/fixtures/test.conf b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/fixtures/test.conf new file mode 100644 index 00000000..6e624441 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/fixtures/test.conf @@ -0,0 +1,4 @@ +{ + "a": "foobar", + "b": false +} \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/options.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/options.test.js new file mode 100644 index 00000000..6a1d9f5b --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/options.test.js @@ -0,0 +1,140 @@ +var Options = require('options') + , assert = require('assert'); + +describe('Options', function() { + describe('#ctor', function() { + it('initializes options', function() { + var option = new Options({a: true, b: false}); + assert.strictEqual(true, option.value.a); + assert.strictEqual(false, option.value.b); + }); + }); + + describe('#merge', function() { + it('merges options from another object', function() { + var option = new Options({a: true, b: false}); + option.merge({b: true}); + assert.strictEqual(true, option.value.a); + assert.strictEqual(true, option.value.b); + }); + it('does nothing when arguments are undefined', function() { + var option = new Options({a: true, b: false}); + option.merge(undefined); + assert.strictEqual(true, option.value.a); + assert.strictEqual(false, option.value.b); + }); + it('cannot set values that werent already there', function() { + var option = new Options({a: true, b: false}); + option.merge({c: true}); + assert.strictEqual('undefined', typeof option.value.c); + }); + it('can require certain options to be defined', function() { + var option = new Options({a: true, b: false, c: 3}); + var caughtException = false; + try { + option.merge({}, ['a', 'b', 'c']); + } + catch (e) { + caughtException = e.toString() == 'Error: options a, b and c must be defined'; + } + assert.strictEqual(true, caughtException); + }); + it('can require certain options to be defined, when options are undefined', function() { + var option = new Options({a: true, b: false, c: 3}); + var caughtException = false; + try { + option.merge(undefined, ['a', 'b', 'c']); + } + catch (e) { + caughtException = e.toString() == 'Error: options a, b and c must be defined'; + } + assert.strictEqual(true, caughtException); + }); + it('returns "this"', function() { + var option = new Options({a: true, b: false, c: 3}); + assert.strictEqual(option, option.merge()); + }); + }); + + describe('#copy', function() { + it('returns a new object with the indicated options', function() { + var option = new Options({a: true, b: false, c: 3}); + option.merge({c: 4}); + var obj = option.copy(['a', 'c']); + assert.strictEqual(true, obj.a); + assert.strictEqual(4, obj.c); + assert.strictEqual('undefined', typeof obj.b); + }); + }); + + describe('#value', function() { + it('can be enumerated', function() { + var option = new Options({a: true, b: false}); + assert.strictEqual(2, Object.keys(option.value).length); + }); + it('can not be used to set values', function() { + var option = new Options({a: true, b: false}); + option.value.b = true; + assert.strictEqual(false, option.value.b); + }); + it('can not be used to add values', function() { + var option = new Options({a: true, b: false}); + option.value.c = 3; + assert.strictEqual('undefined', typeof option.value.c); + }); + }); + + describe('#isDefined', function() { + it('returns true if the named value is defined', function() { + var option = new Options({a: undefined}); + assert.strictEqual(false, option.isDefined('a')); + option.merge({a: false}); + assert.strictEqual(true, option.isDefined('a')); + }); + }); + + describe('#isDefinedAndNonNull', function() { + it('returns true if the named value is defined and non-null', function() { + var option = new Options({a: undefined}); + assert.strictEqual(false, option.isDefinedAndNonNull('a')); + option.merge({a: null}); + assert.strictEqual(false, option.isDefinedAndNonNull('a')); + option.merge({a: 2}); + assert.strictEqual(true, option.isDefinedAndNonNull('a')); + }); + }); + + describe('#read', function() { + it('reads and merges config from a file', function() { + var option = new Options({a: true, b: true}); + option.read(__dirname + '/fixtures/test.conf'); + assert.strictEqual('foobar', option.value.a); + assert.strictEqual(false, option.value.b); + }); + + it('asynchronously reads and merges config from a file when a callback is passed', function(done) { + var option = new Options({a: true, b: true}); + option.read(__dirname + '/fixtures/test.conf', function(error) { + assert.strictEqual('foobar', option.value.a); + assert.strictEqual(false, option.value.b); + done(); + }); + }); + }); + + describe('#reset', function() { + it('resets options to defaults', function() { + var option = new Options({a: true, b: false}); + option.merge({b: true}); + assert.strictEqual(true, option.value.b); + option.reset(); + assert.strictEqual(false, option.value.b); + }); + }); + + it('is immutable', function() { + var option = new Options({a: true, b: false}); + option.foo = 2; + assert.strictEqual('undefined', typeof option.foo); + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/.npmignore b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/.npmignore new file mode 100644 index 00000000..6bfffbb7 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/.npmignore @@ -0,0 +1,5 @@ +npm-debug.log +node_modules +.*.swp +.lock-* +build/ diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/README.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/README.md new file mode 100644 index 00000000..55eb3c11 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/README.md @@ -0,0 +1,3 @@ +# tinycolor # + +This is a no-fuzz, barebone, zero muppetry color module for node.js. \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/example.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/example.js new file mode 100644 index 00000000..f7540468 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/example.js @@ -0,0 +1,3 @@ +require('./tinycolor'); +console.log('this should be red and have an underline!'.grey.underline); +console.log('this should have a blue background!'.bgBlue); \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/package.json new file mode 100644 index 00000000..c9a34e93 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/package.json @@ -0,0 +1,28 @@ +{ + "author": { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com", + "url": "http://2x.io" + }, + "name": "tinycolor", + "description": "a to-the-point color module for node", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "git://github.com/einaros/tinycolor.git" + }, + "engines": { + "node": ">=0.4.0" + }, + "dependencies": {}, + "devDependencies": {}, + "main": "tinycolor", + "readme": "# tinycolor #\n\nThis is a no-fuzz, barebone, zero muppetry color module for node.js.", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/einaros/tinycolor/issues" + }, + "homepage": "https://github.com/einaros/tinycolor", + "_id": "tinycolor@0.0.1", + "_from": "tinycolor@0.x" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/tinycolor.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/tinycolor.js new file mode 100644 index 00000000..36e552c4 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/tinycolor.js @@ -0,0 +1,31 @@ +var styles = { + 'bold': ['\033[1m', '\033[22m'], + 'italic': ['\033[3m', '\033[23m'], + 'underline': ['\033[4m', '\033[24m'], + 'inverse': ['\033[7m', '\033[27m'], + 'black': ['\033[30m', '\033[39m'], + 'red': ['\033[31m', '\033[39m'], + 'green': ['\033[32m', '\033[39m'], + 'yellow': ['\033[33m', '\033[39m'], + 'blue': ['\033[34m', '\033[39m'], + 'magenta': ['\033[35m', '\033[39m'], + 'cyan': ['\033[36m', '\033[39m'], + 'white': ['\033[37m', '\033[39m'], + 'default': ['\033[39m', '\033[39m'], + 'grey': ['\033[90m', '\033[39m'], + 'bgBlack': ['\033[40m', '\033[49m'], + 'bgRed': ['\033[41m', '\033[49m'], + 'bgGreen': ['\033[42m', '\033[49m'], + 'bgYellow': ['\033[43m', '\033[49m'], + 'bgBlue': ['\033[44m', '\033[49m'], + 'bgMagenta': ['\033[45m', '\033[49m'], + 'bgCyan': ['\033[46m', '\033[49m'], + 'bgWhite': ['\033[47m', '\033[49m'], + 'bgDefault': ['\033[49m', '\033[49m'] +} +Object.keys(styles).forEach(function(style) { + Object.defineProperty(String.prototype, style, { + get: function() { return styles[style][0] + this + styles[style][1]; }, + enumerable: false + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/package.json new file mode 100644 index 00000000..71f2d880 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/package.json @@ -0,0 +1,61 @@ +{ + "author": { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com", + "url": "http://2x.io" + }, + "name": "ws", + "description": "simple to use, blazing fast and thoroughly tested websocket client, server and console for node.js, up-to-date against RFC-6455", + "version": "0.4.31", + "keywords": [ + "Hixie", + "HyBi", + "Push", + "RFC-6455", + "WebSocket", + "WebSockets", + "real-time" + ], + "repository": { + "type": "git", + "url": "git://github.com/einaros/ws.git" + }, + "bin": { + "wscat": "./bin/wscat" + }, + "scripts": { + "test": "make test", + "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)" + }, + "engines": { + "node": ">=0.4.0" + }, + "dependencies": { + "commander": "~0.6.1", + "nan": "~0.3.0", + "tinycolor": "0.x", + "options": ">=0.0.5" + }, + "devDependencies": { + "mocha": "1.12.0", + "should": "1.2.x", + "expect.js": "0.2.x", + "benchmark": "0.3.x", + "ansi": "latest" + }, + "browser": "./lib/browser.js", + "component": { + "scripts": { + "ws/index.js": "./lib/browser.js" + } + }, + "gypfile": true, + "readme": "[![Build Status](https://secure.travis-ci.org/einaros/ws.png)](http://travis-ci.org/einaros/ws)\n\n# ws: a node.js websocket library #\n\n`ws` is a simple to use websocket implementation, up-to-date against RFC-6455, and [probably the fastest WebSocket library for node.js](http://web.archive.org/web/20130314230536/http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs).\n\nPasses the quite extensive Autobahn test suite. See http://einaros.github.com/ws for the full reports.\n\nComes with a command line utility, `wscat`, which can either act as a server (--listen), or client (--connect); Use it to debug simple websocket services.\n\n## Protocol support ##\n\n* **Hixie draft 76** (Old and deprecated, but still in use by Safari and Opera. Added to ws version 0.4.2, but server only. Can be disabled by setting the `disableHixie` option to true.)\n* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`, or argument `-p 8` for wscat)\n* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`, or argument `-p 13` for wscat)\n\n_See the echo.websocket.org example below for how to use the `protocolVersion` option._\n\n## Usage ##\n\n### Installing ###\n\n`npm install ws`\n\n### Sending and receiving text data ###\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://www.host.com/path');\nws.on('open', function() {\n ws.send('something');\n});\nws.on('message', function(data, flags) {\n // flags.binary will be set if a binary data is received\n // flags.masked will be set if the data was masked\n});\n```\n\n### Sending binary data ###\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://www.host.com/path');\nws.on('open', function() {\n var array = new Float32Array(5);\n for (var i = 0; i < array.length; ++i) array[i] = i / 2;\n ws.send(array, {binary: true, mask: true});\n});\n```\n\nSetting `mask`, as done for the send options above, will cause the data to be masked according to the websocket protocol. The same option applies for text data.\n\n### Server example ###\n\n```js\nvar WebSocketServer = require('ws').Server\n , wss = new WebSocketServer({port: 8080});\nwss.on('connection', function(ws) {\n ws.on('message', function(message) {\n console.log('received: %s', message);\n });\n ws.send('something');\n});\n```\n\n### Server sending broadcast data ###\n\n```js\nvar WebSocketServer = require('ws').Server\n , wss = new WebSocketServer({port: 8080});\n \nwss.broadcast = function(data) {\n\tfor(var i in this.clients)\n\t\tthis.clients[i].send(data);\n};\n```\n\n### Error handling best practices ###\n\n```js\n// If the WebSocket is closed before the following send is attempted\nws.send('something');\n\n// Errors (both immediate and async write errors) can be detected in an optional callback.\n// The callback is also the only way of being notified that data has actually been sent.\nws.send('something', function(error) {\n // if error is null, the send has been completed,\n // otherwise the error object will indicate what failed.\n});\n\n// Immediate errors can also be handled with try/catch-blocks, but **note**\n// that since sends are inherently asynchronous, socket write failures will *not*\n// be captured when this technique is used.\ntry {\n ws.send('something');\n}\ncatch (e) {\n // handle error\n}\n```\n\n### echo.websocket.org demo ###\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://echo.websocket.org/', {protocolVersion: 8, origin: 'http://websocket.org'});\nws.on('open', function() {\n console.log('connected');\n ws.send(Date.now().toString(), {mask: true});\n});\nws.on('close', function() {\n console.log('disconnected');\n});\nws.on('message', function(data, flags) {\n console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags);\n setTimeout(function() {\n ws.send(Date.now().toString(), {mask: true});\n }, 500);\n});\n```\n\n### wscat against echo.websocket.org ###\n\n $ npm install -g ws\n $ wscat -c ws://echo.websocket.org -p 8\n connected (press CTRL+C to quit)\n > hi there\n < hi there\n > are you a happy parrot?\n < are you a happy parrot?\n\n### Other examples ###\n\nFor a full example with a browser client communicating with a ws server, see the examples folder.\n\nNote that the usage together with Express 3.0 is quite different from Express 2.x. The difference is expressed in the two different serverstats-examples.\n\nOtherwise, see the test cases.\n\n### Running the tests ###\n\n`make test`\n\n## API Docs ##\n\nSee the doc/ directory for Node.js-like docs for the ws classes.\n\n## License ##\n\n(The MIT License)\n\nCopyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/einaros/ws/issues" + }, + "homepage": "https://github.com/einaros/ws", + "_id": "ws@0.4.31", + "_from": "ws@0.4.x" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/bufferutil.cc b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/bufferutil.cc new file mode 100644 index 00000000..f06777f4 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/bufferutil.cc @@ -0,0 +1,117 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "nan.h" + +using namespace v8; +using namespace node; + +class BufferUtil : public ObjectWrap +{ +public: + + static void Initialize(v8::Handle target) + { + NanScope(); + Local t = FunctionTemplate::New(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + NODE_SET_METHOD(t, "unmask", BufferUtil::Unmask); + NODE_SET_METHOD(t, "mask", BufferUtil::Mask); + NODE_SET_METHOD(t, "merge", BufferUtil::Merge); + target->Set(String::NewSymbol("BufferUtil"), t->GetFunction()); + } + +protected: + + static NAN_METHOD(New) + { + NanScope(); + BufferUtil* bufferUtil = new BufferUtil(); + bufferUtil->Wrap(args.This()); + NanReturnValue(args.This()); + } + + static NAN_METHOD(Merge) + { + NanScope(); + Local bufferObj = args[0]->ToObject(); + char* buffer = Buffer::Data(bufferObj); + Local array = Local::Cast(args[1]); + unsigned int arrayLength = array->Length(); + size_t offset = 0; + unsigned int i; + for (i = 0; i < arrayLength; ++i) { + Local src = array->Get(i)->ToObject(); + size_t length = Buffer::Length(src); + memcpy(buffer + offset, Buffer::Data(src), length); + offset += length; + } + NanReturnValue(True()); + } + + static NAN_METHOD(Unmask) + { + NanScope(); + Local buffer_obj = args[0]->ToObject(); + size_t length = Buffer::Length(buffer_obj); + Local mask_obj = args[1]->ToObject(); + unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj); + unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj); + size_t len32 = length / 4; + unsigned int i; + for (i = 0; i < len32; ++i) *(from + i) ^= *mask; + from += i; + switch (length % 4) { + case 3: *((unsigned char*)from+2) = *((unsigned char*)from+2) ^ ((unsigned char*)mask)[2]; + case 2: *((unsigned char*)from+1) = *((unsigned char*)from+1) ^ ((unsigned char*)mask)[1]; + case 1: *((unsigned char*)from ) = *((unsigned char*)from ) ^ ((unsigned char*)mask)[0]; + case 0:; + } + NanReturnValue(True()); + } + + static NAN_METHOD(Mask) + { + NanScope(); + Local buffer_obj = args[0]->ToObject(); + Local mask_obj = args[1]->ToObject(); + unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj); + Local output_obj = args[2]->ToObject(); + unsigned int dataOffset = args[3]->Int32Value(); + unsigned int length = args[4]->Int32Value(); + unsigned int* to = (unsigned int*)(Buffer::Data(output_obj) + dataOffset); + unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj); + unsigned int len32 = length / 4; + unsigned int i; + for (i = 0; i < len32; ++i) *(to + i) = *(from + i) ^ *mask; + to += i; + from += i; + switch (length % 4) { + case 3: *((unsigned char*)to+2) = *((unsigned char*)from+2) ^ *((unsigned char*)mask+2); + case 2: *((unsigned char*)to+1) = *((unsigned char*)from+1) ^ *((unsigned char*)mask+1); + case 1: *((unsigned char*)to ) = *((unsigned char*)from ) ^ *((unsigned char*)mask); + case 0:; + } + NanReturnValue(True()); + } +}; + +extern "C" void init (Handle target) +{ + NanScope(); + BufferUtil::Initialize(target); +} + +NODE_MODULE(bufferutil, init) + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/validation.cc b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/validation.cc new file mode 100644 index 00000000..528eda1f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/validation.cc @@ -0,0 +1,145 @@ +/*! + * ws: a node.js websocket client + * Copyright(c) 2011 Einar Otto Stangvik + * MIT Licensed + */ + +#include +#include +#include +#include +#include +#include +#include +#include "nan.h" + +using namespace v8; +using namespace node; + +#define UNI_SUR_HIGH_START (uint32_t) 0xD800 +#define UNI_SUR_LOW_END (uint32_t) 0xDFFF +#define UNI_REPLACEMENT_CHAR (uint32_t) 0x0000FFFD +#define UNI_MAX_LEGAL_UTF32 (uint32_t) 0x0010FFFF + +static const uint8_t trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +static const uint32_t offsetsFromUTF8[6] = { + 0x00000000, 0x00003080, 0x000E2080, + 0x03C82080, 0xFA082080, 0x82082080 +}; + +static int isLegalUTF8(const uint8_t *source, const int length) +{ + uint8_t a; + const uint8_t *srcptr = source+length; + switch (length) { + default: return 0; + /* Everything else falls through when "true"... */ + /* RFC3629 makes 5 & 6 bytes UTF-8 illegal + case 6: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; + case 5: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; + case 2: if ((a = (*--srcptr)) > 0xBF) return 0; + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return 0; break; + case 0xED: if (a > 0x9F) return 0; break; + case 0xF0: if (a < 0x90) return 0; break; + case 0xF4: if (a > 0x8F) return 0; break; + default: if (a < 0x80) return 0; + } + + case 1: if (*source >= 0x80 && *source < 0xC2) return 0; + } + if (*source > 0xF4) return 0; + return 1; +} + +int is_valid_utf8 (size_t len, char *value) +{ + /* is the string valid UTF-8? */ + for (unsigned int i = 0; i < len; i++) { + uint32_t ch = 0; + uint8_t extrabytes = trailingBytesForUTF8[(uint8_t) value[i]]; + + if (extrabytes + i >= len) + return 0; + + if (isLegalUTF8 ((uint8_t *) (value + i), extrabytes + 1) == 0) return 0; + + switch (extrabytes) { + case 5 : ch += (uint8_t) value[i++]; ch <<= 6; + case 4 : ch += (uint8_t) value[i++]; ch <<= 6; + case 3 : ch += (uint8_t) value[i++]; ch <<= 6; + case 2 : ch += (uint8_t) value[i++]; ch <<= 6; + case 1 : ch += (uint8_t) value[i++]; ch <<= 6; + case 0 : ch += (uint8_t) value[i]; + } + + ch -= offsetsFromUTF8[extrabytes]; + + if (ch <= UNI_MAX_LEGAL_UTF32) { + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) + return 0; + } else { + return 0; + } + } + + return 1; +} + +class Validation : public ObjectWrap +{ +public: + + static void Initialize(v8::Handle target) + { + HandleScope scope; + Local t = FunctionTemplate::New(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + NODE_SET_METHOD(t, "isValidUTF8", Validation::IsValidUTF8); + target->Set(String::NewSymbol("Validation"), t->GetFunction()); + } + +protected: + + static NAN_METHOD(New) + { + NanScope(); + Validation* validation = new Validation(); + validation->Wrap(args.This()); + NanReturnValue(args.This()); + } + + static NAN_METHOD(IsValidUTF8) + { + NanScope(); + if (!Buffer::HasInstance(args[0])) { + return NanThrowTypeError("First argument needs to be a buffer"); + } + Local buffer_obj = args[0]->ToObject(); + char *buffer_data = Buffer::Data(buffer_obj); + size_t buffer_length = Buffer::Length(buffer_obj); + NanReturnValue(is_valid_utf8(buffer_length, buffer_data) == 1 ? True() : False()); + } +}; + +extern "C" void init (Handle target) +{ + NanScope(); + Validation::Initialize(target); +} + +NODE_MODULE(validation, init) + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/BufferPool.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/BufferPool.test.js new file mode 100644 index 00000000..1ee7ff0f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/BufferPool.test.js @@ -0,0 +1,63 @@ +var BufferPool = require('../lib/BufferPool'); +require('should'); + +describe('BufferPool', function() { + describe('#ctor', function() { + it('allocates pool', function() { + var db = new BufferPool(1000); + db.size.should.eql(1000); + }); + }); + describe('#get', function() { + it('grows the pool if necessary', function() { + var db = new BufferPool(1000); + var buf = db.get(2000); + db.size.should.be.above(1000); + db.used.should.eql(2000); + buf.length.should.eql(2000); + }); + it('grows the pool after the first call, if necessary', function() { + var db = new BufferPool(1000); + var buf = db.get(1000); + db.used.should.eql(1000); + db.size.should.eql(1000); + buf.length.should.eql(1000); + var buf2 = db.get(1000); + db.used.should.eql(2000); + db.size.should.be.above(1000); + buf2.length.should.eql(1000); + }); + it('grows the pool according to the growStrategy if necessary', function() { + var db = new BufferPool(1000, function(db, length) { + return db.size + 2345; + }); + var buf = db.get(2000); + db.size.should.eql(3345); + buf.length.should.eql(2000); + }); + it('doesnt grow the pool if theres enough room available', function() { + var db = new BufferPool(1000); + var buf = db.get(1000); + db.size.should.eql(1000); + buf.length.should.eql(1000); + }); + }); + describe('#reset', function() { + it('shinks the pool', function() { + var db = new BufferPool(1000); + var buf = db.get(2000); + db.reset(true); + db.size.should.eql(1000); + }); + it('shrinks the pool according to the shrinkStrategy', function() { + var db = new BufferPool(1000, function(db, length) { + return db.used + length; + }, function(db) { + return 0; + }); + var buf = db.get(2000); + db.reset(true); + db.size.should.eql(0); + }); + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.hixie.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.hixie.test.js new file mode 100644 index 00000000..043d3bc4 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.hixie.test.js @@ -0,0 +1,158 @@ +var assert = require('assert') + , expect = require('expect.js') + , Receiver = require('../lib/Receiver.hixie'); +require('./hybi-common'); + +describe('Receiver', function() { + it('can parse text message', function() { + var p = new Receiver(); + var packet = '00 48 65 6c 6c 6f ff'; + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal('Hello', data); + }; + + p.add(getBufferFromHexString(packet)); + expect(gotData).to.equal(true); + }); + + it('can parse multiple text messages', function() { + var p = new Receiver(); + var packet = '00 48 65 6c 6c 6f ff 00 48 65 6c 6c 6f ff'; + + var gotData = false; + var messages = []; + p.ontext = function(data) { + gotData = true; + messages.push(data); + }; + + p.add(getBufferFromHexString(packet)); + expect(gotData).to.equal(true); + for (var i = 0; i < 2; ++i) { + expect(messages[i]).to.equal('Hello'); + } + }); + + it('can parse empty message', function() { + var p = new Receiver(); + var packet = '00 ff'; + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal('', data); + }; + + p.add(getBufferFromHexString(packet)); + expect(gotData).to.equal(true); + }); + + it('can parse text messages delivered over multiple frames', function() { + var p = new Receiver(); + var packets = [ + '00 48', + '65 6c 6c', + '6f ff 00 48', + '65', + '6c 6c 6f', + 'ff' + ]; + + var gotData = false; + var messages = []; + p.ontext = function(data) { + gotData = true; + messages.push(data); + }; + + for (var i = 0; i < packets.length; ++i) { + p.add(getBufferFromHexString(packets[i])); + } + expect(gotData).to.equal(true); + for (var i = 0; i < 2; ++i) { + expect(messages[i]).to.equal('Hello'); + } + }); + + it('emits an error if a payload doesnt start with 0x00', function() { + var p = new Receiver(); + var packets = [ + '00 6c ff', + '00 6c ff ff', + 'ff 00 6c ff 00 6c ff', + '00', + '6c 6c 6f', + 'ff' + ]; + + var gotData = false; + var gotError = false; + var messages = []; + p.ontext = function(data) { + gotData = true; + messages.push(data); + }; + p.onerror = function(reason, code) { + gotError = code == true; + }; + + for (var i = 0; i < packets.length && !gotError; ++i) { + p.add(getBufferFromHexString(packets[i])); + } + expect(gotError).to.equal(true); + expect(messages[0]).to.equal('l'); + expect(messages[1]).to.equal('l'); + expect(messages.length).to.equal(2); + }); + + it('can parse close messages', function() { + var p = new Receiver(); + var packets = [ + 'ff 00' + ]; + + var gotClose = false; + var gotError = false; + p.onclose = function() { + gotClose = true; + }; + p.onerror = function(reason, code) { + gotError = code == true; + }; + + for (var i = 0; i < packets.length && !gotError; ++i) { + p.add(getBufferFromHexString(packets[i])); + } + expect(gotClose).to.equal(true); + expect(gotError).to.equal(false); + }); + + it('can parse binary messages delivered over multiple frames', function() { + var p = new Receiver(); + var packets = [ + '80 05 48', + '65 6c 6c', + '6f 80 80 05 48', + '65', + '6c 6c 6f' + ]; + + var gotData = false; + var messages = []; + p.ontext = function(data) { + gotData = true; + messages.push(data); + }; + + for (var i = 0; i < packets.length; ++i) { + p.add(getBufferFromHexString(packets[i])); + } + expect(gotData).to.equal(true); + for (var i = 0; i < 2; ++i) { + expect(messages[i]).to.equal('Hello'); + } + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.test.js new file mode 100644 index 00000000..b0b5c0a4 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.test.js @@ -0,0 +1,255 @@ +var assert = require('assert') + , Receiver = require('../lib/Receiver'); +require('should'); +require('./hybi-common'); + +describe('Receiver', function() { + it('can parse unmasked text message', function() { + var p = new Receiver(); + var packet = '81 05 48 65 6c 6c 6f'; + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal('Hello', data); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse close message', function() { + var p = new Receiver(); + var packet = '88 00'; + + var gotClose = false; + p.onclose = function(data) { + gotClose = true; + }; + + p.add(getBufferFromHexString(packet)); + gotClose.should.be.ok; + }); + it('can parse masked text message', function() { + var p = new Receiver(); + var packet = '81 93 34 83 a8 68 01 b9 92 52 4f a1 c6 09 59 e6 8a 52 16 e6 cb 00 5b a1 d5'; + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal('5:::{"name":"echo"}', data); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a masked text message longer than 125 bytes', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + var packet = '81 FE ' + pack(4, message.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a really long masked text message', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 64*1024; ++i) message += (i % 5).toString(); + var packet = '81 FF ' + pack(16, message.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a fragmented masked text message of 300 bytes', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + var msgpiece1 = message.substr(0, 150); + var msgpiece2 = message.substr(150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68')); + var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + + p.add(getBufferFromHexString(packet1)); + p.add(getBufferFromHexString(packet2)); + gotData.should.be.ok; + }); + it('can parse a ping message', function() { + var p = new Receiver(); + var message = 'Hello'; + var packet = '89 ' + getHybiLengthAsHexString(message.length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotPing = false; + p.onping = function(data) { + gotPing = true; + assert.equal(message, data); + }; + + p.add(getBufferFromHexString(packet)); + gotPing.should.be.ok; + }); + it('can parse a ping with no data', function() { + var p = new Receiver(); + var packet = '89 00'; + + var gotPing = false; + p.onping = function(data) { + gotPing = true; + }; + + p.add(getBufferFromHexString(packet)); + gotPing.should.be.ok; + }); + it('can parse a fragmented masked text message of 300 bytes with a ping in the middle', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + + var msgpiece1 = message.substr(0, 150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68')); + + var pingMessage = 'Hello'; + var pingPacket = '89 ' + getHybiLengthAsHexString(pingMessage.length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68')); + + var msgpiece2 = message.substr(150); + var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + var gotPing = false; + p.onping = function(data) { + gotPing = true; + assert.equal(pingMessage, data); + }; + + p.add(getBufferFromHexString(packet1)); + p.add(getBufferFromHexString(pingPacket)); + p.add(getBufferFromHexString(packet2)); + gotData.should.be.ok; + gotPing.should.be.ok; + }); + it('can parse a fragmented masked text message of 300 bytes with a ping in the middle, which is delievered over sevaral tcp packets', function() { + var p = new Receiver(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + + var msgpiece1 = message.substr(0, 150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece1, '34 83 a8 68')); + + var pingMessage = 'Hello'; + var pingPacket = '89 ' + getHybiLengthAsHexString(pingMessage.length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68')); + + var msgpiece2 = message.substr(150); + var packet2 = '80 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.ontext = function(data) { + gotData = true; + assert.equal(message, data); + }; + var gotPing = false; + p.onping = function(data) { + gotPing = true; + assert.equal(pingMessage, data); + }; + + var buffers = []; + buffers = buffers.concat(splitBuffer(getBufferFromHexString(packet1))); + buffers = buffers.concat(splitBuffer(getBufferFromHexString(pingPacket))); + buffers = buffers.concat(splitBuffer(getBufferFromHexString(packet2))); + for (var i = 0; i < buffers.length; ++i) { + p.add(buffers[i]); + } + gotData.should.be.ok; + gotPing.should.be.ok; + }); + it('can parse a 100 byte long masked binary message', function() { + var p = new Receiver(); + var length = 100; + var message = new Buffer(length); + for (var i = 0; i < length; ++i) message[i] = i % 256; + var originalMessage = getHexStringFromBuffer(message); + var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.onbinary = function(data) { + gotData = true; + assert.equal(originalMessage, getHexStringFromBuffer(data)); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a 256 byte long masked binary message', function() { + var p = new Receiver(); + var length = 256; + var message = new Buffer(length); + for (var i = 0; i < length; ++i) message[i] = i % 256; + var originalMessage = getHexStringFromBuffer(message); + var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.onbinary = function(data) { + gotData = true; + assert.equal(originalMessage, getHexStringFromBuffer(data)); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a 200kb long masked binary message', function() { + var p = new Receiver(); + var length = 200 * 1024; + var message = new Buffer(length); + for (var i = 0; i < length; ++i) message[i] = i % 256; + var originalMessage = getHexStringFromBuffer(message); + var packet = '82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' + getHexStringFromBuffer(mask(message, '34 83 a8 68')); + + var gotData = false; + p.onbinary = function(data) { + gotData = true; + assert.equal(originalMessage, getHexStringFromBuffer(data)); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); + it('can parse a 200kb long unmasked binary message', function() { + var p = new Receiver(); + var length = 200 * 1024; + var message = new Buffer(length); + for (var i = 0; i < length; ++i) message[i] = i % 256; + var originalMessage = getHexStringFromBuffer(message); + var packet = '82 ' + getHybiLengthAsHexString(length, false) + ' ' + getHexStringFromBuffer(message); + + var gotData = false; + p.onbinary = function(data) { + gotData = true; + assert.equal(originalMessage, getHexStringFromBuffer(data)); + }; + + p.add(getBufferFromHexString(packet)); + gotData.should.be.ok; + }); +}); + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.hixie.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.hixie.test.js new file mode 100644 index 00000000..783f8922 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.hixie.test.js @@ -0,0 +1,134 @@ +var assert = require('assert') + , Sender = require('../lib/Sender.hixie'); +require('should'); +require('./hybi-common'); + +describe('Sender', function() { + describe('#send', function() { + it('frames and sends a text message', function(done) { + var message = 'Hello world'; + var received; + var socket = { + write: function(data, encoding, cb) { + received = data; + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(message, {}, function() { + received.toString('utf8').should.eql('\u0000' + message + '\ufffd'); + done(); + }); + }); + + it('frames and sends an empty message', function(done) { + var socket = { + write: function(data, encoding, cb) { + done(); + } + }; + var sender = new Sender(socket, {}); + sender.send('', {}, function() {}); + }); + + it('frames and sends a buffer', function(done) { + var received; + var socket = { + write: function(data, encoding, cb) { + received = data; + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(new Buffer('foobar'), {}, function() { + received.toString('utf8').should.eql('\u0000foobar\ufffd'); + done(); + }); + }); + + it('frames and sends a binary message', function(done) { + var message = 'Hello world'; + var received; + var socket = { + write: function(data, encoding, cb) { + received = data; + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(message, {binary: true}, function() { + received.toString('hex').should.eql( + // 0x80 0x0b H e l l o w o r l d + '800b48656c6c6f20776f726c64'); + done(); + }); + }); +/* + it('throws an exception for binary data', function(done) { + var socket = { + write: function(data, encoding, cb) { + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.on('error', function() { + done(); + }); + sender.send(new Buffer(100), {binary: true}, function() {}); + }); +*/ + it('can fauxe stream data', function(done) { + var received = []; + var socket = { + write: function(data, encoding, cb) { + received.push(data); + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(new Buffer('foobar'), { fin: false }, function() {}); + sender.send('bazbar', { fin: false }, function() {}); + sender.send(new Buffer('end'), { fin: true }, function() { + received[0].toString('utf8').should.eql('\u0000foobar'); + received[1].toString('utf8').should.eql('bazbar'); + received[2].toString('utf8').should.eql('end\ufffd'); + done(); + }); + }); + }); + + describe('#close', function() { + it('sends a hixie close frame', function(done) { + var received; + var socket = { + write: function(data, encoding, cb) { + received = data; + process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.close(null, null, null, function() { + received.toString('utf8').should.eql('\ufffd\u0000'); + done(); + }); + }); + + it('sends a message end marker if fauxe streaming has started, before hixie close frame', function(done) { + var received = []; + var socket = { + write: function(data, encoding, cb) { + received.push(data); + if (cb) process.nextTick(cb); + } + }; + var sender = new Sender(socket, {}); + sender.send(new Buffer('foobar'), { fin: false }, function() {}); + sender.close(null, null, null, function() { + received[0].toString('utf8').should.eql('\u0000foobar'); + received[1].toString('utf8').should.eql('\ufffd'); + received[2].toString('utf8').should.eql('\ufffd\u0000'); + done(); + }); + }); + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.test.js new file mode 100644 index 00000000..43b4864d --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.test.js @@ -0,0 +1,24 @@ +var Sender = require('../lib/Sender'); +require('should'); + +describe('Sender', function() { + describe('#frameAndSend', function() { + it('does not modify a masked binary buffer', function() { + var sender = new Sender({ write: function() {} }); + var buf = new Buffer([1, 2, 3, 4, 5]); + sender.frameAndSend(2, buf, true, true); + buf[0].should.eql(1); + buf[1].should.eql(2); + buf[2].should.eql(3); + buf[3].should.eql(4); + buf[4].should.eql(5); + }); + + it('does not modify a masked text buffer', function() { + var sender = new Sender({ write: function() {} }); + var text = 'hi there'; + sender.frameAndSend(1, text, true, true); + text.should.eql('hi there'); + }); + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Validation.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Validation.test.js new file mode 100644 index 00000000..37c33993 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Validation.test.js @@ -0,0 +1,23 @@ +var Validation = require('../lib/Validation').Validation; +require('should'); + +describe('Validation', function() { + describe('isValidUTF8', function() { + it('should return true for a valid utf8 string', function() { + var validBuffer = new Buffer('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque gravida mattis rhoncus. Donec iaculis, metus quis varius accumsan, erat mauris condimentum diam, et egestas erat enim ut ligula. Praesent sollicitudin tellus eget dolor euismod euismod. Nullam ac augue nec neque varius luctus. Curabitur elit mi, consequat ultricies adipiscing mollis, scelerisque in erat. Phasellus facilisis fermentum ullamcorper. Nulla et sem eu arcu pharetra pellentesque. Praesent consectetur tempor justo, vel iaculis dui ullamcorper sit amet. Integer tristique viverra ullamcorper. Vivamus laoreet, nulla eget suscipit eleifend, lacus lectus feugiat libero, non fermentum erat nisi at risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut pulvinar dignissim tellus, eu dignissim lorem vulputate quis. Morbi ut pulvinar augue.'); + Validation.isValidUTF8(validBuffer).should.be.ok; + }); + it('should return false for an erroneous string', function() { + var invalidBuffer = new Buffer([0xce, 0xba, 0xe1, 0xbd, 0xb9, 0xcf, 0x83, 0xce, 0xbc, 0xce, 0xb5, 0xed, 0xa0, 0x80, 0x65, 0x64, 0x69, 0x74, 0x65, 0x64]); + Validation.isValidUTF8(invalidBuffer).should.not.be.ok; + }); + it('should return true for valid cases from the autobahn test suite', function() { + Validation.isValidUTF8(new Buffer('\xf0\x90\x80\x80')).should.be.ok; + Validation.isValidUTF8(new Buffer([0xf0, 0x90, 0x80, 0x80])).should.be.ok; + }); + it('should return false for erroneous autobahn strings', function() { + Validation.isValidUTF8(new Buffer([0xce, 0xba, 0xe1, 0xbd])).should.not.be.ok; + }); + }); +}); + diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.integration.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.integration.js new file mode 100644 index 00000000..5d4f426f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.integration.js @@ -0,0 +1,44 @@ +var assert = require('assert') + , WebSocket = require('../') + , server = require('./testserver'); + +var port = 20000; + +function getArrayBuffer(buf) { + var l = buf.length; + var arrayBuf = new ArrayBuffer(l); + var uint8View = new Uint8Array(arrayBuf); + + for (var i = 0; i < l; i++) { + uint8View[i] = buf[i]; + } + return uint8View.buffer; +} + +function areArraysEqual(x, y) { + if (x.length != y.length) return false; + for (var i = 0, l = x.length; i < l; ++i) { + if (x[i] !== y[i]) return false; + } + return true; +} + +describe('WebSocket', function() { + it('communicates successfully with echo service', function(done) { + var ws = new WebSocket('ws://echo.websocket.org/', {protocolVersion: 13, origin: 'http://websocket.org'}); + var str = Date.now().toString(); + var dataReceived = false; + ws.on('open', function() { + ws.send(str, {mask: true}); + }); + ws.on('close', function() { + assert.equal(true, dataReceived); + done(); + }); + ws.on('message', function(data, flags) { + assert.equal(str, data); + ws.terminate(); + dataReceived = true; + }); + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.test.js new file mode 100644 index 00000000..91336b93 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.test.js @@ -0,0 +1,1724 @@ +var assert = require('assert') + , https = require('https') + , http = require('http') + , should = require('should') + , WebSocket = require('../') + , WebSocketServer = require('../').Server + , fs = require('fs') + , server = require('./testserver') + , crypto = require('crypto'); + +var port = 20000; + +function getArrayBuffer(buf) { + var l = buf.length; + var arrayBuf = new ArrayBuffer(l); + var uint8View = new Uint8Array(arrayBuf); + for (var i = 0; i < l; i++) { + uint8View[i] = buf[i]; + } + return uint8View.buffer; +} + + +function areArraysEqual(x, y) { + if (x.length != y.length) return false; + for (var i = 0, l = x.length; i < l; ++i) { + if (x[i] !== y[i]) return false; + } + return true; +} + +describe('WebSocket', function() { + describe('#ctor', function() { + it('throws exception for invalid url', function(done) { + try { + var ws = new WebSocket('echo.websocket.org'); + } + catch (e) { + done(); + } + }); + }); + + describe('options', function() { + it('should accept an `agent` option', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var agent = { + addRequest: function() { + wss.close(); + done(); + } + }; + var ws = new WebSocket('ws://localhost:' + port, { agent: agent }); + }); + }); + // GH-227 + it('should accept the `options` object as the 3rd argument', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var agent = { + addRequest: function() { + wss.close(); + done(); + } + }; + var ws = new WebSocket('ws://localhost:' + port, [], { agent: agent }); + }); + }); + }); + + describe('properties', function() { + it('#bytesReceived exposes number of bytes received', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('message', function() { + ws.bytesReceived.should.eql(8); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + ws.send('foobar'); + }); + }); + + it('#url exposes the server url', function(done) { + server.createServer(++port, function(srv) { + var url = 'ws://localhost:' + port; + var ws = new WebSocket(url); + assert.equal(url, ws.url); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('#protocolVersion exposes the protocol version', function(done) { + server.createServer(++port, function(srv) { + var url = 'ws://localhost:' + port; + var ws = new WebSocket(url); + assert.equal(13, ws.protocolVersion); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + describe('#bufferedAmount', function() { + it('defaults to zero', function(done) { + server.createServer(++port, function(srv) { + var url = 'ws://localhost:' + port; + var ws = new WebSocket(url); + assert.equal(0, ws.bufferedAmount); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('defaults to zero upon "open"', function(done) { + server.createServer(++port, function(srv) { + var url = 'ws://localhost:' + port; + var ws = new WebSocket(url); + ws.onopen = function() { + assert.equal(0, ws.bufferedAmount); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }; + }); + }); + + it('stress kernel write buffer', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(ws) { + while (true) { + if (ws.bufferedAmount > 0) break; + ws.send((new Array(10000)).join('hello')); + } + ws.terminate(); + ws.on('close', function() { + wss.close(); + done(); + }); + }); + }); + }); + + describe('Custom headers', function() { + it('request has an authorization header', function (done) { + var auth = 'test:testpass'; + var srv = http.createServer(function (req, res) {}); + var wss = new WebSocketServer({server: srv}); + srv.listen(++port); + var ws = new WebSocket('ws://' + auth + '@localhost:' + port); + srv.on('upgrade', function (req, socket, head) { + assert(req.headers.authorization, 'auth header exists'); + assert.equal(req.headers.authorization, 'Basic ' + new Buffer(auth).toString('base64')); + ws.terminate(); + ws.on('close', function () { + srv.close(); + wss.close(); + done(); + }); + }); + }); + + it('accepts custom headers', function (done) { + var srv = http.createServer(function (req, res) {}); + var wss = new WebSocketServer({server: srv}); + srv.listen(++port); + + var ws = new WebSocket('ws://localhost:' + port, { + headers: { + 'Cookie': 'foo=bar' + } + }); + + srv.on('upgrade', function (req, socket, head) { + assert(req.headers.cookie, 'auth header exists'); + assert.equal(req.headers.cookie, 'foo=bar'); + + ws.terminate(); + ws.on('close', function () { + srv.close(); + wss.close(); + done(); + }); + }); + }); + }); + + describe('#readyState', function() { + it('defaults to connecting', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + assert.equal(WebSocket.CONNECTING, ws.readyState); + ws.terminate(); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('set to open once connection is established', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + assert.equal(WebSocket.OPEN, ws.readyState); + srv.close(); + done(); + }); + }); + }); + + it('set to closed once connection is closed', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.close(1001); + ws.on('close', function() { + assert.equal(WebSocket.CLOSED, ws.readyState); + srv.close(); + done(); + }); + }); + }); + + it('set to closed once connection is terminated', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.terminate(); + ws.on('close', function() { + assert.equal(WebSocket.CLOSED, ws.readyState); + srv.close(); + done(); + }); + }); + }); + }); + + /* + * Ready state constants + */ + + var readyStates = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 + }; + + /* + * Ready state constant tests + */ + + Object.keys(readyStates).forEach(function(state) { + describe('.' + state, function() { + it('is enumerable property of class', function() { + var propertyDescripter = Object.getOwnPropertyDescriptor(WebSocket, state) + assert.equal(readyStates[state], propertyDescripter.value); + assert.equal(true, propertyDescripter.enumerable); + }); + }); + }); + + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + Object.keys(readyStates).forEach(function(state) { + describe('.' + state, function() { + it('is property of instance', function() { + assert.equal(readyStates[state], ws[state]); + }); + }); + }); + }); + }); + + describe('events', function() { + it('emits a ping event', function(done) { + var wss = new WebSocketServer({port: ++port}); + wss.on('connection', function(client) { + client.ping(); + }); + var ws = new WebSocket('ws://localhost:' + port); + ws.on('ping', function() { + ws.terminate(); + wss.close(); + done(); + }); + }); + + it('emits a pong event', function(done) { + var wss = new WebSocketServer({port: ++port}); + wss.on('connection', function(client) { + client.pong(); + }); + var ws = new WebSocket('ws://localhost:' + port); + ws.on('pong', function() { + ws.terminate(); + wss.close(); + done(); + }); + }); + }); + + describe('connection establishing', function() { + it('can disconnect before connection is established', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.terminate(); + ws.on('open', function() { + assert.fail('connect shouldnt be raised here'); + }); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('can close before connection is established', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.close(1001); + ws.on('open', function() { + assert.fail('connect shouldnt be raised here'); + }); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('invalid server key is denied', function(done) { + server.createServer(++port, server.handlers.invalidKey, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() { + srv.close(); + done(); + }); + }); + }); + + it('close event is raised when server closes connection', function(done) { + server.createServer(++port, server.handlers.closeAfterConnect, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('close', function() { + srv.close(); + done(); + }); + }); + }); + + it('error is emitted if server aborts connection', function(done) { + server.createServer(++port, server.handlers.return401, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + assert.fail('connect shouldnt be raised here'); + }); + ws.on('error', function() { + srv.close(); + done(); + }); + }); + }); + }); + + describe('#pause and #resume', function() { + it('pauses the underlying stream', function(done) { + // this test is sort-of racecondition'y, since an unlikely slow connection + // to localhost can cause the test to succeed even when the stream pausing + // isn't working as intended. that is an extremely unlikely scenario, though + // and an acceptable risk for the test. + var client; + var serverClient; + var openCount = 0; + function onOpen() { + if (++openCount == 2) { + var paused = true; + serverClient.on('message', function() { + paused.should.not.be.ok; + wss.close(); + done(); + }); + serverClient.pause(); + setTimeout(function() { + paused = false; + serverClient.resume(); + }, 200); + client.send('foo'); + } + } + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + serverClient = ws; + serverClient.on('open', onOpen); + }); + wss.on('connection', function(ws) { + client = ws; + onOpen(); + }); + }); + }); + + describe('#ping', function() { + it('before connect should fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + try { + ws.ping(); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + + it('before connect can silently fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + ws.ping('', {}, true); + srv.close(); + ws.terminate(); + done(); + }); + }); + + it('without message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.ping(); + }); + srv.on('ping', function(message) { + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.ping('hi'); + }); + srv.on('ping', function(message) { + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.ping('hi', {mask: true}); + }); + srv.on('ping', function(message, flags) { + assert.ok(flags.masked); + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + describe('#pong', function() { + it('before connect should fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + try { + ws.pong(); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + + it('before connect can silently fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + ws.pong('', {}, true); + srv.close(); + ws.terminate(); + done(); + }); + }); + + it('without message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.pong(); + }); + srv.on('pong', function(message) { + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.pong('hi'); + }); + srv.on('pong', function(message) { + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.pong('hi', {mask: true}); + }); + srv.on('pong', function(message, flags) { + assert.ok(flags.masked); + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + describe('#send', function() { + it('very long binary data can be sent and received (with echoing server)', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5 * 1024 * 1024); + for (var i = 0; i < array.length; ++i) array[i] = i / 5; + ws.on('open', function() { + ws.send(array, {binary: true}); + }); + ws.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('can send and receive text data', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send('hi'); + }); + ws.on('message', function(message, flags) { + assert.equal('hi', message); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('send and receive binary data as an array', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(6); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + var partial = array.subarray(2, 5); + ws.on('open', function() { + ws.send(partial, {binary: true}); + }); + ws.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(partial, new Float32Array(getArrayBuffer(message)))); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('binary data can be sent and received as buffer', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var buf = new Buffer('foobar'); + ws.on('open', function() { + ws.send(buf, {binary: true}); + }); + ws.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(buf, message)); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('ArrayBuffer is auto-detected without binary flag', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.on('open', function() { + ws.send(array.buffer); + }); + ws.onmessage = function (event) { + assert.ok(event.type = 'Binary'); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(event.data)))); + ws.terminate(); + srv.close(); + done(); + }; + }); + }); + + it('Buffer is auto-detected without binary flag', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var buf = new Buffer('foobar'); + ws.on('open', function() { + ws.send(buf); + }); + ws.onmessage = function (event) { + assert.ok(event.type = 'Binary'); + assert.ok(areArraysEqual(event.data, buf)); + ws.terminate(); + srv.close(); + done(); + }; + }); + }); + + it('before connect should fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + try { + ws.send('hi'); + } + catch (e) { + ws.terminate(); + srv.close(); + done(); + } + }); + }); + + it('before connect should pass error through callback, if present', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + ws.send('hi', function(error) { + assert.ok(error instanceof Error); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('without data should be successful', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send(); + }); + srv.on('message', function(message, flags) { + assert.equal('', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('calls optional callback when flushed', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send('hi', function() { + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + it('with unencoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send('hi'); + }); + srv.on('message', function(message, flags) { + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.send('hi', {mask: true}); + }); + srv.on('message', function(message, flags) { + assert.ok(flags.masked); + assert.equal('hi', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with unencoded binary message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.on('open', function() { + ws.send(array, {binary: true}); + }); + srv.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded binary message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var array = new Float32Array(5); + for (var i = 0; i < array.length; ++i) array[i] = i / 2; + ws.on('open', function() { + ws.send(array, {mask: true, binary: true}); + }); + srv.on('message', function(message, flags) { + assert.ok(flags.binary); + assert.ok(flags.masked); + assert.ok(areArraysEqual(array, new Float32Array(getArrayBuffer(message)))); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with binary stream will send fragmented data', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var callbackFired = false; + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.bufferSize = 100; + ws.send(fileStream, {binary: true}, function(error) { + assert.equal(null, error); + callbackFired = true; + }); + }); + srv.on('message', function(data, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile'), data)); + ws.terminate(); + }); + ws.on('close', function() { + assert.ok(callbackFired); + srv.close(); + done(); + }); + }); + }); + + it('with text stream will send fragmented data', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var callbackFired = false; + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream, {binary: false}, function(error) { + assert.equal(null, error); + callbackFired = true; + }); + }); + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + ws.terminate(); + }); + ws.on('close', function() { + assert.ok(callbackFired); + srv.close(); + done(); + }); + }); + }); + + it('will cause intermittent send to be delayed in order', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + ws.send('foobar'); + ws.send('baz'); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + ++receivedIndex; + if (receivedIndex == 1) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + } + else if (receivedIndex == 2) { + assert.ok(!flags.binary); + assert.equal('foobar', data); + } + else { + assert.ok(!flags.binary); + assert.equal('baz', data); + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent stream to be delayed in order', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) send('foo'); + else send('bar', true); + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + ++receivedIndex; + if (receivedIndex == 1) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + } + else if (receivedIndex == 2) { + assert.ok(!flags.binary); + assert.equal('foobar', data); + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent ping to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + ws.ping('foobar'); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + srv.on('ping', function(data) { + assert.equal('foobar', data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent pong to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + ws.pong('foobar'); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + srv.on('pong', function(data) { + assert.equal('foobar', data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent close to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream); + ws.close(1000, 'foobar'); + }); + ws.on('close', function() { + srv.close(); + ws.terminate(); + done(); + }); + ws.on('error', function() { /* That's quite alright -- a send was attempted after close */ }); + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.ok(areArraysEqual(fs.readFileSync('test/fixtures/textfile', 'utf8'), data)); + }); + srv.on('close', function(code, data) { + assert.equal(1000, code); + assert.equal('foobar', data); + }); + }); + }); + }); + + describe('#stream', function() { + it('very long binary data can be streamed', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var buffer = new Buffer(10 * 1024); + for (var i = 0; i < buffer.length; ++i) buffer[i] = i % 0xff; + ws.on('open', function() { + var i = 0; + var blockSize = 800; + var bufLen = buffer.length; + ws.stream({binary: true}, function(error, send) { + assert.ok(!error); + var start = i * blockSize; + var toSend = Math.min(blockSize, bufLen - (i * blockSize)); + var end = start + toSend; + var isFinal = toSend < blockSize; + send(buffer.slice(start, end), isFinal); + i += 1; + }); + }); + srv.on('message', function(data, flags) { + assert.ok(flags.binary); + assert.ok(areArraysEqual(buffer, data)); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('before connect should pass error through callback', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('error', function() {}); + ws.stream(function(error) { + assert.ok(error instanceof Error); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('without callback should fail', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + try { + ws.stream(); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent send to be delayed in order', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) { + send(payload.substr(0, 5)); + ws.send('foobar'); + ws.send('baz'); + } + else { + send(payload.substr(5, 5), true); + } + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + ++receivedIndex; + if (receivedIndex == 1) { + assert.ok(!flags.binary); + assert.equal(payload, data); + } + else if (receivedIndex == 2) { + assert.ok(!flags.binary); + assert.equal('foobar', data); + } + else { + assert.ok(!flags.binary); + assert.equal('baz', data); + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent stream to be delayed in order', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) { + send(payload.substr(0, 5)); + var i2 = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i2 == 1) send('foo'); + else send('bar', true); + }); + ws.send('baz'); + } + else send(payload.substr(5, 5), true); + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + ++receivedIndex; + if (receivedIndex == 1) { + assert.ok(!flags.binary); + assert.equal(payload, data); + } + else if (receivedIndex == 2) { + assert.ok(!flags.binary); + assert.equal('foobar', data); + } + else if (receivedIndex == 3){ + assert.ok(!flags.binary); + assert.equal('baz', data); + setTimeout(function() { + srv.close(); + ws.terminate(); + done(); + }, 1000); + } + else throw new Error('more messages than we actually sent just arrived'); + }); + }); + }); + + it('will cause intermittent ping to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) { + send(payload.substr(0, 5)); + ws.ping('foobar'); + } + else { + send(payload.substr(5, 5), true); + } + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.equal(payload, data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + srv.on('ping', function(data) { + assert.equal('foobar', data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent pong to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + assert.ok(!error); + if (++i == 1) { + send(payload.substr(0, 5)); + ws.pong('foobar'); + } + else { + send(payload.substr(5, 5), true); + } + }); + }); + var receivedIndex = 0; + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.equal(payload, data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + srv.on('pong', function(data) { + assert.equal('foobar', data); + if (++receivedIndex == 2) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('will cause intermittent close to be delivered', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var payload = 'HelloWorld'; + var errorGiven = false; + ws.on('open', function() { + var i = 0; + ws.stream(function(error, send) { + if (++i == 1) { + send(payload.substr(0, 5)); + ws.close(1000, 'foobar'); + } + else if(i == 2) { + send(payload.substr(5, 5), true); + } + else if (i == 3) { + assert.ok(error); + errorGiven = true; + } + }); + }); + ws.on('close', function() { + assert.ok(errorGiven); + srv.close(); + ws.terminate(); + done(); + }); + srv.on('message', function(data, flags) { + assert.ok(!flags.binary); + assert.equal(payload, data); + }); + srv.on('close', function(code, data) { + assert.equal(1000, code); + assert.equal('foobar', data); + }); + }); + }); + }); + + describe('#close', function() { + it('will raise error callback, if any, if called during send stream', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var errorGiven = false; + ws.on('open', function() { + var fileStream = fs.createReadStream('test/fixtures/textfile'); + fileStream.setEncoding('utf8'); + fileStream.bufferSize = 100; + ws.send(fileStream, function(error) { + errorGiven = error != null; + }); + ws.close(1000, 'foobar'); + }); + ws.on('close', function() { + setTimeout(function() { + assert.ok(errorGiven); + srv.close(); + ws.terminate(); + done(); + }, 1000); + }); + }); + }); + + it('without invalid first argument throws exception', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + try { + ws.close('error'); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('without reserved error code 1004 throws exception', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + try { + ws.close(1004); + } + catch (e) { + srv.close(); + ws.terminate(); + done(); + } + }); + }); + }); + + it('without message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.close(1000); + }); + srv.on('close', function(code, message, flags) { + assert.equal('', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.close(1000, 'some reason'); + }); + srv.on('close', function(code, message, flags) { + assert.ok(flags.masked); + assert.equal('some reason', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('with encoded message is successfully transmitted to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('open', function() { + ws.close(1000, 'some reason', {mask: true}); + }); + srv.on('close', function(code, message, flags) { + assert.ok(flags.masked); + assert.equal('some reason', message); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + + it('ends connection to the server', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var connectedOnce = false; + ws.on('open', function() { + connectedOnce = true; + ws.close(1000, 'some reason', {mask: true}); + }); + ws.on('close', function() { + assert.ok(connectedOnce); + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + describe('W3C API emulation', function() { + it('should not throw errors when getting and setting', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var listener = function () {}; + + ws.onmessage = listener; + ws.onerror = listener; + ws.onclose = listener; + ws.onopen = listener; + + assert.ok(ws.onopen === listener); + assert.ok(ws.onmessage === listener); + assert.ok(ws.onclose === listener); + assert.ok(ws.onerror === listener); + + srv.close(); + ws.terminate(); + done(); + }); + }); + + it('should work the same as the EventEmitter api', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + var listener = function() {}; + var message = 0; + var close = 0; + var open = 0; + + ws.onmessage = function(messageEvent) { + assert.ok(!!messageEvent.data); + ++message; + ws.close(); + }; + + ws.onopen = function() { + ++open; + } + + ws.onclose = function() { + ++close; + } + + ws.on('open', function() { + ws.send('foo'); + }); + + ws.on('close', function() { + process.nextTick(function() { + assert.ok(message === 1); + assert.ok(open === 1); + assert.ok(close === 1); + + srv.close(); + ws.terminate(); + done(); + }); + }); + }); + }); + + it('should receive text data wrapped in a MessageEvent when using addEventListener', function(done) { + server.createServer(++port, function(srv) { + var ws = new WebSocket('ws://localhost:' + port); + ws.addEventListener('open', function() { + ws.send('hi'); + }); + ws.addEventListener('message', function(messageEvent) { + assert.equal('hi', messageEvent.data); + ws.terminate(); + srv.close(); + done(); + }); + }); + }); + + it('should receive valid CloseEvent when server closes with code 1000', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.addEventListener('close', function(closeEvent) { + assert.equal(true, closeEvent.wasClean); + assert.equal(1000, closeEvent.code); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('connection', function(client) { + client.close(1000); + }); + }); + + it('should receive valid CloseEvent when server closes with code 1001', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.addEventListener('close', function(closeEvent) { + assert.equal(false, closeEvent.wasClean); + assert.equal(1001, closeEvent.code); + assert.equal('some daft reason', closeEvent.reason); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('connection', function(client) { + client.close(1001, 'some daft reason'); + }); + }); + + it('should have target set on Events', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.addEventListener('open', function(openEvent) { + assert.equal(ws, openEvent.target); + }); + ws.addEventListener('message', function(messageEvent) { + assert.equal(ws, messageEvent.target); + wss.close(); + }); + ws.addEventListener('close', function(closeEvent) { + assert.equal(ws, closeEvent.target); + ws.emit('error', new Error('forced')); + }); + ws.addEventListener('error', function(errorEvent) { + assert.equal(errorEvent.message, 'forced'); + assert.equal(ws, errorEvent.target); + ws.terminate(); + done(); + }); + }); + wss.on('connection', function(client) { + client.send('hi') + }); + }); + }); + + describe('ssl', function() { + it('can connect to secure websocket server', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var wss = new WebSocketServer({server: app}); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port); + }); + wss.on('connection', function(ws) { + app.close(); + ws.terminate(); + wss.close(); + done(); + }); + }); + + it('can connect to secure websocket server with client side certificate', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem'), + ca: [fs.readFileSync('test/fixtures/ca1-cert.pem')], + requestCert: true + }; + var clientOptions = { + key: fs.readFileSync('test/fixtures/agent1-key.pem'), + cert: fs.readFileSync('test/fixtures/agent1-cert.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var success = false; + var wss = new WebSocketServer({ + server: app, + verifyClient: function(info) { + success = !!info.req.client.authorized; + return true; + } + }); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port, clientOptions); + }); + wss.on('connection', function(ws) { + app.close(); + ws.terminate(); + wss.close(); + success.should.be.ok; + done(); + }); + }); + + it('cannot connect to secure websocket server via ws://', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var wss = new WebSocketServer({server: app}); + app.listen(++port, function() { + var ws = new WebSocket('ws://localhost:' + port, { rejectUnauthorized :false }); + ws.on('error', function() { + app.close(); + ws.terminate(); + wss.close(); + done(); + }); + }); + }); + + it('can send and receive text data', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var wss = new WebSocketServer({server: app}); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port); + ws.on('open', function() { + ws.send('foobar'); + }); + }); + wss.on('connection', function(ws) { + ws.on('message', function(message, flags) { + message.should.eql('foobar'); + app.close(); + ws.terminate(); + wss.close(); + done(); + }); + }); + }); + + it('can send and receive very long binary data', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + } + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + crypto.randomBytes(5 * 1024 * 1024, function(ex, buf) { + if (ex) throw ex; + var wss = new WebSocketServer({server: app}); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port); + ws.on('open', function() { + ws.send(buf, {binary: true}); + }); + ws.on('message', function(message, flags) { + flags.binary.should.be.ok; + areArraysEqual(buf, message).should.be.ok; + app.close(); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + ws.on('message', function(message, flags) { + ws.send(message, {binary: true}); + }); + }); + }); + }); + }); + + describe('protocol support discovery', function() { + describe('#supports', function() { + describe('#binary', function() { + it('returns true for hybi transport', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + assert.equal(true, client.supports.binary); + wss.close(); + done(); + }); + }); + + it('returns false for hixie transport', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + }); + wss.on('connection', function(client) { + assert.equal(false, client.supports.binary); + wss.close(); + done(); + }); + }); + }); + }); + }); + + describe('host and origin headers', function() { + it('includes the host header with port number', function(done) { + var srv = http.createServer(); + srv.listen(++port, function(){ + srv.on('upgrade', function(req, socket, upgradeHeade) { + assert.equal('localhost:' + port, req.headers['host']); + srv.close(); + done(); + }); + var ws = new WebSocket('ws://localhost:' + port); + }); + }); + + it('includes the origin header with port number', function(done) { + var srv = http.createServer(); + srv.listen(++port, function() { + srv.on('upgrade', function(req, socket, upgradeHeade) { + assert.equal('localhost:' + port, req.headers['origin']); + srv.close(); + done(); + }); + var ws = new WebSocket('ws://localhost:' + port); + }); + }); + }); + +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocketServer.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocketServer.test.js new file mode 100644 index 00000000..c21fd97f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocketServer.test.js @@ -0,0 +1,1103 @@ +var http = require('http') + , https = require('https') + , WebSocket = require('../') + , WebSocketServer = WebSocket.Server + , fs = require('fs') + , should = require('should'); + +var port = 8000; + +function getArrayBuffer(buf) { + var l = buf.length; + var arrayBuf = new ArrayBuffer(l); + for (var i = 0; i < l; ++i) { + arrayBuf[i] = buf[i]; + } + return arrayBuf; +} + +function areArraysEqual(x, y) { + if (x.length != y.length) return false; + for (var i = 0, l = x.length; i < l; ++i) { + if (x[i] !== y[i]) return false; + } + return true; +} + +describe('WebSocketServer', function() { + describe('#ctor', function() { + it('throws an error if no option object is passed', function() { + var gotException = false; + try { + var wss = new WebSocketServer(); + } + catch (e) { + gotException = true; + } + gotException.should.be.ok; + }); + + it('throws an error if no port or server is specified', function() { + var gotException = false; + try { + var wss = new WebSocketServer({}); + } + catch (e) { + gotException = true; + } + gotException.should.be.ok; + }); + + it('does not throw an error if no port or server is specified, when the noServer option is true', function() { + var gotException = false; + try { + var wss = new WebSocketServer({noServer: true}); + } + catch (e) { + gotException = true; + } + gotException.should.eql(false); + }); + + it('emits an error if http server bind fails', function(done) { + var wss = new WebSocketServer({port: 1}); + wss.on('error', function() { done(); }); + }); + + it('starts a server on a given port', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + wss.close(); + done(); + }); + }); + + it('uses a precreated http server', function (done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss = new WebSocketServer({server: srv}); + var ws = new WebSocket('ws://localhost:' + port); + + wss.on('connection', function(client) { + wss.close(); + srv.close(); + done(); + }); + }); + }); + + it('uses a precreated http server listening on unix socket', function (done) { + var srv = http.createServer(); + var sockPath = '/tmp/ws_socket_'+new Date().getTime()+'.'+Math.floor(Math.random() * 1000); + srv.listen(sockPath, function () { + var wss = new WebSocketServer({server: srv}); + var ws = new WebSocket('ws+unix://'+sockPath); + + wss.on('connection', function(client) { + wss.close(); + srv.close(); + done(); + }); + }); + }); + + it('emits path specific connection event', function (done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss = new WebSocketServer({server: srv}); + var ws = new WebSocket('ws://localhost:' + port+'/endpointName'); + + wss.on('connection/endpointName', function(client) { + wss.close(); + srv.close(); + done(); + }); + }); + }); + + it('can have two different instances listening on the same http server with two different paths', function(done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss1 = new WebSocketServer({server: srv, path: '/wss1'}) + , wss2 = new WebSocketServer({server: srv, path: '/wss2'}); + var doneCount = 0; + wss1.on('connection', function(client) { + wss1.close(); + if (++doneCount == 2) { + srv.close(); + done(); + } + }); + wss2.on('connection', function(client) { + wss2.close(); + if (++doneCount == 2) { + srv.close(); + done(); + } + }); + var ws1 = new WebSocket('ws://localhost:' + port + '/wss1'); + var ws2 = new WebSocket('ws://localhost:' + port + '/wss2?foo=1'); + }); + }); + + it('cannot have two different instances listening on the same http server with the same path', function(done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss1 = new WebSocketServer({server: srv, path: '/wss1'}); + try { + var wss2 = new WebSocketServer({server: srv, path: '/wss1'}); + } + catch (e) { + wss1.close(); + srv.close(); + done(); + } + }); + }); + }); + + describe('#close', function() { + it('will close all clients', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('close', function() { + if (++closes == 2) done(); + }); + }); + var closes = 0; + wss.on('connection', function(client) { + client.on('close', function() { + if (++closes == 2) done(); + }); + wss.close(); + }); + }); + + it('does not close a precreated server', function(done) { + var srv = http.createServer(); + var realClose = srv.close; + srv.close = function() { + should.fail('must not close pre-created server'); + } + srv.listen(++port, function () { + var wss = new WebSocketServer({server: srv}); + var ws = new WebSocket('ws://localhost:' + port); + wss.on('connection', function(client) { + wss.close(); + srv.close = realClose; + srv.close(); + done(); + }); + }); + }); + + it('cleans up websocket data on a precreated server', function(done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss1 = new WebSocketServer({server: srv, path: '/wss1'}) + , wss2 = new WebSocketServer({server: srv, path: '/wss2'}); + (typeof srv._webSocketPaths).should.eql('object'); + Object.keys(srv._webSocketPaths).length.should.eql(2); + wss1.close(); + Object.keys(srv._webSocketPaths).length.should.eql(1); + wss2.close(); + (typeof srv._webSocketPaths).should.eql('undefined'); + srv.close(); + done(); + }); + }); + }); + + describe('#clients', function() { + it('returns a list of connected clients', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + wss.clients.length.should.eql(0); + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + wss.clients.length.should.eql(1); + wss.close(); + done(); + }); + }); + + it('can be disabled', function(done) { + var wss = new WebSocketServer({port: ++port, clientTracking: false}, function() { + wss.clients.length.should.eql(0); + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + wss.clients.length.should.eql(0); + wss.close(); + done(); + }); + }); + + it('is updated when client terminates the connection', function(done) { + var ws; + var wss = new WebSocketServer({port: ++port}, function() { + ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + client.on('close', function() { + wss.clients.length.should.eql(0); + wss.close(); + done(); + }); + ws.terminate(); + }); + }); + + it('is updated when client closes the connection', function(done) { + var ws; + var wss = new WebSocketServer({port: ++port}, function() { + ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(client) { + client.on('close', function() { + wss.clients.length.should.eql(0); + wss.close(); + done(); + }); + ws.close(); + }); + }); + }); + + describe('#options', function() { + it('exposes options passed to constructor', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + wss.options.port.should.eql(port); + wss.close(); + done(); + }); + }); + }); + + describe('#handleUpgrade', function() { + it('can be used for a pre-existing server', function (done) { + var srv = http.createServer(); + srv.listen(++port, function () { + var wss = new WebSocketServer({noServer: true}); + srv.on('upgrade', function(req, socket, upgradeHead) { + wss.handleUpgrade(req, socket, upgradeHead, function(client) { + client.send('hello'); + }); + }); + var ws = new WebSocket('ws://localhost:' + port); + ws.on('message', function(message) { + message.should.eql('hello'); + wss.close(); + srv.close(); + done(); + }); + }); + }); + }); + + describe('hybi mode', function() { + describe('connection establishing', function() { + it('does not accept connections with no sec-websocket-key', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('does not accept connections with no sec-websocket-version', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('does not accept connections with invalid sec-websocket-version', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 12 + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be denied', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 8, + 'Sec-WebSocket-Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be accepted', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return true; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.end(); + }); + wss.on('connection', function(ws) { + ws.terminate(); + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('verifyClient gets client origin', function(done) { + var verifyClientCalled = false; + var wss = new WebSocketServer({port: ++port, verifyClient: function(info) { + info.origin.should.eql('http://foobarbaz.com'); + verifyClientCalled = true; + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobarbaz.com' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + verifyClientCalled.should.be.ok; + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('verifyClient gets original request', function(done) { + var verifyClientCalled = false; + var wss = new WebSocketServer({port: ++port, verifyClient: function(info) { + info.req.headers['sec-websocket-key'].should.eql('dGhlIHNhbXBsZSBub25jZQ=='); + verifyClientCalled = true; + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobarbaz.com' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + verifyClientCalled.should.be.ok; + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('verifyClient has secure:true for ssl connections', function(done) { + var options = { + key: fs.readFileSync('test/fixtures/key.pem'), + cert: fs.readFileSync('test/fixtures/certificate.pem') + }; + var app = https.createServer(options, function (req, res) { + res.writeHead(200); + res.end(); + }); + var success = false; + var wss = new WebSocketServer({ + server: app, + verifyClient: function(info) { + success = info.secure === true; + return true; + } + }); + app.listen(++port, function() { + var ws = new WebSocket('wss://localhost:' + port); + }); + wss.on('connection', function(ws) { + app.close(); + ws.terminate(); + wss.close(); + success.should.be.ok; + done(); + }); + }); + + it('verifyClient has secure:false for non-ssl connections', function(done) { + var app = http.createServer(function (req, res) { + res.writeHead(200); + res.end(); + }); + var success = false; + var wss = new WebSocketServer({ + server: app, + verifyClient: function(info) { + success = info.secure === false; + return true; + } + }); + app.listen(++port, function() { + var ws = new WebSocket('ws://localhost:' + port); + }); + wss.on('connection', function(ws) { + app.close(); + ws.terminate(); + wss.close(); + success.should.be.ok; + done(); + }); + }); + + it('client can be denied asynchronously', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) { + process.nextTick(function() { + cb(false); + }); + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 8, + 'Sec-WebSocket-Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be accepted asynchronously', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) { + process.nextTick(function() { + cb(true); + }); + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.end(); + }); + wss.on('connection', function(ws) { + ws.terminate(); + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('handles messages passed along with the upgrade request (upgrade head)', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return true; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.write(new Buffer([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f], 'binary')); + req.end(); + }); + wss.on('connection', function(ws) { + ws.on('message', function(data) { + data.should.eql('Hello'); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('selects the first protocol by default', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + ws.protocol.should.eql('prot1'); + wss.close(); + done(); + }); + }); + }); + + it('selects the last protocol via protocol handler', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + cb(true, ps[ps.length-1]); }}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + ws.protocol.should.eql('prot2'); + wss.close(); + done(); + }); + }); + }); + + it('client detects invalid server protocol', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + cb(true, 'prot3'); }}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + done(new Error('connection must not be established')); + }); + ws.on('error', function() { + done(); + }); + }); + }); + + it('client detects no server protocol', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + cb(true); }}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + done(new Error('connection must not be established')); + }); + ws.on('error', function() { + done(); + }); + }); + }); + + it('client refuses server protocols', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + cb(false); }}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'}); + ws.on('open', function(client) { + done(new Error('connection must not be established')); + }); + ws.on('error', function() { + done(); + }); + }); + }); + + it('server detects invalid protocol handler', function(done) { + var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) { + // not calling callback is an error and shouldn't timeout + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', + 'Sec-WebSocket-Version': 13, + 'Sec-WebSocket-Origin': 'http://foobar.com' + } + }; + options.port = port; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(501); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + }); + + describe('messaging', function() { + it('can send and receive data', function(done) { + var data = new Array(65*1024); + for (var i = 0; i < data.length; ++i) { + data[i] = String.fromCharCode(65 + ~~(25 * Math.random())); + } + data = data.join(''); + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port); + ws.on('message', function(message, flags) { + ws.send(message); + }); + }); + wss.on('connection', function(client) { + client.on('message', function(message) { + message.should.eql(data); + wss.close(); + done(); + }); + client.send(data); + }); + }); + }); + }); + + describe('hixie mode', function() { + it('can be disabled', function(done) { + var wss = new WebSocketServer({port: ++port, disableHixie: true}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + describe('connection establishing', function() { + it('does not accept connections with no sec-websocket-key1', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('does not accept connections with no sec-websocket-key2', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(400); + wss.close(); + done(); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('accepts connections with valid handshake', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + }); + wss.on('connection', function(ws) { + ws.terminate(); + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('client can be denied', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be accepted', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return true; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + }); + wss.on('connection', function(ws) { + ws.terminate(); + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('verifyClient gets client origin', function(done) { + var verifyClientCalled = false; + var wss = new WebSocketServer({port: ++port, verifyClient: function(info) { + info.origin.should.eql('http://foobarbaz.com'); + verifyClientCalled = true; + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Origin': 'http://foobarbaz.com', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + verifyClientCalled.should.be.ok; + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('verifyClient gets original request', function(done) { + var verifyClientCalled = false; + var wss = new WebSocketServer({port: ++port, verifyClient: function(info) { + info.req.headers['sec-websocket-key1'].should.eql('3e6b263 4 17 80'); + verifyClientCalled = true; + return false; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Origin': 'http://foobarbaz.com', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + verifyClientCalled.should.be.ok; + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + + it('client can be denied asynchronously', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) { + cb(false); + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Origin': 'http://foobarbaz.com', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + req.on('response', function(res) { + res.statusCode.should.eql(401); + process.nextTick(function() { + wss.close(); + done(); + }); + }); + }); + wss.on('connection', function(ws) { + done(new Error('connection must not be established')); + }); + wss.on('error', function() {}); + }); + + it('client can be accepted asynchronously', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) { + cb(true); + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Origin': 'http://foobarbaz.com', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.end(); + }); + wss.on('connection', function(ws) { + wss.close(); + done(); + }); + wss.on('error', function() {}); + }); + + it('handles messages passed along with the upgrade request (upgrade head)', function(done) { + var wss = new WebSocketServer({port: ++port, verifyClient: function(o) { + return true; + }}, function() { + var options = { + port: port, + host: '127.0.0.1', + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'WebSocket', + 'Sec-WebSocket-Key1': '3e6b263 4 17 80', + 'Sec-WebSocket-Key2': '17 9 G`ZD9 2 2b 7X 3 /r90', + 'Origin': 'http://foobar.com' + } + }; + var req = http.request(options); + req.write('WjN}|M(6'); + req.write(new Buffer([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], 'binary')); + req.end(); + }); + wss.on('connection', function(ws) { + ws.on('message', function(data) { + data.should.eql('Hello'); + ws.terminate(); + wss.close(); + done(); + }); + }); + wss.on('error', function() {}); + }); + }); + }); + + describe('client properties', function() { + it('protocol is exposed', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocol: 'hi'}); + }); + wss.on('connection', function(client) { + client.protocol.should.eql('hi'); + wss.close(); + done(); + }); + }); + + it('protocolVersion is exposed', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocolVersion: 8}); + }); + wss.on('connection', function(client) { + client.protocolVersion.should.eql(8); + wss.close(); + done(); + }); + }); + + it('upgradeReq is the original request object', function(done) { + var wss = new WebSocketServer({port: ++port}, function() { + var ws = new WebSocket('ws://localhost:' + port, {protocolVersion: 8}); + }); + wss.on('connection', function(client) { + client.upgradeReq.httpVersion.should.eql('1.1'); + wss.close(); + done(); + }); + }); + }); + +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn-server.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn-server.js new file mode 100644 index 00000000..36fe0c24 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn-server.js @@ -0,0 +1,29 @@ +var WebSocketServer = require('../').Server; + +process.on('uncaughtException', function(err) { + console.log('Caught exception: ', err, err.stack); +}); + +process.on('SIGINT', function () { + try { + console.log('Updating reports and shutting down'); + var ws = new WebSocket('ws://localhost:9001/updateReports?agent=ws'); + ws.on('close', function() { + process.exit(); + }); + } + catch(e) { + process.exit(); + } +}); + +var wss = new WebSocketServer({port: 8181}); +wss.on('connection', function(ws) { + console.log('new connection'); + ws.on('message', function(data, flags) { + ws.send(flags.buffer, {binary: flags.binary === true}); + }); + ws.on('error', function() { + console.log('error', arguments); + }); +}); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn.js new file mode 100644 index 00000000..048cc904 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn.js @@ -0,0 +1,52 @@ +var WebSocket = require('../'); +var currentTest = 1; +var lastTest = -1; +var testCount = null; + +process.on('uncaughtException', function(err) { + console.log('Caught exception: ', err, err.stack); +}); + +process.on('SIGINT', function () { + try { + console.log('Updating reports and shutting down'); + var ws = new WebSocket('ws://localhost:9001/updateReports?agent=ws'); + ws.on('close', function() { + process.exit(); + }); + } + catch(e) { + process.exit(); + } +}); + +function nextTest() { + if (currentTest > testCount || (lastTest != -1 && currentTest > lastTest)) { + console.log('Updating reports and shutting down'); + var ws = new WebSocket('ws://localhost:9001/updateReports?agent=ws'); + ws.on('close', function() { + process.exit(); + }); + return; + }; + console.log('Running test case ' + currentTest + '/' + testCount); + var ws = new WebSocket('ws://localhost:9001/runCase?case=' + currentTest + '&agent=ws'); + ws.on('message', function(data, flags) { + ws.send(flags.buffer, {binary: flags.binary === true, mask: true}); + }); + ws.on('close', function(data) { + currentTest += 1; + process.nextTick(nextTest); + }); + ws.on('error', function(e) {}); +} + +var ws = new WebSocket('ws://localhost:9001/getCaseCount'); +ws.on('message', function(data, flags) { + testCount = parseInt(data); +}); +ws.on('close', function() { + if (testCount > 0) { + nextTest(); + } +}); \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-cert.pem b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-cert.pem new file mode 100644 index 00000000..cccb9fb4 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-cert.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICbjCCAdcCCQCVvok5oeLpqzANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJV +UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAO +BgNVBAsTB05vZGUuanMxDDAKBgNVBAMTA2NhMTEgMB4GCSqGSIb3DQEJARYRcnlA +dGlueWNsb3Vkcy5vcmcwHhcNMTMwMzA4MDAzMDIyWhcNNDAwNzIzMDAzMDIyWjB9 +MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQK +EwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MTEgMB4G +CSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAL6GwKosYb0Yc3Qo0OtQVlCJ4208Idw11ij+t2W5sfYbCil5tyQo +jnhGM1CJhEXynQpXXwjKJuIeTQCkeUibTyFKa0bs8+li2FiGoKYbb4G81ovnqkmE +2iDVb8Gw3rrM4zeZ0ZdFnjMsAZac8h6+C4sB/pS9BiMOo6qTl15RQlcJAgMBAAEw +DQYJKoZIhvcNAQEFBQADgYEAOtmLo8DwTPnI4wfQbQ3hWlTS/9itww6IsxH2ODt9 +ggB7wi7N3uAdIWRZ54ke0NEAO5CW1xNTwsWcxQbiHrDOqX1vfVCjIenI76jVEEap +/Ay53ydHNBKdsKkib61Me14Mu0bA3lUul57VXwmH4NUEFB3w973Q60PschUhOEXj +7DY= +-----END CERTIFICATE----- diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-key.pem b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-key.pem new file mode 100644 index 00000000..cbd5f0c2 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC+hsCqLGG9GHN0KNDrUFZQieNtPCHcNdYo/rdlubH2Gwopebck +KI54RjNQiYRF8p0KV18IyibiHk0ApHlIm08hSmtG7PPpYthYhqCmG2+BvNaL56pJ +hNog1W/BsN66zOM3mdGXRZ4zLAGWnPIevguLAf6UvQYjDqOqk5deUUJXCQIDAQAB +AoGANu/CBA+SCyVOvRK70u4yRTzNMAUjukxnuSBhH1rg/pajYnwvG6T6F6IeT72n +P0gKkh3JUE6B0bds+p9yPUZTFUXghxjcF33wlIY44H6gFE4K5WutsFJ9c450wtuu +8rXZTsIg7lAXWjTFVmdtOEPetcGlO2Hpi1O7ZzkzHgB2w9ECQQDksCCYx78or1zY +ZSokm8jmpIjG3VLKdvI9HAoJRN40ldnwFoigrFa1AHwsFtWNe8bKyVRPDoLDUjpB +dkPWgweVAkEA1UfgqguQ2KIkbtp9nDBionu3QaajksrRHwIa8vdfRfLxszfHk2fh +NGY3dkRZF8HUAbzYLrd9poVhCBAEjWekpQJASOM6AHfpnXYHCZF01SYx6hEW5wsz +kARJQODm8f1ZNTlttO/5q/xBxn7ZFNRSTD3fJlL05B2j380ddC/Vf1FT4QJAP1BC +GliqnBSuGhZUWYxni3KMeTm9rzL0F29pjpzutHYlWB2D6ndY/FQnvL0XcZ0Bka58 +womIDGnl3x3aLBwLXQJBAJv6h5CHbXHx7VyDJAcNfppAqZGcEaiVg8yf2F33iWy2 +FLthhJucx7df7SO2aw5h06bRDRAhb9br0R9/3mLr7RE= +-----END RSA PRIVATE KEY----- diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-cert.pem b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-cert.pem new file mode 100644 index 00000000..1d0c0d68 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICazCCAdQCCQC9/g69HtxXRzANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJV +UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAO +BgNVBAsTB05vZGUuanMxDDAKBgNVBAMTA2NhMTEgMB4GCSqGSIb3DQEJARYRcnlA +dGlueWNsb3Vkcy5vcmcwHhcNMTMwMzA4MDAzMDIyWhcNNDAwNzIzMDAzMDIyWjB6 +MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQK +EwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDDAKBgNVBAMTA2NhMTEgMB4GCSqG +SIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBAKxr1mARUcv7zaqx5y4AxJPK6c1jdbSg7StcL4vg8klaPAlfNO6o+/Cl +w5CdQD3ukaVUwUOJ4T/+b3Xf7785XcWBC33GdjVQkfbHATJYcka7j7JDw3qev5Jk +1rAbRw48hF6rYlSGcx1mccAjoLoa3I8jgxCNAYHIjUQXgdmU893rAgMBAAEwDQYJ +KoZIhvcNAQEFBQADgYEAis05yxjCtJRuv8uX/DK6TX/j9C9Lzp1rKDNFTaTZ0iRw +KCw1EcNx4OXSj9gNblW4PWxpDvygrt1AmH9h2cb8K859NSHa9JOBFw6MA5C2A4Sj +NQfNATqUl4T6cdORlcDEZwHtT8b6D4A6Er31G/eJF4Sen0TUFpjdjd+l9RBjHlo= +-----END CERTIFICATE----- diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-key.pem b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-key.pem new file mode 100644 index 00000000..df149508 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-key.pem @@ -0,0 +1,17 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIFeWxJE1BrRECAggA +MBQGCCqGSIb3DQMHBAgu9PlMSQ+BOASCAoDEZN2tX0xWo/N+Jg+PrvCrFDk3P+3x +5xG/PEDjtMCAWPBEwbnaYHDzYmhNcAmxzGqEHGMDiWYs46LbO560VS3uMvFbEWPo +KYYVb13vkxl2poXdonCb5cHZA5GUYzTIVVJFptl4LHwBczHoMHtA4FqAhKlYvlWw +EOrdLB8XcwMmGPFabbbGxno0+EWWM27uNjlogfoxj35mQqSW4rOlhZ460XjOB1Zx +LjXMuZeONojkGYQRG5EUMchBoctQpCOM6cAi9r1B9BvtFCBpDV1c1zEZBzTEUd8o +kLn6tjLmY+QpTdylFjEWc7U3ppLY/pkoTBv4r85a2sEMWqkhSJboLaTboWzDJcU3 +Ke61pMpovt/3yCUd3TKgwduVwwQtDVTlBe0p66aN9QVj3CrFy/bKAGO3vxlli24H +aIjZf+OVoBY21ESlW3jLvNlBf7Ezf///2E7j4SCDLyZSFMTpFoAG/jDRyvi+wTKX +Kh485Bptnip6DCSuoH4u2SkOqwz3gJS/6s02YKe4m311QT4Pzne5/FwOFaS/HhQg +Xvyh2/d00OgJ0Y0PYQsHILPRgTUCKUXvj1O58opn3fxSacsPxIXwj6Z4FYAjUTaV +2B85k1lpant/JJEilDqMjqzx4pHZ/Z3Uto1lSM1JZs9SNL/0UR+6F0TXZTULVU9V +w8jYzz4sPr7LEyrrTbzmjQgnQFVbhAN/eKgRZK/SpLjxpmBV5MfpbPKsPUZqT4UC +4nXa8a/NYUQ9e+QKK8enq9E599c2W442W7Z1uFRZTWReMx/lF8wwA6G8zOPG0bdj +d+T5Gegzd5mvRiXMBklCo8RLxOOvgxun1n3PY4a63aH6mqBhdfhiLp5j +-----END ENCRYPTED PRIVATE KEY----- diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/certificate.pem b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/certificate.pem new file mode 100644 index 00000000..0efc2ef5 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/certificate.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQDPufXH86n2QzANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJu +bzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTEyMDEwMTE0NDQwMFoXDTIwMDMxOTE0NDQwMFowRTELMAkG +A1UEBhMCbm8xEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrQ7 ++r//2iV/B6F+4boH0XqFn7alcV9lpjvAmwRXNKnxAoa0f97AjYPGNLKrjpkNXXhB +JROIdbRbZnCNeC5fzX1a+JCo7KStzBXuGSZr27TtFmcV4H+9gIRIcNHtZmJLnxbJ +sIhkGR8yVYdmJZe4eT5ldk1zoB1adgPF1hZhCBMCAwEAATANBgkqhkiG9w0BAQUF +AAOBgQCeWBEHYJ4mCB5McwSSUox0T+/mJ4W48L/ZUE4LtRhHasU9hiW92xZkTa7E +QLcoJKQiWfiLX2ysAro0NX4+V8iqLziMqvswnPzz5nezaOLE/9U/QvH3l8qqNkXu +rNbsW1h/IO6FV8avWFYVFoutUwOaZ809k7iMh2F2JMgXQ5EymQ== +-----END CERTIFICATE----- diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/key.pem b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/key.pem new file mode 100644 index 00000000..176fe320 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC2tDv6v//aJX8HoX7hugfReoWftqVxX2WmO8CbBFc0qfEChrR/ +3sCNg8Y0squOmQ1deEElE4h1tFtmcI14Ll/NfVr4kKjspK3MFe4ZJmvbtO0WZxXg +f72AhEhw0e1mYkufFsmwiGQZHzJVh2Yll7h5PmV2TXOgHVp2A8XWFmEIEwIDAQAB +AoGAAlVY8sHi/aE+9xT77twWX3mGHV0SzdjfDnly40fx6S1Gc7bOtVdd9DC7pk6l +3ENeJVR02IlgU8iC5lMHq4JEHPE272jtPrLlrpWLTGmHEqoVFv9AITPqUDLhB9Kk +Hjl7h8NYBKbr2JHKICr3DIPKOT+RnXVb1PD4EORbJ3ooYmkCQQDfknUnVxPgxUGs +ouABw1WJIOVgcCY/IFt4Ihf6VWTsxBgzTJKxn3HtgvE0oqTH7V480XoH0QxHhjLq +DrgobWU9AkEA0TRJ8/ouXGnFEPAXjWr9GdPQRZ1Use2MrFjneH2+Sxc0CmYtwwqL +Kr5kS6mqJrxprJeluSjBd+3/ElxURrEXjwJAUvmlN1OPEhXDmRHd92mKnlkyKEeX +OkiFCiIFKih1S5Y/sRJTQ0781nyJjtJqO7UyC3pnQu1oFEePL+UEniRztQJAMfav +AtnpYKDSM+1jcp7uu9BemYGtzKDTTAYfoiNF42EzSJiGrWJDQn4eLgPjY0T0aAf/ +yGz3Z9ErbhMm/Ysl+QJBAL4kBxRT8gM4ByJw4sdOvSeCCANFq8fhbgm8pGWlCPb5 +JGmX3/GHFM8x2tbWMGpyZP1DLtiNEFz7eCGktWK5rqE= +-----END RSA PRIVATE KEY----- diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/request.pem b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/request.pem new file mode 100644 index 00000000..51bc7f62 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/request.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBhDCB7gIBADBFMQswCQYDVQQGEwJubzETMBEGA1UECAwKU29tZS1TdGF0ZTEh +MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQC2tDv6v//aJX8HoX7hugfReoWftqVxX2WmO8CbBFc0qfEC +hrR/3sCNg8Y0squOmQ1deEElE4h1tFtmcI14Ll/NfVr4kKjspK3MFe4ZJmvbtO0W +ZxXgf72AhEhw0e1mYkufFsmwiGQZHzJVh2Yll7h5PmV2TXOgHVp2A8XWFmEIEwID +AQABoAAwDQYJKoZIhvcNAQEFBQADgYEAjsUXEARgfxZNkMjuUcudgU2w4JXS0gGI +JQ0U1LmU0vMDSKwqndMlvCbKzEgPbJnGJDI8D4MeINCJHa5Ceyb8c+jaJYUcCabl +lQW5Psn3+eWp8ncKlIycDRj1Qk615XuXtV0fhkrgQM2ZCm9LaQ1O1Gd/CzLihLjF +W0MmgMKMMRk= +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/textfile b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/textfile new file mode 100644 index 00000000..a10483b0 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/textfile @@ -0,0 +1,9 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam egestas, massa at aliquam luctus, sapien erat viverra elit, nec pulvinar turpis eros sagittis urna. Pellentesque imperdiet tempor varius. Pellentesque blandit, ipsum in imperdiet venenatis, mi elit faucibus odio, id condimentum ante enim sed lectus. Aliquam et odio non odio pellentesque pulvinar. Vestibulum a erat dolor. Integer pretium risus sit amet nisl volutpat nec venenatis magna egestas. Ut bibendum felis eu tellus laoreet eleifend. Nam pulvinar auctor tortor, eu iaculis leo vestibulum quis. In euismod risus ac purus vehicula et fermentum ligula consectetur. Vivamus condimentum tempus lacinia. + +Curabitur sodales condimentum urna id dictum. Sed quis justo sit amet quam ultrices tincidunt vel laoreet nulla. Nullam quis ipsum sed nisi mollis bibendum at sit amet nisi. Donec laoreet consequat velit sit amet mollis. Nam sed sapien a massa iaculis dapibus. Sed dui nunc, ultricies et pellentesque ullamcorper, aliquet vitae ligula. Integer eu velit in neque iaculis venenatis. Ut rhoncus cursus est, ac dignissim leo vehicula a. Nulla ullamcorper vulputate mauris id blandit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eleifend, nisi a tempor sollicitudin, odio massa pretium urna, quis congue sapien elit at tortor. Curabitur ipsum orci, vehicula non commodo molestie, laoreet id enim. Pellentesque convallis ultrices congue. Pellentesque nec iaculis lorem. In sagittis pharetra ipsum eget sodales. + +Fusce id nulla odio. Nunc nibh justo, placerat vel tincidunt sed, ornare et enim. Nulla vel urna vel ante commodo bibendum in vitae metus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis erat nunc, semper eget sagittis sit amet, ullamcorper eget lacus. Donec hendrerit ipsum vitae eros vestibulum eu gravida neque tincidunt. Ut molestie lacinia nulla. Donec mattis odio at magna egestas at pellentesque eros accumsan. Praesent interdum sem sit amet nibh commodo dignissim. Duis laoreet, enim ultricies fringilla suscipit, enim libero cursus nulla, sollicitudin adipiscing erat velit ut dui. Nulla eleifend mauris at velit fringilla a molestie lorem venenatis. + +Donec sit amet scelerisque metus. Cras ac felis a nulla venenatis vulputate. Duis porttitor eros ac neque rhoncus eget aliquet neque egestas. Quisque sed nunc est, vitae dapibus quam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In vehicula, est vitae posuere ultricies, diam purus pretium sapien, nec rhoncus dolor nisl eget arcu. Aliquam et nisi vitae risus tincidunt auctor. In vehicula, erat a cursus adipiscing, lorem orci congue est, nec ultricies elit dui in nunc. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Duis congue tempus elit sit amet auctor. Duis dignissim, risus ut sollicitudin ultricies, dolor ligula gravida odio, nec congue orci purus ut ligula. Fusce pretium dictum lectus at volutpat. Sed non auctor mauris. Etiam placerat vestibulum massa id blandit. Quisque consequat lacus ut nulla euismod facilisis. Sed aliquet ipsum nec mi imperdiet viverra. Pellentesque ullamcorper, lectus nec varius gravida, odio justo cursus risus, eu sagittis metus arcu quis felis. Phasellus consectetur vehicula libero, at condimentum orci euismod vel. Nunc purus tortor, suscipit nec fringilla nec, vulputate et nibh. Nam porta vehicula neque. Praesent porttitor, sapien eu auctor euismod, arcu quam elementum urna, sed hendrerit magna augue sed quam. \ No newline at end of file diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/hybi-common.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/hybi-common.js new file mode 100644 index 00000000..006f9c69 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/hybi-common.js @@ -0,0 +1,99 @@ +/** + * Returns a Buffer from a "ff 00 ff"-type hex string. + */ + +getBufferFromHexString = function(byteStr) { + var bytes = byteStr.split(' '); + var buf = new Buffer(bytes.length); + for (var i = 0; i < bytes.length; ++i) { + buf[i] = parseInt(bytes[i], 16); + } + return buf; +} + +/** + * Returns a hex string from a Buffer. + */ + +getHexStringFromBuffer = function(data) { + var s = ''; + for (var i = 0; i < data.length; ++i) { + s += padl(data[i].toString(16), 2, '0') + ' '; + } + return s.trim(); +} + +/** + * Splits a buffer in two parts. + */ + +splitBuffer = function(buffer) { + var b1 = new Buffer(Math.ceil(buffer.length / 2)); + buffer.copy(b1, 0, 0, b1.length); + var b2 = new Buffer(Math.floor(buffer.length / 2)); + buffer.copy(b2, 0, b1.length, b1.length + b2.length); + return [b1, b2]; +} + +/** + * Performs hybi07+ type masking on a hex string or buffer. + */ + +mask = function(buf, maskString) { + if (typeof buf == 'string') buf = new Buffer(buf); + var mask = getBufferFromHexString(maskString || '34 83 a8 68'); + for (var i = 0; i < buf.length; ++i) { + buf[i] ^= mask[i % 4]; + } + return buf; +} + +/** + * Returns a hex string representing the length of a message + */ + +getHybiLengthAsHexString = function(len, masked) { + if (len < 126) { + var buf = new Buffer(1); + buf[0] = (masked ? 0x80 : 0) | len; + } + else if (len < 65536) { + var buf = new Buffer(3); + buf[0] = (masked ? 0x80 : 0) | 126; + getBufferFromHexString(pack(4, len)).copy(buf, 1); + } + else { + var buf = new Buffer(9); + buf[0] = (masked ? 0x80 : 0) | 127; + getBufferFromHexString(pack(16, len)).copy(buf, 1); + } + return getHexStringFromBuffer(buf); +} + +/** + * Unpacks a Buffer into a number. + */ + +unpack = function(buffer) { + var n = 0; + for (var i = 0; i < buffer.length; ++i) { + n = (i == 0) ? buffer[i] : (n * 256) + buffer[i]; + } + return n; +} + +/** + * Returns a hex string, representing a specific byte count 'length', from a number. + */ + +pack = function(length, number) { + return padl(number.toString(16), length, '0').replace(/([0-9a-f][0-9a-f])/gi, '$1 ').trim(); +} + +/** + * Left pads the string 's' to a total length of 'n' with char 'c'. + */ + +padl = function(s, n, c) { + return new Array(1 + n - s.length).join(c) + s; +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/testserver.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/testserver.js new file mode 100644 index 00000000..3e7a9667 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/testserver.js @@ -0,0 +1,180 @@ +var http = require('http') + , util = require('util') + , crypto = require('crypto') + , events = require('events') + , Sender = require('../lib/Sender') + , Receiver = require('../lib/Receiver'); + +module.exports = { + handlers: { + valid: validServer, + invalidKey: invalidRequestHandler, + closeAfterConnect: closeAfterConnectHandler, + return401: return401 + }, + createServer: function(port, handler, cb) { + if (handler && !cb) { + cb = handler; + handler = null; + } + var webServer = http.createServer(function (req, res) { + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.end('okay'); + }); + var srv = new Server(webServer); + webServer.on('upgrade', function(req, socket) { + webServer._socket = socket; + (handler || validServer)(srv, req, socket); + }); + webServer.listen(port, '127.0.0.1', function() { cb(srv); }); + } +}; + +/** + * Test strategies + */ + +function validServer(server, req, socket) { + if (typeof req.headers.upgrade === 'undefined' || + req.headers.upgrade.toLowerCase() !== 'websocket') { + throw new Error('invalid headers'); + return; + } + + if (!req.headers['sec-websocket-key']) { + socket.end(); + throw new Error('websocket key is missing'); + } + + // calc key + var key = req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + socket.write(headers.concat('', '').join('\r\n')); + socket.setTimeout(0); + socket.setNoDelay(true); + + var sender = new Sender(socket); + var receiver = new Receiver(); + receiver.ontext = function (message, flags) { + server.emit('message', message, flags); + sender.send(message); + }; + receiver.onbinary = function (message, flags) { + flags = flags || {}; + flags.binary = true; + server.emit('message', message, flags); + sender.send(message, {binary: true}); + }; + receiver.onping = function (message, flags) { + flags = flags || {}; + server.emit('ping', message, flags); + }; + receiver.onpong = function (message, flags) { + flags = flags || {}; + server.emit('pong', message, flags); + }; + receiver.onclose = function (code, message, flags) { + flags = flags || {}; + server.emit('close', code, message, flags); + }; + socket.on('data', function (data) { + receiver.add(data); + }); + socket.on('end', function() { + socket.end(); + }); +} + +function invalidRequestHandler(server, req, socket) { + if (typeof req.headers.upgrade === 'undefined' || + req.headers.upgrade.toLowerCase() !== 'websocket') { + throw new Error('invalid headers'); + return; + } + + if (!req.headers['sec-websocket-key']) { + socket.end(); + throw new Error('websocket key is missing'); + } + + // calc key + var key = req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "bogus"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + socket.write(headers.concat('', '').join('\r\n')); + socket.end(); +} + +function closeAfterConnectHandler(server, req, socket) { + if (typeof req.headers.upgrade === 'undefined' || + req.headers.upgrade.toLowerCase() !== 'websocket') { + throw new Error('invalid headers'); + return; + } + + if (!req.headers['sec-websocket-key']) { + socket.end(); + throw new Error('websocket key is missing'); + } + + // calc key + var key = req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + socket.write(headers.concat('', '').join('\r\n')); + socket.end(); +} + + +function return401(server, req, socket) { + var headers = [ + 'HTTP/1.1 401 Unauthorized' + , 'Content-type: text/html' + ]; + + socket.write(headers.concat('', '').join('\r\n')); + socket.end(); +} + +/** + * Server object, which will do the actual emitting + */ + +function Server(webServer) { + this.webServer = webServer; +} + +util.inherits(Server, events.EventEmitter); + +Server.prototype.close = function() { + this.webServer.close(); + if (this._socket) this._socket.end(); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/README.md b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/README.md new file mode 100644 index 00000000..22aab8bd --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/README.md @@ -0,0 +1,53 @@ +# node-XMLHttpRequest # + +node-XMLHttpRequest is a wrapper for the built-in http client to emulate the +browser XMLHttpRequest object. + +This can be used with JS designed for browsers to improve reuse of code and +allow the use of existing libraries. + +Note: This library currently conforms to [XMLHttpRequest 1](http://www.w3.org/TR/XMLHttpRequest/). Version 2.0 will target [XMLHttpRequest Level 2](http://www.w3.org/TR/XMLHttpRequest2/). + +## Usage ## + +Here's how to include the module in your project and use as the browser-based +XHR object. + + var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; + var xhr = new XMLHttpRequest(); + +Note: use the lowercase string "xmlhttprequest" in your require(). On +case-sensitive systems (eg Linux) using uppercase letters won't work. + +## Versions ## + +Prior to 1.4.0 version numbers were arbitrary. From 1.4.0 on they conform to +the standard major.minor.bugfix. 1.x shouldn't necessarily be considered +stable just because it's above 0.x. + +Since the XMLHttpRequest API is stable this library's API is stable as +well. Major version numbers indicate significant core code changes. +Minor versions indicate minor core code changes or better conformity to +the W3C spec. + +## Supports ## + +* Async and synchronous requests +* GET, POST, PUT, and DELETE requests +* All spec methods (open, send, abort, getRequestHeader, + getAllRequestHeaders, event methods) +* Requests to all domains + +## Known Issues / Missing Features ## + +For a list of open issues or to report your own visit the [github issues +page](https://github.com/driverdan/node-XMLHttpRequest/issues). + +* Local file access may have unexpected results for non-UTF8 files +* Synchronous requests don't set headers properly +* Synchronous requests freeze node while waiting for response (But that's what you want, right? Stick with async!). +* Some events are missing, such as abort +* getRequestHeader is case-sensitive +* Cookies aren't persisted between requests +* Missing XML support +* Missing basic auth diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/autotest.watchr b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/autotest.watchr new file mode 100644 index 00000000..5324db6c --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/autotest.watchr @@ -0,0 +1,8 @@ +def run_all_tests + puts `clear` + puts `node tests/test-constants.js` + puts `node tests/test-headers.js` + puts `node tests/test-request.js` +end +watch('.*.js') { run_all_tests } +run_all_tests diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/example/demo.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/example/demo.js new file mode 100644 index 00000000..4f333de9 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/example/demo.js @@ -0,0 +1,16 @@ +var sys = require('util'); +var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; + +var xhr = new XMLHttpRequest(); + +xhr.onreadystatechange = function() { + sys.puts("State: " + this.readyState); + + if (this.readyState == 4) { + sys.puts("Complete.\nBody length: " + this.responseText.length); + sys.puts("Body:\n" + this.responseText); + } +}; + +xhr.open("GET", "http://driverdan.com"); +xhr.send(); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/lib/XMLHttpRequest.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/lib/XMLHttpRequest.js new file mode 100644 index 00000000..214a2e3b --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/lib/XMLHttpRequest.js @@ -0,0 +1,548 @@ +/** + * Wrapper for built-in http.js to emulate the browser XMLHttpRequest object. + * + * This can be used with JS designed for browsers to improve reuse of code and + * allow the use of existing libraries. + * + * Usage: include("XMLHttpRequest.js") and use XMLHttpRequest per W3C specs. + * + * @author Dan DeFelippi + * @contributor David Ellis + * @license MIT + */ + +var Url = require("url") + , spawn = require("child_process").spawn + , fs = require('fs'); + +exports.XMLHttpRequest = function() { + /** + * Private variables + */ + var self = this; + var http = require('http'); + var https = require('https'); + + // Holds http.js objects + var client; + var request; + var response; + + // Request settings + var settings = {}; + + // Set some default headers + var defaultHeaders = { + "User-Agent": "node-XMLHttpRequest", + "Accept": "*/*", + }; + + var headers = defaultHeaders; + + // These headers are not user setable. + // The following are allowed but banned in the spec: + // * user-agent + var forbiddenRequestHeaders = [ + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "content-transfer-encoding", + "cookie", + "cookie2", + "date", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "via" + ]; + + // These request methods are not allowed + var forbiddenRequestMethods = [ + "TRACE", + "TRACK", + "CONNECT" + ]; + + // Send flag + var sendFlag = false; + // Error flag, used when errors occur or abort is called + var errorFlag = false; + + // Event listeners + var listeners = {}; + + /** + * Constants + */ + + this.UNSENT = 0; + this.OPENED = 1; + this.HEADERS_RECEIVED = 2; + this.LOADING = 3; + this.DONE = 4; + + /** + * Public vars + */ + + // Current state + this.readyState = this.UNSENT; + + // default ready state change handler in case one is not set or is set late + this.onreadystatechange = null; + + // Result & response + this.responseText = ""; + this.responseXML = ""; + this.status = null; + this.statusText = null; + + /** + * Private methods + */ + + /** + * Check if the specified header is allowed. + * + * @param string header Header to validate + * @return boolean False if not allowed, otherwise true + */ + var isAllowedHttpHeader = function(header) { + return (header && forbiddenRequestHeaders.indexOf(header.toLowerCase()) === -1); + }; + + /** + * Check if the specified method is allowed. + * + * @param string method Request method to validate + * @return boolean False if not allowed, otherwise true + */ + var isAllowedHttpMethod = function(method) { + return (method && forbiddenRequestMethods.indexOf(method) === -1); + }; + + /** + * Public methods + */ + + /** + * Open the connection. Currently supports local server requests. + * + * @param string method Connection method (eg GET, POST) + * @param string url URL for the connection. + * @param boolean async Asynchronous connection. Default is true. + * @param string user Username for basic authentication (optional) + * @param string password Password for basic authentication (optional) + */ + this.open = function(method, url, async, user, password) { + this.abort(); + errorFlag = false; + + // Check for valid request method + if (!isAllowedHttpMethod(method)) { + throw "SecurityError: Request method not allowed"; + return; + } + + settings = { + "method": method, + "url": url.toString(), + "async": (typeof async !== "boolean" ? true : async), + "user": user || null, + "password": password || null + }; + + setState(this.OPENED); + }; + + /** + * Sets a header for the request. + * + * @param string header Header name + * @param string value Header value + */ + this.setRequestHeader = function(header, value) { + if (this.readyState != this.OPENED) { + throw "INVALID_STATE_ERR: setRequestHeader can only be called when state is OPEN"; + } + if (!isAllowedHttpHeader(header)) { + console.warn('Refused to set unsafe header "' + header + '"'); + return; + } + if (sendFlag) { + throw "INVALID_STATE_ERR: send flag is true"; + } + headers[header] = value; + }; + + /** + * Gets a header from the server response. + * + * @param string header Name of header to get. + * @return string Text of the header or null if it doesn't exist. + */ + this.getResponseHeader = function(header) { + if (typeof header === "string" + && this.readyState > this.OPENED + && response.headers[header.toLowerCase()] + && !errorFlag + ) { + return response.headers[header.toLowerCase()]; + } + + return null; + }; + + /** + * Gets all the response headers. + * + * @return string A string with all response headers separated by CR+LF + */ + this.getAllResponseHeaders = function() { + if (this.readyState < this.HEADERS_RECEIVED || errorFlag) { + return ""; + } + var result = ""; + + for (var i in response.headers) { + // Cookie headers are excluded + if (i !== "set-cookie" && i !== "set-cookie2") { + result += i + ": " + response.headers[i] + "\r\n"; + } + } + return result.substr(0, result.length - 2); + }; + + /** + * Gets a request header + * + * @param string name Name of header to get + * @return string Returns the request header or empty string if not set + */ + this.getRequestHeader = function(name) { + // @TODO Make this case insensitive + if (typeof name === "string" && headers[name]) { + return headers[name]; + } + + return ""; + } + + /** + * Sends the request to the server. + * + * @param string data Optional data to send as request body. + */ + this.send = function(data) { + if (this.readyState != this.OPENED) { + throw "INVALID_STATE_ERR: connection must be opened before send() is called"; + } + + if (sendFlag) { + throw "INVALID_STATE_ERR: send has already been called"; + } + + var ssl = false, local = false; + var url = Url.parse(settings.url); + + // Determine the server + switch (url.protocol) { + case 'https:': + ssl = true; + // SSL & non-SSL both need host, no break here. + case 'http:': + var host = url.hostname; + break; + + case 'file:': + local = true; + break; + + case undefined: + case '': + var host = "localhost"; + break; + + default: + throw "Protocol not supported."; + } + + // Load files off the local filesystem (file://) + if (local) { + if (settings.method !== "GET") { + throw "XMLHttpRequest: Only GET method is supported"; + } + + if (settings.async) { + fs.readFile(url.pathname, 'utf8', function(error, data) { + if (error) { + self.handleError(error); + } else { + self.status = 200; + self.responseText = data; + setState(self.DONE); + } + }); + } else { + try { + this.responseText = fs.readFileSync(url.pathname, 'utf8'); + this.status = 200; + setState(self.DONE); + } catch(e) { + this.handleError(e); + } + } + + return; + } + + // Default to port 80. If accessing localhost on another port be sure + // to use http://localhost:port/path + var port = url.port || (ssl ? 443 : 80); + // Add query string if one is used + var uri = url.pathname + (url.search ? url.search : ''); + + // Set the Host header or the server may reject the request + headers["Host"] = host; + if (!((ssl && port === 443) || port === 80)) { + headers["Host"] += ':' + url.port; + } + + // Set Basic Auth if necessary + if (settings.user) { + if (typeof settings.password == "undefined") { + settings.password = ""; + } + var authBuf = new Buffer(settings.user + ":" + settings.password); + headers["Authorization"] = "Basic " + authBuf.toString("base64"); + } + + // Set content length header + if (settings.method === "GET" || settings.method === "HEAD") { + data = null; + } else if (data) { + headers["Content-Length"] = Buffer.byteLength(data); + + if (!headers["Content-Type"]) { + headers["Content-Type"] = "text/plain;charset=UTF-8"; + } + } else if (settings.method === "POST") { + // For a post with no data set Content-Length: 0. + // This is required by buggy servers that don't meet the specs. + headers["Content-Length"] = 0; + } + + var options = { + host: host, + port: port, + path: uri, + method: settings.method, + headers: headers + }; + + // Reset error flag + errorFlag = false; + + // Handle async requests + if (settings.async) { + // Use the proper protocol + var doRequest = ssl ? https.request : http.request; + + // Request is being sent, set send flag + sendFlag = true; + + // As per spec, this is called here for historical reasons. + self.dispatchEvent("readystatechange"); + + // Create the request + request = doRequest(options, function(resp) { + response = resp; + response.setEncoding("utf8"); + + setState(self.HEADERS_RECEIVED); + self.status = response.statusCode; + + response.on('data', function(chunk) { + // Make sure there's some data + if (chunk) { + self.responseText += chunk; + } + // Don't emit state changes if the connection has been aborted. + if (sendFlag) { + setState(self.LOADING); + } + }); + + response.on('end', function() { + if (sendFlag) { + // Discard the 'end' event if the connection has been aborted + setState(self.DONE); + sendFlag = false; + } + }); + + response.on('error', function(error) { + self.handleError(error); + }); + }).on('error', function(error) { + self.handleError(error); + }); + + // Node 0.4 and later won't accept empty data. Make sure it's needed. + if (data) { + request.write(data); + } + + request.end(); + + self.dispatchEvent("loadstart"); + } else { // Synchronous + // Create a temporary file for communication with the other Node process + var syncFile = ".node-xmlhttprequest-sync-" + process.pid; + fs.writeFileSync(syncFile, "", "utf8"); + // The async request the other Node process executes + var execString = "var http = require('http'), https = require('https'), fs = require('fs');" + + "var doRequest = http" + (ssl ? "s" : "") + ".request;" + + "var options = " + JSON.stringify(options) + ";" + + "var responseText = '';" + + "var req = doRequest(options, function(response) {" + + "response.setEncoding('utf8');" + + "response.on('data', function(chunk) {" + + "responseText += chunk;" + + "});" + + "response.on('end', function() {" + + "fs.writeFileSync('" + syncFile + "', 'NODE-XMLHTTPREQUEST-STATUS:' + response.statusCode + ',' + responseText, 'utf8');" + + "});" + + "response.on('error', function(error) {" + + "fs.writeFileSync('" + syncFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');" + + "});" + + "}).on('error', function(error) {" + + "fs.writeFileSync('" + syncFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');" + + "});" + + (data ? "req.write('" + data.replace(/'/g, "\\'") + "');":"") + + "req.end();"; + // Start the other Node Process, executing this string + syncProc = spawn(process.argv[0], ["-e", execString]); + while((self.responseText = fs.readFileSync(syncFile, 'utf8')) == "") { + // Wait while the file is empty + } + // Kill the child process once the file has data + syncProc.stdin.end(); + // Remove the temporary file + fs.unlinkSync(syncFile); + if (self.responseText.match(/^NODE-XMLHTTPREQUEST-ERROR:/)) { + // If the file returned an error, handle it + var errorObj = self.responseText.replace(/^NODE-XMLHTTPREQUEST-ERROR:/, ""); + self.handleError(errorObj); + } else { + // If the file returned okay, parse its data and move to the DONE state + self.status = self.responseText.replace(/^NODE-XMLHTTPREQUEST-STATUS:([0-9]*),.*/, "$1"); + self.responseText = self.responseText.replace(/^NODE-XMLHTTPREQUEST-STATUS:[0-9]*,(.*)/, "$1"); + setState(self.DONE); + } + } + }; + + /** + * Called when an error is encountered to deal with it. + */ + this.handleError = function(error) { + this.status = 503; + this.statusText = error; + this.responseText = error.stack; + errorFlag = true; + setState(this.DONE); + }; + + /** + * Aborts a request. + */ + this.abort = function() { + if (request) { + request.abort(); + request = null; + } + + headers = defaultHeaders; + this.responseText = ""; + this.responseXML = ""; + + errorFlag = true; + + if (this.readyState !== this.UNSENT + && (this.readyState !== this.OPENED || sendFlag) + && this.readyState !== this.DONE) { + sendFlag = false; + setState(this.DONE); + } + this.readyState = this.UNSENT; + }; + + /** + * Adds an event listener. Preferred method of binding to events. + */ + this.addEventListener = function(event, callback) { + if (!(event in listeners)) { + listeners[event] = []; + } + // Currently allows duplicate callbacks. Should it? + listeners[event].push(callback); + }; + + /** + * Remove an event callback that has already been bound. + * Only works on the matching funciton, cannot be a copy. + */ + this.removeEventListener = function(event, callback) { + if (event in listeners) { + // Filter will return a new array with the callback removed + listeners[event] = listeners[event].filter(function(ev) { + return ev !== callback; + }); + } + }; + + /** + * Dispatch any events, including both "on" methods and events attached using addEventListener. + */ + this.dispatchEvent = function(event) { + if (typeof self["on" + event] === "function") { + self["on" + event](); + } + if (event in listeners) { + for (var i = 0, len = listeners[event].length; i < len; i++) { + listeners[event][i].call(self); + } + } + }; + + /** + * Changes readyState and calls onreadystatechange. + * + * @param int state New state + */ + var setState = function(state) { + if (self.readyState !== state) { + self.readyState = state; + + if (settings.async || self.readyState < self.OPENED || self.readyState === self.DONE) { + self.dispatchEvent("readystatechange"); + } + + if (self.readyState === self.DONE && !errorFlag) { + self.dispatchEvent("load"); + // @TODO figure out InspectorInstrumentation::didLoadXHR(cookie) + self.dispatchEvent("loadend"); + } + } + }; +}; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/package.json new file mode 100644 index 00000000..e1f4bf34 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/package.json @@ -0,0 +1,39 @@ +{ + "name": "xmlhttprequest", + "description": "XMLHttpRequest for Node", + "version": "1.4.2", + "author": { + "name": "Dan DeFelippi", + "url": "http://driverdan.com" + }, + "keywords": [ + "xhr", + "ajax" + ], + "licenses": [ + { + "type": "MIT", + "url": "http://creativecommons.org/licenses/MIT/" + } + ], + "repository": { + "type": "git", + "url": "git://github.com/driverdan/node-XMLHttpRequest.git" + }, + "bugs": { + "url": "http://github.com/driverdan/node-XMLHttpRequest/issues" + }, + "engines": { + "node": ">=0.4.0" + }, + "directories": { + "lib": "./lib", + "example": "./example" + }, + "main": "./lib/XMLHttpRequest.js", + "readme": "# node-XMLHttpRequest #\n\nnode-XMLHttpRequest is a wrapper for the built-in http client to emulate the\nbrowser XMLHttpRequest object.\n\nThis can be used with JS designed for browsers to improve reuse of code and\nallow the use of existing libraries.\n\nNote: This library currently conforms to [XMLHttpRequest 1](http://www.w3.org/TR/XMLHttpRequest/). Version 2.0 will target [XMLHttpRequest Level 2](http://www.w3.org/TR/XMLHttpRequest2/).\n\n## Usage ##\n\nHere's how to include the module in your project and use as the browser-based\nXHR object.\n\n\tvar XMLHttpRequest = require(\"xmlhttprequest\").XMLHttpRequest;\n\tvar xhr = new XMLHttpRequest();\n\nNote: use the lowercase string \"xmlhttprequest\" in your require(). On\ncase-sensitive systems (eg Linux) using uppercase letters won't work.\n\n## Versions ##\n\nPrior to 1.4.0 version numbers were arbitrary. From 1.4.0 on they conform to\nthe standard major.minor.bugfix. 1.x shouldn't necessarily be considered\nstable just because it's above 0.x.\n\nSince the XMLHttpRequest API is stable this library's API is stable as\nwell. Major version numbers indicate significant core code changes.\nMinor versions indicate minor core code changes or better conformity to\nthe W3C spec.\n\n## Supports ##\n\n* Async and synchronous requests\n* GET, POST, PUT, and DELETE requests\n* All spec methods (open, send, abort, getRequestHeader,\n getAllRequestHeaders, event methods)\n* Requests to all domains\n\n## Known Issues / Missing Features ##\n\nFor a list of open issues or to report your own visit the [github issues\npage](https://github.com/driverdan/node-XMLHttpRequest/issues).\n\n* Local file access may have unexpected results for non-UTF8 files\n* Synchronous requests don't set headers properly\n* Synchronous requests freeze node while waiting for response (But that's what you want, right? Stick with async!).\n* Some events are missing, such as abort\n* getRequestHeader is case-sensitive\n* Cookies aren't persisted between requests\n* Missing XML support\n* Missing basic auth\n", + "readmeFilename": "README.md", + "homepage": "https://github.com/driverdan/node-XMLHttpRequest", + "_id": "xmlhttprequest@1.4.2", + "_from": "xmlhttprequest@1.4.2" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-constants.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-constants.js new file mode 100644 index 00000000..372e46cc --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-constants.js @@ -0,0 +1,13 @@ +var sys = require("util") + , assert = require("assert") + , XMLHttpRequest = require("../lib/XMLHttpRequest").XMLHttpRequest + , xhr = new XMLHttpRequest(); + +// Test constant values +assert.equal(0, xhr.UNSENT); +assert.equal(1, xhr.OPENED); +assert.equal(2, xhr.HEADERS_RECEIVED); +assert.equal(3, xhr.LOADING); +assert.equal(4, xhr.DONE); + +sys.puts("done"); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-events.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-events.js new file mode 100644 index 00000000..c72f001d --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-events.js @@ -0,0 +1,50 @@ +var sys = require("util") + , assert = require("assert") + , http = require("http") + , XMLHttpRequest = require("../lib/XMLHttpRequest").XMLHttpRequest + , xhr; + +// Test server +var server = http.createServer(function (req, res) { + var body = (req.method != "HEAD" ? "Hello World" : ""); + + res.writeHead(200, { + "Content-Type": "text/plain", + "Content-Length": Buffer.byteLength(body) + }); + // HEAD has no body + if (req.method != "HEAD") { + res.write(body); + } + res.end(); + assert.equal(onreadystatechange, true); + assert.equal(readystatechange, true); + assert.equal(removed, true); + sys.puts("done"); + this.close(); +}).listen(8000); + +xhr = new XMLHttpRequest(); + +// Track event calls +var onreadystatechange = false; +var readystatechange = false; +var removed = true; +var removedEvent = function() { + removed = false; +}; + +xhr.onreadystatechange = function() { + onreadystatechange = true; +}; + +xhr.addEventListener("readystatechange", function() { + readystatechange = true; +}); + +// This isn't perfect, won't guarantee it was added in the first place +xhr.addEventListener("readystatechange", removedEvent); +xhr.removeEventListener("readystatechange", removedEvent); + +xhr.open("GET", "http://localhost:8000"); +xhr.send(); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-exceptions.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-exceptions.js new file mode 100644 index 00000000..f1edd71f --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-exceptions.js @@ -0,0 +1,62 @@ +var sys = require("util") + , assert = require("assert") + , XMLHttpRequest = require("../lib/XMLHttpRequest").XMLHttpRequest + , xhr = new XMLHttpRequest(); + +// Test request methods that aren't allowed +try { + xhr.open("TRACK", "http://localhost:8000/"); + console.log("ERROR: TRACK should have thrown exception"); +} catch(e) {} +try { + xhr.open("TRACE", "http://localhost:8000/"); + console.log("ERROR: TRACE should have thrown exception"); +} catch(e) {} +try { + xhr.open("CONNECT", "http://localhost:8000/"); + console.log("ERROR: CONNECT should have thrown exception"); +} catch(e) {} +// Test valid request method +try { + xhr.open("GET", "http://localhost:8000/"); +} catch(e) { + console.log("ERROR: Invalid exception for GET", e); +} + +// Test forbidden headers +var forbiddenRequestHeaders = [ + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "content-transfer-encoding", + "cookie", + "cookie2", + "date", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "user-agent", + "via" +]; + +for (var i in forbiddenRequestHeaders) { + try { + xhr.setRequestHeader(forbiddenRequestHeaders[i], "Test"); + console.log("ERROR: " + forbiddenRequestHeaders[i] + " should have thrown exception"); + } catch(e) { + } +} + +// Try valid header +xhr.setRequestHeader("X-Foobar", "Test"); + +console.log("Done"); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-headers.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-headers.js new file mode 100644 index 00000000..2ecb045d --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-headers.js @@ -0,0 +1,61 @@ +var sys = require("util") + , assert = require("assert") + , XMLHttpRequest = require("../lib/XMLHttpRequest").XMLHttpRequest + , xhr = new XMLHttpRequest() + , http = require("http"); + +// Test server +var server = http.createServer(function (req, res) { + // Test setRequestHeader + assert.equal("Foobar", req.headers["x-test"]); + + var body = "Hello World"; + res.writeHead(200, { + "Content-Type": "text/plain", + "Content-Length": Buffer.byteLength(body), + // Set cookie headers to see if they're correctly suppressed + // Actual values don't matter + "Set-Cookie": "foo=bar", + "Set-Cookie2": "bar=baz", + "Connection": "close" + }); + res.write("Hello World"); + res.end(); + + this.close(); +}).listen(8000); + +xhr.onreadystatechange = function() { + if (this.readyState == 4) { + // Test getAllResponseHeaders() + var headers = "content-type: text/plain\r\ncontent-length: 11\r\nconnection: close"; + assert.equal(headers, this.getAllResponseHeaders()); + + // Test case insensitivity + assert.equal('text/plain', this.getResponseHeader('Content-Type')); + assert.equal('text/plain', this.getResponseHeader('Content-type')); + assert.equal('text/plain', this.getResponseHeader('content-Type')); + assert.equal('text/plain', this.getResponseHeader('content-type')); + + // Test aborted getAllResponseHeaders + this.abort(); + assert.equal("", this.getAllResponseHeaders()); + assert.equal(null, this.getResponseHeader("Connection")); + + sys.puts("done"); + } +}; + +assert.equal(null, xhr.getResponseHeader("Content-Type")); +try { + xhr.open("GET", "http://localhost:8000/"); + // Valid header + xhr.setRequestHeader("X-Test", "Foobar"); + // Invalid header + xhr.setRequestHeader("Content-Length", 0); + // Test getRequestHeader + assert.equal("Foobar", xhr.getRequestHeader("X-Test")); + xhr.send(); +} catch(e) { + console.log("ERROR: Exception raised", e); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-methods.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-methods.js new file mode 100644 index 00000000..fa1b1bed --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-methods.js @@ -0,0 +1,62 @@ +var sys = require("util") + , assert = require("assert") + , XMLHttpRequest = require("../lib/XMLHttpRequest").XMLHttpRequest + , http = require("http") + , xhr; + +// Test server +var server = http.createServer(function (req, res) { + // Check request method and URL + assert.equal(methods[curMethod], req.method); + assert.equal("/" + methods[curMethod], req.url); + + var body = (req.method != "HEAD" ? "Hello World" : ""); + + res.writeHead(200, { + "Content-Type": "text/plain", + "Content-Length": Buffer.byteLength(body) + }); + // HEAD has no body + if (req.method != "HEAD") { + res.write(body); + } + res.end(); + + if (curMethod == methods.length - 1) { + this.close(); + sys.puts("done"); + } +}).listen(8000); + +// Test standard methods +var methods = ["GET", "POST", "HEAD", "PUT", "DELETE"]; +var curMethod = 0; + +function start(method) { + // Reset each time + xhr = new XMLHttpRequest(); + + xhr.onreadystatechange = function() { + if (this.readyState == 4) { + if (method == "HEAD") { + assert.equal("", this.responseText); + } else { + assert.equal("Hello World", this.responseText); + } + + curMethod++; + + if (curMethod < methods.length) { + sys.puts("Testing " + methods[curMethod]); + start(methods[curMethod]); + } + } + }; + + var url = "http://localhost:8000/" + method; + xhr.open(method, url); + xhr.send(); +} + +sys.puts("Testing " + methods[curMethod]); +start(methods[curMethod]); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-protocols.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-protocols.js new file mode 100644 index 00000000..cd4e1745 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-protocols.js @@ -0,0 +1,34 @@ +var sys = require("util") + , assert = require("assert") + , XMLHttpRequest = require("../lib/XMLHttpRequest").XMLHttpRequest + , xhr; + +xhr = new XMLHttpRequest(); + +xhr.onreadystatechange = function() { + if (this.readyState == 4) { + assert.equal("Hello World", this.responseText); + this.close(); + runSync(); + } +}; + +// Async +var url = "file://" + __dirname + "/testdata.txt"; +xhr.open("GET", url); +xhr.send(); + +// Sync +var runSync = function() { + xhr = new XMLHttpRequest(); + + xhr.onreadystatechange = function() { + if (this.readyState == 4) { + assert.equal("Hello World", this.responseText); + this.close(); + sys.puts("done"); + } + }; + xhr.open("GET", url, false); + xhr.send(); +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/testdata.txt b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/testdata.txt new file mode 100644 index 00000000..557db03d --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/testdata.txt @@ -0,0 +1 @@ +Hello World diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/package.json b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/package.json new file mode 100644 index 00000000..569ad0b8 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/package.json @@ -0,0 +1,67 @@ +{ + "name": "socket.io-client", + "description": "Socket.IO client for the browser and node.js", + "version": "0.9.16", + "main": "./lib/io.js", + "browserify": "./dist/socket.io.js", + "homepage": "http://socket.io", + "keywords": [ + "websocket", + "socket", + "realtime", + "socket.io", + "comet", + "ajax" + ], + "author": { + "name": "Guillermo Rauch", + "email": "guillermo@learnboost.com" + }, + "contributors": [ + { + "name": "Guillermo Rauch", + "email": "rauchg@gmail.com" + }, + { + "name": "Arnout Kazemier", + "email": "info@3rd-eden.com" + }, + { + "name": "Vladimir Dronnikov", + "email": "dronnikov@gmail.com" + }, + { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/LearnBoost/socket.io-client.git" + }, + "dependencies": { + "uglify-js": "1.2.5", + "ws": "0.4.x", + "xmlhttprequest": "1.4.2", + "active-x-obfuscator": "0.0.1" + }, + "devDependencies": { + "expresso": "*", + "express": "2.5.x", + "jade": "*", + "stylus": "*", + "socket.io": "0.9.16", + "socket.io-client": "0.9.16", + "should": "*" + }, + "engines": { + "node": ">= 0.4.0" + }, + "readme": "socket.io\n=========\n\n#### Sockets for the rest of us\n\nThe `socket.io` client is basically a simple HTTP Socket interface implementation.\nIt looks similar to WebSocket while providing additional features and\nleveraging other transports when WebSocket is not supported by the user's\nbrowser.\n\n```js\nvar socket = io.connect('http://domain.com');\nsocket.on('connect', function () {\n // socket connected\n});\nsocket.on('custom event', function () {\n // server emitted a custom event\n});\nsocket.on('disconnect', function () {\n // socket disconnected\n});\nsocket.send('hi there');\n```\n\n### Recipes\n\n#### Utilizing namespaces (ie: multiple sockets)\n\nIf you want to namespace all the messages and events emitted to a particular\nendpoint, simply specify it as part of the `connect` uri:\n\n```js\nvar chat = io.connect('http://localhost/chat');\nchat.on('connect', function () {\n // chat socket connected\n});\n\nvar news = io.connect('/news'); // io.connect auto-detects host\nnews.on('connect', function () {\n // news socket connected\n});\n```\n\n#### Emitting custom events\n\nTo ease with the creation of applications, you can emit custom events outside\nof the global `message` event.\n\n```js\nvar socket = io.connect();\nsocket.emit('server custom event', { my: 'data' });\n```\n\n#### Forcing disconnection\n\n```js\nvar socket = io.connect();\nsocket.on('connect', function () {\n socket.disconnect();\n});\n```\n\n### Documentation \n\n#### io#connect\n\n```js\nio.connect(uri, [options]);\n```\n\n##### Options:\n\n- *resource*\n\n socket.io\n\n The resource is what allows the `socket.io` server to identify incoming connections by `socket.io` clients. In other words, any HTTP server can implement socket.io and still serve other normal, non-realtime HTTP requests.\n\n- *transports*\n\n```js\n['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling']\n```\n\n A list of the transports to attempt to utilize (in order of preference).\n\n- *'connect timeout'*\n\n```js\n5000\n```\n\n The amount of milliseconds a transport has to create a connection before we consider it timed out.\n \n- *'try multiple transports'*\n\n```js\ntrue\n```\n\n A boolean indicating if we should try other transports when the connectTimeout occurs.\n \n- *reconnect*\n\n```js\ntrue\n```\n\n A boolean indicating if we should automatically reconnect if a connection is disconnected. \n \n- *'reconnection delay'*\n\n```js\n500\n```\n\n The amount of milliseconds before we try to connect to the server again. We are using a exponential back off algorithm for the following reconnections, on each reconnect attempt this value will get multiplied (500 > 1000 > 2000 > 4000 > 8000).\n \n\n- *'max reconnection attempts'*\n\n```js\n10\n```\n\n The amount of attempts should we make using the current transport to connect to the server? After this we will do one final attempt, and re-try with all enabled transport methods before we give up.\n\n##### Properties:\n\n- *options*\n\n The passed in options combined with the defaults.\n\n- *connected*\n\n Whether the socket is connected or not.\n \n- *connecting*\n\n Whether the socket is connecting or not.\n\n- *reconnecting*\n\n Whether we are reconnecting or not.\n \n- *transport* \n\n The transport instance.\n\n##### Methods:\n \n- *connect(λ)*\n\n Establishes a connection. If λ is supplied as argument, it will be called once the connection is established.\n \n- *send(message)*\n \n A string of data to send.\n \n- *disconnect*\n\n Closes the connection.\n \n- *on(event, λ)*\n\n Adds a listener for the event *event*.\n\n- *once(event, λ)*\n\n Adds a one time listener for the event *event*. The listener is removed after the first time the event is fired.\n \n- *removeListener(event, λ)*\n\n Removes the listener λ for the event *event*.\n \n##### Events:\n\n- *connect*\n\n Fired when the connection is established and the handshake successful.\n \n- *connecting(transport_type)*\n\n Fired when a connection is attempted, passing the transport name.\n \n- *connect_failed*\n\n Fired when the connection timeout occurs after the last connection attempt.\n This only fires if the `connectTimeout` option is set.\n If the `tryTransportsOnConnectTimeout` option is set, this only fires once all\n possible transports have been tried.\n \n- *message(message)*\n \n Fired when a message arrives from the server\n\n- *close*\n\n Fired when the connection is closed. Be careful with using this event, as some transports will fire it even under temporary, expected disconnections (such as XHR-Polling).\n \n- *disconnect*\n\n Fired when the connection is considered disconnected.\n \n- *reconnect(transport_type,reconnectionAttempts)*\n\n Fired when the connection has been re-established. This only fires if the `reconnect` option is set.\n\n- *reconnecting(reconnectionDelay,reconnectionAttempts)*\n\n Fired when a reconnection is attempted, passing the next delay for the next reconnection.\n\n- *reconnect_failed*\n\n Fired when all reconnection attempts have failed and we where unsuccessful in reconnecting to the server. \n\n### Contributors\n\nGuillermo Rauch <guillermo@learnboost.com>\n\nArnout Kazemier <info@3rd-eden.com>\n\n### License \n\n(The MIT License)\n\nCopyright (c) 2010 LearnBoost <dev@learnboost.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/LearnBoost/socket.io-client/issues" + }, + "_id": "socket.io-client@0.9.16", + "_from": "socket.io-client@0.9.16" +} diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/events.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/events.test.js new file mode 100644 index 00000000..365c4223 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/events.test.js @@ -0,0 +1,120 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +(function (module, io, should) { + + module.exports = { + + 'add listeners': function () { + var event = new io.EventEmitter + , calls = 0; + + event.on('test', function (a, b) { + ++calls; + a.should().eql('a'); + b.should().eql('b'); + }); + + event.emit('test', 'a', 'b'); + calls.should().eql(1); + event.on.should().eql(event.addListener); + }, + + 'remove listener': function () { + var event = new io.EventEmitter; + function empty () { } + + event.on('test', empty); + event.on('test:more', empty); + event.removeAllListeners('test'); + + event.listeners('test').should().eql([]); + event.listeners('test:more').should().eql([empty]); + }, + + 'remove all listeners with no arguments': function () { + var event = new io.EventEmitter; + function empty () { } + + event.on('test', empty); + event.on('test:more', empty); + event.removeAllListeners(); + + event.listeners('test').should().eql([]); + event.listeners('test:more').should().eql([]); + }, + + 'remove listeners functions': function () { + var event = new io.EventEmitter + , calls = 0; + + function one () { ++calls } + function two () { ++calls } + function three () { ++calls } + + event.on('one', one); + event.removeListener('one', one); + event.listeners('one').should().eql([]); + + event.on('two', two); + event.removeListener('two', one); + event.listeners('two').should().eql([two]); + + event.on('three', three); + event.on('three', two); + event.removeListener('three', three); + event.listeners('three').should().eql([two]); + }, + + 'number of arguments': function () { + var event = new io.EventEmitter + , number = []; + + event.on('test', function () { + number.push(arguments.length); + }); + + event.emit('test'); + event.emit('test', null); + event.emit('test', null, null); + event.emit('test', null, null, null); + event.emit('test', null, null, null, null); + event.emit('test', null, null, null, null, null); + + [0, 1, 2, 3, 4, 5].should().eql(number); + }, + + 'once': function () { + var event = new io.EventEmitter + , calls = 0; + + event.once('test', function (a, b) { + ++calls; + }); + + event.emit('test', 'a', 'b'); + event.emit('test', 'a', 'b'); + event.emit('test', 'a', 'b'); + + function removed () { + should().fail('not removed'); + }; + + event.once('test:removed', removed); + event.removeListener('test:removed', removed); + event.emit('test:removed'); + + calls.should().eql(1); + } + + }; + +})( + 'undefined' == typeof module ? module = {} : module + , 'undefined' == typeof io ? require('socket.io-client') : io + , 'undefined' == typeof should || !should.fail ? require('should') : should +); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/io.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/io.test.js new file mode 100644 index 00000000..d9f0b09e --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/io.test.js @@ -0,0 +1,31 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +(function (module, io, should) { + + module.exports = { + + 'client version number': function () { + io.version.should().match(/([0-9]+)\.([0-9]+)\.([0-9]+)/); + }, + + 'socket.io protocol version': function () { + io.protocol.should().be.a('number'); + io.protocol.toString().should().match(/^\d+$/); + }, + + 'socket.io available transports': function () { + (io.transports.length > 0).should().be_true; + } + + }; + +})( + 'undefined' == typeof module ? module = {} : module + , 'undefined' == typeof io ? require('socket.io-client') : io + , 'undefined' == typeof should ? require('should') : should +); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/node/builder.common.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/node/builder.common.js new file mode 100644 index 00000000..fa8d46ed --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/node/builder.common.js @@ -0,0 +1,102 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +var vm = require('vm') + , should = require('should'); + +/** + * Generates evn variables for the vm so we can `emulate` a browser. + * @returns {Object} evn variables + */ + +exports.env = function env () { + var details = { + location: { + port: 8080 + , host: 'www.example.org' + , hostname: 'www.example.org' + , href: 'http://www.example.org/example/' + , pathname: '/example/' + , protocol: 'http:' + , search: '' + , hash: '' + } + , console: { + log: function(){}, + info: function(){}, + warn: function(){}, + error: function(){} + } + , navigator: { + userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_7) AppleWebKit' + + '/534.27 (KHTML, like Gecko) Chrome/12.0.716.0 Safari/534.27' + , appName: 'socket.io' + , platform: process.platform + , appVersion: process.version + , } + , name: 'socket.io' + , innerWidth: 1024 + , innerHeight: 768 + , length: 1 + , outerWidth: 1024 + , outerHeight: 768 + , pageXOffset: 0 + , pageYOffset: 0 + , screenX: 0 + , screenY: 0 + , screenLeft: 0 + , screenTop: 0 + , scrollX: 0 + , scrollY: 0 + , scrollTop: 0 + , scrollLeft: 0 + , screen: { + width: 0 + , height: 0 + } + }; + + // circular references + details.window = details.self = details.contentWindow = details; + + // callable methods + details.Image = details.scrollTo = details.scrollBy = details.scroll = + details.resizeTo = details.resizeBy = details.prompt = details.print = + details.open = details.moveTo = details.moveBy = details.focus = + details.createPopup = details.confirm = details.close = details.blur = + details.alert = details.clearTimeout = details.clearInterval = + details.setInterval = details.setTimeout = details.XMLHttpRequest = + details.getComputedStyle = details.trigger = details.dispatchEvent = + details.removeEventListener = details.addEventListener = function(){}; + + // frames + details.frames = [details]; + + // document + details.document = details; + details.document.domain = details.location.href; + + return details; +}; + +/** + * Executes a script in a browser like env and returns + * the result + * + * @param {String} contents The script content + * @returns {Object} The evaluated script. + */ + +exports.execute = function execute (contents) { + var env = exports.env() + , script = vm.createScript(contents); + + // run the script with `browser like` globals + script.runInNewContext(env); + + return env; +}; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/node/builder.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/node/builder.test.js new file mode 100644 index 00000000..989e2bc5 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/node/builder.test.js @@ -0,0 +1,131 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Test dependencies. + */ + +var builder = require('../../bin/builder') + , common = require('./builder.common') + , should = require('should'); + +/** + * Tests. + */ + +module.exports = { + + 'version number': function () { + builder.version.should().match(/([0-9]+)\.([0-9]+)\.([0-9]+)/); + builder.version.should().equal(require('../../lib/io').version); + }, + + 'production build LOC': function () { + builder(function (err, result) { + should.strictEqual(err, null) + + var lines = result.split('\n'); + lines.length.should().be.below(5); + lines[0].should().match(/production/gi); + Buffer.byteLength(result).should().be.below(43000); + }); + }, + + 'development build LOC': function () { + builder({ minify: false }, function (err, result) { + should.strictEqual(err, null) + + var lines = result.split('\n'); + lines.length.should().be.above(5); + lines[0].should().match(/development/gi); + Buffer.byteLength(result).should().be.above(35000); + }); + }, + + 'default builds': function () { + builder(function (err, result) { + should.strictEqual(err, null); + + var io = common.execute(result).io + , transports = Object.keys(io.Transport) + , defaults = Object.keys(builder.transports); + + /* XHR transport is private, but still available */ + transports.length.should().be.equal(defaults.length + 1); + + defaults.forEach(function (transport) { + transports.indexOf(transport).should().be.above(-1); + }) + }); + }, + + 'custom build': function () { + builder(['websocket'], function (err, result) { + should.strictEqual(err, null); + + var io = common.execute(result).io + , transports = Object.keys(io.Transport); + + transports.should().have.length(1); + transports[0].should().eql('websocket'); + }); + }, + + 'custom code': function () { + var custom = 'var hello = "world";'; + builder({ custom: [custom], minify: false }, function (err, result) { + should.strictEqual(err, null); + + result.should().include.string(custom); + }); + }, + + 'node if': function () { + var custom = '// if node \nvar hello = "world";\n' + + '// end node\nvar pew = "pew";'; + + builder({ custom: [custom], minify: false }, function (err, result) { + should.strictEqual(err, null); + + result.should().not.include.string(custom); + result.should().not.include.string('// if node'); + result.should().not.include.string('// end node'); + result.should().not.include.string('"world"'); + + result.should().include.string('var pew = "pew"'); + }); + }, + + 'preserve the encoding during minification': function () { + builder(function (err, result) { + should.strictEqual(err, null); + + result.should().match(/(\\ufffd)/g); + }) + }, + + 'globals': function () { + builder(function (err, result) { + should.strictEqual(err, null); + + var io = common.execute(result) + , env = common.env() + , allowed = ['io', 'swfobject', 'WEB_SOCKET_DISABLE_AUTO_INITIALIZATION']; + + Array.prototype.push.apply(allowed, Object.keys(env)); + + Object.keys(io).forEach(function (global) { + var index = allowed.indexOf(global); + + // the global is not allowed! + if (!~index) { + throw new Error('Global leak: ' + global); + } + }); + }) + } + +}; diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/parser.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/parser.test.js new file mode 100644 index 00000000..0022afb2 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/parser.test.js @@ -0,0 +1,360 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +(function (module, io, should) { + + var parser = io.parser; + + module.exports = { + + 'decoding error packet': function () { + parser.decodePacket('7:::').should().eql({ + type: 'error' + , reason: '' + , advice: '' + , endpoint: '' + }); + }, + + 'decoding error packet with reason': function () { + parser.decodePacket('7:::0').should().eql({ + type: 'error' + , reason: 'transport not supported' + , advice: '' + , endpoint: '' + }); + }, + + 'decoding error packet with reason and advice': function () { + parser.decodePacket('7:::2+0').should().eql({ + type: 'error' + , reason: 'unauthorized' + , advice: 'reconnect' + , endpoint: '' + }); + }, + + 'decoding error packet with endpoint': function () { + parser.decodePacket('7::/woot').should().eql({ + type: 'error' + , reason: '' + , advice: '' + , endpoint: '/woot' + }); + }, + + 'decoding ack packet': function () { + parser.decodePacket('6:::140').should().eql({ + type: 'ack' + , ackId: '140' + , endpoint: '' + , args: [] + }); + }, + + 'decoding ack packet with args': function () { + parser.decodePacket('6:::12+["woot","wa"]').should().eql({ + type: 'ack' + , ackId: '12' + , endpoint: '' + , args: ['woot', 'wa'] + }); + }, + + 'decoding ack packet with bad json': function () { + var thrown = false; + + try { + parser.decodePacket('6:::1+{"++]').should().eql({ + type: 'ack' + , ackId: '1' + , endpoint: '' + , args: [] + }); + } catch (e) { + thrown = true; + } + + thrown.should().be_false; + }, + + 'decoding json packet': function () { + parser.decodePacket('4:::"2"').should().eql({ + type: 'json' + , endpoint: '' + , data: '2' + }); + }, + + 'decoding json packet with message id and ack data': function () { + parser.decodePacket('4:1+::{"a":"b"}').should().eql({ + type: 'json' + , id: 1 + , ack: 'data' + , endpoint: '' + , data: { a: 'b' } + }); + }, + + 'decoding an event packet': function () { + parser.decodePacket('5:::{"name":"woot"}').should().eql({ + type: 'event' + , name: 'woot' + , endpoint: '' + , args: [] + }); + }, + + 'decoding an event packet with message id and ack': function () { + parser.decodePacket('5:1+::{"name":"tobi"}').should().eql({ + type: 'event' + , id: 1 + , ack: 'data' + , endpoint: '' + , name: 'tobi' + , args: [] + }); + }, + + 'decoding an event packet with data': function () { + parser.decodePacket('5:::{"name":"edwald","args":[{"a": "b"},2,"3"]}') + .should().eql({ + type: 'event' + , name: 'edwald' + , endpoint: '' + , args: [{a: 'b'}, 2, '3'] + }); + }, + + 'decoding a message packet': function () { + parser.decodePacket('3:::woot').should().eql({ + type: 'message' + , endpoint: '' + , data: 'woot' + }); + }, + + 'decoding a message packet with id and endpoint': function () { + parser.decodePacket('3:5:/tobi').should().eql({ + type: 'message' + , id: 5 + , ack: true + , endpoint: '/tobi' + , data: '' + }); + }, + + 'decoding a heartbeat packet': function () { + parser.decodePacket('2:::').should().eql({ + type: 'heartbeat' + , endpoint: '' + }); + }, + + 'decoding a connection packet': function () { + parser.decodePacket('1::/tobi').should().eql({ + type: 'connect' + , endpoint: '/tobi' + , qs: '' + }); + }, + + 'decoding a connection packet with query string': function () { + parser.decodePacket('1::/test:?test=1').should().eql({ + type: 'connect' + , endpoint: '/test' + , qs: '?test=1' + }); + }, + + 'decoding a disconnection packet': function () { + parser.decodePacket('0::/woot').should().eql({ + type: 'disconnect' + , endpoint: '/woot' + }); + }, + + 'encoding error packet': function () { + parser.encodePacket({ + type: 'error' + , reason: '' + , advice: '' + , endpoint: '' + }).should().eql('7::'); + }, + + 'encoding error packet with reason': function () { + parser.encodePacket({ + type: 'error' + , reason: 'transport not supported' + , advice: '' + , endpoint: '' + }).should().eql('7:::0'); + }, + + 'encoding error packet with reason and advice': function () { + parser.encodePacket({ + type: 'error' + , reason: 'unauthorized' + , advice: 'reconnect' + , endpoint: '' + }).should().eql('7:::2+0'); + }, + + 'encoding error packet with endpoint': function () { + parser.encodePacket({ + type: 'error' + , reason: '' + , advice: '' + , endpoint: '/woot' + }).should().eql('7::/woot'); + }, + + 'encoding ack packet': function () { + parser.encodePacket({ + type: 'ack' + , ackId: '140' + , endpoint: '' + , args: [] + }).should().eql('6:::140'); + }, + + 'encoding ack packet with args': function () { + parser.encodePacket({ + type: 'ack' + , ackId: '12' + , endpoint: '' + , args: ['woot', 'wa'] + }).should().eql('6:::12+["woot","wa"]'); + }, + + 'encoding json packet': function () { + parser.encodePacket({ + type: 'json' + , endpoint: '' + , data: '2' + }).should().eql('4:::"2"'); + }, + + 'encoding json packet with message id and ack data': function () { + parser.encodePacket({ + type: 'json' + , id: 1 + , ack: 'data' + , endpoint: '' + , data: { a: 'b' } + }).should().eql('4:1+::{"a":"b"}'); + }, + + 'encoding an event packet': function () { + parser.encodePacket({ + type: 'event' + , name: 'woot' + , endpoint: '' + , args: [] + }).should().eql('5:::{"name":"woot"}'); + }, + + 'encoding an event packet with message id and ack': function () { + parser.encodePacket({ + type: 'event' + , id: 1 + , ack: 'data' + , endpoint: '' + , name: 'tobi' + , args: [] + }).should().eql('5:1+::{"name":"tobi"}'); + }, + + 'encoding an event packet with data': function () { + parser.encodePacket({ + type: 'event' + , name: 'edwald' + , endpoint: '' + , args: [{a: 'b'}, 2, '3'] + }).should().eql('5:::{"name":"edwald","args":[{"a":"b"},2,"3"]}'); + }, + + 'encoding a message packet': function () { + parser.encodePacket({ + type: 'message' + , endpoint: '' + , data: 'woot' + }).should().eql('3:::woot'); + }, + + 'encoding a message packet with id and endpoint': function () { + parser.encodePacket({ + type: 'message' + , id: 5 + , ack: true + , endpoint: '/tobi' + , data: '' + }).should().eql('3:5:/tobi'); + }, + + 'encoding a heartbeat packet': function () { + parser.encodePacket({ + type: 'heartbeat' + , endpoint: '' + }).should().eql('2::'); + }, + + 'encoding a connection packet': function () { + parser.encodePacket({ + type: 'connect' + , endpoint: '/tobi' + , qs: '' + }).should().eql('1::/tobi'); + }, + + 'encoding a connection packet with query string': function () { + parser.encodePacket({ + type: 'connect' + , endpoint: '/test' + , qs: '?test=1' + }).should().eql('1::/test:?test=1'); + }, + + 'encoding a disconnection packet': function () { + parser.encodePacket({ + type: 'disconnect' + , endpoint: '/woot' + }).should().eql('0::/woot'); + }, + + 'test decoding a payload': function () { + parser.decodePayload('\ufffd5\ufffd3:::5\ufffd7\ufffd3:::53d' + + '\ufffd3\ufffd0::').should().eql([ + { type: 'message', data: '5', endpoint: '' } + , { type: 'message', data: '53d', endpoint: '' } + , { type: 'disconnect', endpoint: '' } + ]); + }, + + 'test encoding a payload': function () { + parser.encodePayload([ + parser.encodePacket({ type: 'message', data: '5', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: '53d', endpoint: '' }) + ]).should().eql('\ufffd5\ufffd3:::5\ufffd7\ufffd3:::53d') + }, + + 'test decoding newline': function () { + parser.decodePacket('3:::\n').should().eql({ + type: 'message' + , endpoint: '' + , data: '\n' + }); + } + + }; + +})( + 'undefined' == typeof module ? module = {} : module + , 'undefined' == typeof io ? require('socket.io-client') : io + , 'undefined' == typeof should ? require('should') : should +); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/socket.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/socket.test.js new file mode 100644 index 00000000..eae49564 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/socket.test.js @@ -0,0 +1,422 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +(function (module, io, should) { + + if ('object' == typeof global) { + return module.exports = { '': function () {} }; + } + + module.exports = { + + 'test connecting the socket and disconnecting': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('connect', function () { + socket.disconnect(); + next(); + }); + }, + + 'test receiving messages': function (next) { + var socket = create() + , connected = false + , messages = 0; + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('connect', function () { + connected = true; + }); + + socket.on('message', function (i) { + String(++messages).should().equal(i); + }); + + socket.on('disconnect', function (reason) { + connected.should().be_true; + messages.should().equal(3); + reason.should().eql('booted'); + next(); + }); + }, + + 'test sending messages': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('connect', function () { + socket.send('echo'); + + socket.on('message', function (msg) { + msg.should().equal('echo'); + socket.disconnect(); + next(); + }); + }); + }, + + 'test manual buffer flushing': function (next) { + var socket = create(); + + socket.socket.options['manualFlush'] = true; + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('connect', function () { + socket.socket.connected = false; + socket.send('buffered'); + socket.socket.onConnect(); + socket.socket.flushBuffer(); + + socket.on('message', function (msg) { + msg.should().equal('buffered'); + socket.disconnect(); + next(); + }); + }); + }, + + 'test automatic buffer flushing': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('connect', function () { + socket.socket.connected = false; + socket.send('buffered'); + socket.socket.onConnect(); + + socket.on('message', function (msg) { + msg.should().equal('buffered'); + socket.disconnect(); + next(); + }); + }); + }, + + 'test acks sent from client': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('connect', function () { + socket.on('message', function (msg) { + if ('tobi 2' == msg) { + socket.disconnect(); + next(); + } + }); + }); + }, + + 'test acks sent from server': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('connect', function () { + socket.send('ooo', function () { + socket.disconnect(); + next(); + }); + }); + }, + + 'test connecting to namespaces': function (next) { + var io = create() + , socket = io.socket + , namespaces = 2 + , connect = 0; + + function finish () { + socket.of('').disconnect(); + connect.should().equal(3); + next(); + } + + socket.on('connect', function(){ + connect++; + }); + + socket.of('/woot').on('connect', function () { + connect++; + }).on('message', function (msg) { + msg.should().equal('connected to woot'); + --namespaces || finish(); + }).on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.of('/chat').on('connect', function () { + connect++; + }).on('message', function (msg) { + msg.should().equal('connected to chat'); + --namespaces || finish(); + }).on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + }, + + 'test disconnecting from namespaces': function (next) { + var socket = create().socket + , namespaces = 2 + , disconnections = 0; + + function finish () { + socket.of('').disconnect(); + next(); + }; + + socket.of('/a').on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.of('/a').on('connect', function () { + socket.of('/a').disconnect(); + }); + + socket.of('/a').on('disconnect', function () { + --namespaces || finish(); + }); + + socket.of('/b').on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.of('/b').on('connect', function () { + socket.of('/b').disconnect(); + }); + + socket.of('/b').on('disconnect', function () { + --namespaces || finish(); + }); + }, + + 'test authorizing for namespaces': function (next) { + var socket = create().socket + + function finish () { + socket.of('').disconnect(); + next(); + }; + + socket.of('/a') + .on('connect_failed', function (msg) { + next(); + }) + .on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + }, + + 'test sending json from server': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('message', function (msg) { + msg.should().eql(3141592); + socket.disconnect(); + next(); + }); + }, + + 'test sending json from client': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.json.send([1, 2, 3]); + socket.on('message', function (msg) { + msg.should().equal('echo'); + socket.disconnect(); + next(); + }); + }, + + 'test emitting an event from server': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('woot', function () { + socket.disconnect(); + next(); + }); + }, + + 'test emitting an event to server': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.emit('woot'); + socket.on('echo', function () { + socket.disconnect(); + next(); + }) + }, + + 'test emitting multiple events at once to the server': function (next) { + var socket = create(); + + socket.on('connect', function () { + socket.emit('print', 'foo'); + socket.emit('print', 'bar'); + }); + + socket.on('done', function () { + socket.disconnect(); + next(); + }); + }, + + 'test emitting an event from server and sending back data': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('woot', function (a, fn) { + a.should().eql(1); + fn('test'); + + socket.on('done', function () { + socket.disconnect(); + next(); + }); + }); + }, + + 'test emitting an event to server and sending back data': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.emit('tobi', 1, 2, function (a) { + a.should().eql({ hello: 'world' }); + socket.disconnect(); + next(); + }); + }, + + 'test encoding a payload': function (next) { + var socket = create('/woot'); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('connect', function () { + socket.socket.setBuffer(true); + socket.send('ñ'); + socket.send('ñ'); + socket.send('ñ'); + socket.send('ñ'); + socket.socket.setBuffer(false); + }); + + socket.on('done', function () { + socket.disconnect(); + next(); + }); + }, + + 'test sending query strings to the server': function (next) { + var socket = create('?foo=bar'); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.on('message', function (data) { + data.query.foo.should().eql('bar'); + + socket.disconnect(); + next(); + }); + }, + + 'test sending newline': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.send('\n'); + + socket.on('done', function () { + socket.disconnect(); + next(); + }); + }, + + 'test sending unicode': function (next) { + var socket = create(); + + socket.on('error', function (msg) { + throw new Error(msg || 'Received an error'); + }); + + socket.json.send({ test: "☃" }); + + socket.on('done', function () { + socket.disconnect(); + next(); + }); + }, + + 'test webworker connection': function (next) { + if (!window.Worker) { + return next(); + } + + var worker = new Worker('/test/worker.js'); + worker.postMessage(uri()); + worker.onmessage = function (ev) { + if ('done!' == ev.data) return next(); + throw new Error('Unexpected message: ' + ev.data); + } + } + + }; + +})( + 'undefined' == typeof module ? module = {} : module + , 'undefined' == typeof io ? require('socket.io-client') : io + , 'undefined' == typeof should ? require('should-browser') : should +); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/util.test.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/util.test.js new file mode 100644 index 00000000..30db5a63 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/util.test.js @@ -0,0 +1,156 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +(function (module, io, should) { + + module.exports = { + + 'parse uri': function () { + var http = io.util.parseUri('http://google.com') + , https = io.util.parseUri('https://www.google.com:80') + , query = io.util.parseUri('google.com:8080/foo/bar?foo=bar'); + + http.protocol.should().eql('http'); + http.port.should().eql(''); + http.host.should().eql('google.com'); + https.protocol.should().eql('https'); + https.port.should().eql('80'); + https.host.should().eql('www.google.com'); + query.port.should().eql('8080'); + query.query.should().eql('foo=bar'); + query.path.should().eql('/foo/bar'); + query.relative.should().eql('/foo/bar?foo=bar'); + }, + + 'unique uri': function () { + var protocol = io.util.parseUri('http://google.com') + , noprotocol = io.util.parseUri('google.com') + , https = io.util.parseUri('https://google.com') + , path = io.util.parseUri('https://google.com/google.com/com/?foo=bar'); + + if ('object' == typeof window) { + io.util.uniqueUri(protocol).should().eql('http://google.com:3000'); + io.util.uniqueUri(noprotocol).should().eql('http://google.com:3000'); + } else { + io.util.uniqueUri(protocol).should().eql('http://google.com:80'); + io.util.uniqueUri(noprotocol).should().eql('http://google.com:80'); + } + + io.util.uniqueUri(https).should().eql('https://google.com:443'); + io.util.uniqueUri(path).should().eql('https://google.com:443'); + }, + + 'chunk query string': function () { + io.util.chunkQuery('foo=bar').should().be.a('object'); + io.util.chunkQuery('foo=bar').foo.should().eql('bar'); + }, + + 'merge query strings': function () { + var base = io.util.query('foo=bar', 'foo=baz') + , add = io.util.query('foo=bar', 'bar=foo') + + base.should().eql('?foo=baz'); + add.should().eql('?foo=bar&bar=foo'); + + io.util.query('','').should().eql(''); + io.util.query('foo=bar', '').should().eql('?foo=bar'); + io.util.query('', 'foo=bar').should().eql('?foo=bar'); + }, + + 'request': function () { + var type = typeof io.util.request(); + type.should().eql('object'); + }, + + 'is array': function () { + io.util.isArray([]).should().be_true; + io.util.isArray({}).should().be_false; + io.util.isArray('str').should().be_false; + io.util.isArray(new Date).should().be_false; + io.util.isArray(true).should().be_false; + io.util.isArray(arguments).should().be_false; + }, + + 'merge, deep merge': function () { + var start = { + foo: 'bar' + , bar: 'baz' + } + , duplicate = { + foo: 'foo' + , bar: 'bar' + } + , extra = { + ping: 'pong' + } + , deep = { + level1:{ + foo: 'bar' + , level2: { + foo: 'bar' + , level3:{ + foo: 'bar' + , rescursive: deep + } + } + } + } + // same structure, but changed names + , deeper = { + foo: 'bar' + , level1:{ + foo: 'baz' + , level2: { + foo: 'foo' + , level3:{ + foo: 'pewpew' + , rescursive: deep + } + } + } + }; + + io.util.merge(start, duplicate); + + start.foo.should().eql('foo'); + start.bar.should().eql('bar'); + + io.util.merge(start, extra); + start.ping.should().eql('pong'); + start.foo.should().eql('foo'); + + io.util.merge(deep, deeper); + + deep.foo.should().eql('bar'); + deep.level1.foo.should().eql('baz'); + deep.level1.level2.foo.should().eql('foo'); + deep.level1.level2.level3.foo.should().eql('pewpew'); + }, + + 'defer': function (next) { + var now = +new Date; + + io.util.defer(function () { + ((new Date - now) >= ( io.util.webkit ? 100 : 0 )).should().be_true(); + next(); + }) + }, + + 'indexOf': function () { + var data = ['socket', 2, 3, 4, 'socket', 5, 6, 7, 'io']; + io.util.indexOf(data, 'socket', 1).should().eql(4); + io.util.indexOf(data, 'socket').should().eql(0); + io.util.indexOf(data, 'waffles').should().eql(-1); + } + + }; + +})( + 'undefined' == typeof module ? module = {} : module + , 'undefined' == typeof io ? require('socket.io-client') : io + , 'undefined' == typeof should ? require('should') : should +); diff --git a/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/worker.js b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/worker.js new file mode 100644 index 00000000..c5426326 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/test/worker.js @@ -0,0 +1,20 @@ +importScripts('/socket.io/socket.io.js'); + +self.onmessage = function (ev) { + var url = ev.data + , socket = io.connect(url); + + socket.on('done', function () { + self.postMessage('done!'); + }); + + socket.on('connect_failed', function () { + self.postMessage('connect failed'); + }); + + socket.on('error', function () { + self.postMessage('error'); + }); + + socket.send('woot'); +} diff --git a/node_modules/karma/node_modules/socket.io/package.json b/node_modules/karma/node_modules/socket.io/package.json new file mode 100644 index 00000000..17428b02 --- /dev/null +++ b/node_modules/karma/node_modules/socket.io/package.json @@ -0,0 +1,70 @@ +{ + "name": "socket.io", + "version": "0.9.16", + "description": "Real-time apps made cross-browser & easy with a WebSocket-like API", + "homepage": "http://socket.io", + "keywords": [ + "websocket", + "socket", + "realtime", + "socket.io", + "comet", + "ajax" + ], + "author": { + "name": "Guillermo Rauch", + "email": "guillermo@learnboost.com" + }, + "contributors": [ + { + "name": "Guillermo Rauch", + "email": "rauchg@gmail.com" + }, + { + "name": "Arnout Kazemier", + "email": "info@3rd-eden.com" + }, + { + "name": "Vladimir Dronnikov", + "email": "dronnikov@gmail.com" + }, + { + "name": "Einar Otto Stangvik", + "email": "einaros@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/LearnBoost/socket.io.git" + }, + "dependencies": { + "socket.io-client": "0.9.16", + "policyfile": "0.0.4", + "base64id": "0.1.0", + "redis": "0.7.3" + }, + "devDependencies": { + "expresso": "0.9.2", + "should": "*", + "benchmark": "0.2.2", + "microtime": "0.1.3-1", + "colors": "0.5.1" + }, + "optionalDependencies": { + "redis": "0.7.3" + }, + "main": "index", + "engines": { + "node": ">= 0.4.0" + }, + "scripts": { + "test": "make test" + }, + "readme": "# Socket.IO\n\nSocket.IO is a Node.JS project that makes WebSockets and realtime possible in\nall browsers. It also enhances WebSockets by providing built-in multiplexing,\nhorizontal scalability, automatic JSON encoding/decoding, and more.\n\n## How to Install\n\n```bash\nnpm install socket.io\n```\n\n## How to use\n\nFirst, require `socket.io`:\n\n```js\nvar io = require('socket.io');\n```\n\nNext, attach it to a HTTP/HTTPS server. If you're using the fantastic `express`\nweb framework:\n\n#### Express 3.x\n\n```js\nvar app = express()\n , server = require('http').createServer(app)\n , io = io.listen(server);\n\nserver.listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.emit('news', { hello: 'world' });\n socket.on('my other event', function (data) {\n console.log(data);\n });\n});\n```\n\n#### Express 2.x\n\n```js\nvar app = express.createServer()\n , io = io.listen(app);\n\napp.listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.emit('news', { hello: 'world' });\n socket.on('my other event', function (data) {\n console.log(data);\n });\n});\n```\n\nFinally, load it from the client side code:\n\n```html\n\n\n```\n\nFor more thorough examples, look at the `examples/` directory.\n\n## Short recipes\n\n### Sending and receiving events.\n\nSocket.IO allows you to emit and receive custom events.\nBesides `connect`, `message` and `disconnect`, you can emit custom events:\n\n```js\n// note, io.listen() will create a http server for you\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n io.sockets.emit('this', { will: 'be received by everyone' });\n\n socket.on('private message', function (from, msg) {\n console.log('I received a private message by ', from, ' saying ', msg);\n });\n\n socket.on('disconnect', function () {\n io.sockets.emit('user disconnected');\n });\n});\n```\n\n### Storing data associated to a client\n\nSometimes it's necessary to store data associated with a client that's\nnecessary for the duration of the session.\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.on('set nickname', function (name) {\n socket.set('nickname', name, function () { socket.emit('ready'); });\n });\n\n socket.on('msg', function () {\n socket.get('nickname', function (err, name) {\n console.log('Chat message by ', name);\n });\n });\n});\n```\n\n#### Client side\n\n```html\n\n```\n\n### Restricting yourself to a namespace\n\nIf you have control over all the messages and events emitted for a particular\napplication, using the default `/` namespace works.\n\nIf you want to leverage 3rd-party code, or produce code to share with others,\nsocket.io provides a way of namespacing a `socket`.\n\nThis has the benefit of `multiplexing` a single connection. Instead of\nsocket.io using two `WebSocket` connections, it'll use one.\n\nThe following example defines a socket that listens on '/chat' and one for\n'/news':\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nvar chat = io\n .of('/chat')\n .on('connection', function (socket) {\n socket.emit('a message', { that: 'only', '/chat': 'will get' });\n chat.emit('a message', { everyone: 'in', '/chat': 'will get' });\n });\n\nvar news = io\n .of('/news');\n .on('connection', function (socket) {\n socket.emit('item', { news: 'item' });\n });\n```\n\n#### Client side:\n\n```html\n\n```\n\n### Sending volatile messages.\n\nSometimes certain messages can be dropped. Let's say you have an app that\nshows realtime tweets for the keyword `bieber`. \n\nIf a certain client is not ready to receive messages (because of network slowness\nor other issues, or because he's connected through long polling and is in the\nmiddle of a request-response cycle), if he doesn't receive ALL the tweets related\nto bieber your application won't suffer.\n\nIn that case, you might want to send those messages as volatile messages.\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n var tweets = setInterval(function () {\n getBieberTweet(function (tweet) {\n socket.volatile.emit('bieber tweet', tweet);\n });\n }, 100);\n\n socket.on('disconnect', function () {\n clearInterval(tweets);\n });\n});\n```\n\n#### Client side\n\nIn the client side, messages are received the same way whether they're volatile\nor not.\n\n### Getting acknowledgements\n\nSometimes, you might want to get a callback when the client confirmed the message\nreception.\n\nTo do this, simply pass a function as the last parameter of `.send` or `.emit`.\nWhat's more, when you use `.emit`, the acknowledgement is done by you, which\nmeans you can also pass data along:\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.on('ferret', function (name, fn) {\n fn('woot');\n });\n});\n```\n\n#### Client side\n\n```html\n\n```\n\n### Broadcasting messages\n\nTo broadcast, simply add a `broadcast` flag to `emit` and `send` method calls.\nBroadcasting means sending a message to everyone else except for the socket\nthat starts it.\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.broadcast.emit('user connected');\n socket.broadcast.json.send({ a: 'message' });\n});\n```\n\n### Rooms\n\nSometimes you want to put certain sockets in the same room, so that it's easy\nto broadcast to all of them together.\n\nThink of this as built-in channels for sockets. Sockets `join` and `leave`\nrooms in each socket.\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.join('justin bieber fans');\n socket.broadcast.to('justin bieber fans').emit('new fan');\n io.sockets.in('rammstein fans').emit('new non-fan');\n});\n```\n\n### Using it just as a cross-browser WebSocket\n\nIf you just want the WebSocket semantics, you can do that too.\nSimply leverage `send` and listen on the `message` event:\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.sockets.on('connection', function (socket) {\n socket.on('message', function () { });\n socket.on('disconnect', function () { });\n});\n```\n\n#### Client side\n\n```html\n\n```\n\n### Changing configuration\n\nConfiguration in socket.io is TJ-style:\n\n#### Server side\n\n```js\nvar io = require('socket.io').listen(80);\n\nio.configure(function () {\n io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']);\n});\n\nio.configure('development', function () {\n io.set('transports', ['websocket', 'xhr-polling']);\n io.enable('log');\n});\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 Guillermo Rauch <guillermo@learnboost.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/LearnBoost/socket.io/issues" + }, + "_id": "socket.io@0.9.16", + "_from": "socket.io@~0.9.13" +} diff --git a/node_modules/karma/node_modules/useragent/.npmignore b/node_modules/karma/node_modules/useragent/.npmignore new file mode 100644 index 00000000..ad02c133 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/.npmignore @@ -0,0 +1,3 @@ +tests +benchmark +node_modules diff --git a/node_modules/karma/node_modules/useragent/.travis.yml b/node_modules/karma/node_modules/useragent/.travis.yml new file mode 100644 index 00000000..6875969f --- /dev/null +++ b/node_modules/karma/node_modules/useragent/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.7 + - 0.8 diff --git a/node_modules/karma/node_modules/useragent/CHANGELOG.md b/node_modules/karma/node_modules/useragent/CHANGELOG.md new file mode 100644 index 00000000..9262b3c7 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/CHANGELOG.md @@ -0,0 +1,63 @@ +## Version 2.0 +* __v2.0.0__ *breaking* + - Added support for Operating System version parsing + - Added support for Device parsing + - Introduced deferred OnDemand parsing for Operating and Devices + - The `Agent#toJSON` method now returns an object instread of JSON string. Use + `JSON.stringify(agent)` instead. + - Removed the fromAgent method + - semver is removed from the dependencies, if you use the useragent/features + you should add it to your own dependencies. + +* __v2.0.1__ + - Fixed broken reference to the update module. + - Updated with some new parsers. + +* __v2.0.2__ + - Use LRU-cache for the lookups so it doesn't create a memory "leak" #22 + - Updated with some new parsers. + +* __v2.0.3__ + - Updated regexp library with new parsers as Opera's latest browser which runs + WebKit was detected as Chrome Mobile. + +* __v2.0.4__ + - Added support for IE11 and PhantomJS. In addition to that when you run the + updater without the correct dependencies it will just output an error + instead of throwing an error. + +* __v2.0.5__ + - Upgraded the regular expressions to support Opera Next + +* __v2.0.6__ + - Only write the parse file when there isn't an error. #30 + - Output an error in the console when we fail to compile new parsers #30 + +## Version 1.0 +* __v1.1.0__ + - Removed the postupdate hook, it was causing to much issues #9 + +* __v1.0.6__ + - Updated the agent parser, JHint issues and leaking globals. + +* __v1.0.5__ + - Potential fix for #11 where it doesn't install the stuff in windows this also + brings a fresh update of the agents.js. + +* __v1.0.3__ + - Rewritten the `is` method so it doesn't display IE as true for firefox, chrome + etc fixes #10 and #7. + +* __v1.0.3__ + - A fix for bug #6, updated the semver dependency for browserify support. + +* __v1.0.2__ + - Don't throw errors when .parse is called without a useragent string. It now + defaults to a empty Agent instance. + +* __v1.0.1__ + - Added support for cURL, Wget and thunderbird using a custom useragent + definition file. + +* __v1.0.0__ *breaking* + - Complete rewrite of the API and major performance improvements. diff --git a/node_modules/karma/node_modules/useragent/CREDITS b/node_modules/karma/node_modules/useragent/CREDITS new file mode 100644 index 00000000..b5641547 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/CREDITS @@ -0,0 +1,16 @@ +The regex library that the useragent parser uses if from; code.google.com/p/ua-parser/ +which is released under Apache license: + +# Copyright 2009 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +#     http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/node_modules/karma/node_modules/useragent/LICENSE b/node_modules/karma/node_modules/useragent/LICENSE new file mode 100644 index 00000000..a4d6a95f --- /dev/null +++ b/node_modules/karma/node_modules/useragent/LICENSE @@ -0,0 +1,19 @@ +# MIT LICENSED Copyright (c) 2013 Arnout Kazemier (http://3rd-Eden.com) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. diff --git a/node_modules/karma/node_modules/useragent/README.md b/node_modules/karma/node_modules/useragent/README.md new file mode 100644 index 00000000..52ba4792 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/README.md @@ -0,0 +1,393 @@ +# useragent - high performance user agent parser for Node.js + +Useragent originated as port of [browserscope.org][browserscope]'s user agent +parser project also known as ua-parser. Useragent allows you to parse user agent +string with high accuracy by using hand tuned dedicated regular expressions for +browser matching. This database is needed to ensure that every browser is +correctly parsed as every browser vendor implements it's own user agent schema. +This is why regular user agent parsers have major issues because they will +most likely parse out the wrong browser name or confuse the render engine version +with the actual version of the browser. + +--- + +### Build status [![BuildStatus](https://secure.travis-ci.org/3rd-Eden/useragent.png?branch=master)](http://travis-ci.org/3rd-Eden/useragent) + +--- + +### High performance + +The module has been developed with a benchmark driven approach. It has a +pre-compiled library that contains all the Regular Expressions and uses deferred +or on demand parsing for Operating System and device information. All this +engineering effort has been worth it as [this benchmark shows][benchmark]: + +``` +Starting the benchmark, parsing 62 useragent strings per run + +Executed benchmark against node module: "useragent" +Count (61), Cycles (5), Elapsed (5.559), Hz (1141.3739447904327) + +Executed benchmark against node module: "useragent_parser" +Count (29), Cycles (3), Elapsed (5.448), Hz (545.6817291171243) + +Executed benchmark against node module: "useragent-parser" +Count (16), Cycles (4), Elapsed (5.48), Hz (304.5373431830105) + +Executed benchmark against node module: "ua-parser" +Count (54), Cycles (3), Elapsed (5.512), Hz (1018.7561434659247) + +Module: "useragent" is the user agent fastest parser. +``` + +--- + +### Installation + +Installation is done using the Node Package Manager (NPM). If you don't have +NPM installed on your system you can download it from +[npmjs.org][npm] + +``` +npm install useragent --save +``` + +The `--save` flag tells NPM to automatically add it to your `package.json` file. + +--- + +### API + + +Include the `useragent` parser in you node.js application: + +```js +var useragent = require('useragent'); +``` + +The `useragent` library allows you do use the automatically installed RegExp +library or you can fetch it live from the remote servers. So if you are +paranoid and always want your RegExp library to be up to date to match with +agent the widest range of `useragent` strings you can do: + +```js +var useragent = require('useragent'); +useragent(true); +``` + +This will async load the database from the server and compile it to a proper +JavaScript supported format. If it fails to compile or load it from the remote +location it will just fall back silently to the shipped version. If you want to +use this feature you need to add `yamlparser` and `request` to your package.json + +``` +npm install yamlparser --save +npm install request --save +``` + +#### useragent.parse(useragent string[, js useragent]); + +This is the actual user agent parser, this is where all the magic is happening. +The function accepts 2 arguments, both should be a `string`. The first argument +should the user agent string that is known on the server from the +`req.headers.useragent` header. The other argument is optional and should be +the user agent string that you see in the browser, this can be send from the +browser using a xhr request or something like this. This allows you detect if +the user is browsing the web using the `Chrome Frame` extension. + +The parser returns a Agent instance, this allows you to output user agent +information in different predefined formats. See the Agent section for more +information. + +```js +var agent = useragent.parse(req.headers['user-agent']); + +// example for parsing both the useragent header and a optional js useragent +var agent2 = useragent.parse(req.headers['user-agent'], req.query.jsuseragent); +``` + +The parse method returns a `Agent` instance which contains all details about the +user agent. See the Agent section of the API documentation for the available +methods. + +#### useragent.lookup(useragent string[, js useragent]); + +This provides the same functionality as above, but it caches the user agent +string and it's parsed result in memory to provide faster lookups in the +future. This can be handy if you expect to parse a lot of user agent strings. + +It uses the same arguments as the `useragent.parse` method and returns exactly +the same result, but it's just cached. + +```js +var agent = useragent.lookup(req.headers['user-agent']); +``` + +And this is a serious performance improvement as shown in this benchmark: + +``` +Executed benchmark against method: "useragent.parse" +Count (49), Cycles (3), Elapsed (5.534), Hz (947.6844321931629) + +Executed benchmark against method: "useragent.lookup" +Count (11758), Cycles (3), Elapsed (5.395), Hz (229352.03831239208) +``` + +#### useragent.fromJSON(obj); + +Transforms the JSON representation of a `Agent` instance back in to a working +`Agent` instance + +```js +var agent = useragent.parse(req.headers['user-agent']) + , another = useragent.fromJSON(JSON.stringify(agent)); + +console.log(agent == another); +``` + +#### useragent.is(useragent string).browsername; + +This api provides you with a quick and dirty browser lookup. The underlying +code is usually found on client side scripts so it's not the same quality as +our `useragent.parse` method but it might be needed for legacy reasons. + +`useragent.is` returns a object with potential matched browser names + +```js +useragent.is(req.headers['user-agent']).firefox // true +useragent.is(req.headers['user-agent']).safari // false +var ua = useragent.is(req.headers['user-agent']) + +// the object +{ + version: '3' + webkit: false + opera: false + ie: false + chrome: false + safari: false + mobile_safari: false + firefox: true +} +``` + +--- + +### Agents, OperatingSystem and Device instances + +Most of the methods mentioned above return a Agent instance. The Agent exposes +the parsed out information from the user agent strings. This allows us to +extend the agent with more methods that do not necessarily need to be in the +core agent instance, allowing us to expose a plugin interface for third party +developers and at the same time create a uniform interface for all versioning. + +The Agent has the following property + +- `family` The browser family, or browser name, it defaults to Other. +- `major` The major version number of the family, it defaults to 0. +- `minor` The minor version number of the family, it defaults to 0. +- `patch` The patch version number of the family, it defaults to 0. + +In addition to the properties mentioned above, it also has 2 special properties, +which are: + +- `os` OperatingSystem instance +- `device` Device instance + +When you access those 2 properties the agent will do on demand parsing of the +Operating System or/and Device information. + +The OperatingSystem has the same properties as the Agent, for the Device we +don't have any versioning information available, so only the `family` property is +set there. If we cannot find the family, they will default to `Other`. + +The following methods are available: + +#### Agent.toAgent(); + +Returns the family and version number concatinated in a nice human readable +string. + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.toAgent(); // 'Chrome 15.0.874' +``` + +#### Agent.toString(); + +Returns the results of the `Agent.toAgent()` but also adds the parsed operating +system to the string in a human readable format. + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.toString(); // 'Chrome 15.0.874 / Mac OS X 10.8.1' + +// as it's a to string method you can also concat it with another string +'your useragent is ' + agent; +// 'your useragent is Chrome 15.0.874 / Mac OS X 10.8.1' +``` +#### Agent.toVersion(); + +Returns the version of the browser in a human readable string. + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.toVersion(); // '15.0.874' +``` + +#### Agent.toJSON(); + +Generates a JSON representation of the Agent. By using the `toJSON` method we +automatically allow it to be stringified when supplying as to the +`JSON.stringify` method. + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.toJSON(); // returns an object + +JSON.stringify(agent); +``` + +#### OperatingSystem.toString(); + +Generates a stringified version of operating system; + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.os.toString(); // 'Mac OSX 10.8.1' +``` + +#### OperatingSystem.toVersion(); + +Generates a stringified version of operating system's version; + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.os.toVersion(); // '10.8.1' +``` + +#### OperatingSystem.toJSON(); + +Generates a JSON representation of the OperatingSystem. By using the `toJSON` +method we automatically allow it to be stringified when supplying as to the +`JSON.stringify` method. + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.os.toJSON(); // returns an object + +JSON.stringify(agent.os); +``` + +#### Device.toString(); + +Generates a stringified version of device; + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.device.toString(); // 'Asus A100' +``` + +#### Device.toVersion(); + +Generates a stringified version of device's version; + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.device.toVersion(); // '' , no version found but could also be '0.0.0' +``` + +#### Device.toJSON(); + +Generates a JSON representation of the Device. By using the `toJSON` method we +automatically allow it to be stringified when supplying as to the +`JSON.stringify` method. + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.device.toJSON(); // returns an object + +JSON.stringify(agent.device); +``` + +### Adding more features to the useragent + +As I wanted to keep the core of the user agent parser as clean and fast as +possible I decided to move some of the initially planned features to a new +`plugin` file. + +These extensions to the Agent prototype can be loaded by requiring the +`useragent/features` file: + +```js +var useragent = require('useragent'); +require('useragent/features'); +``` + +The initial release introduces 1 new method, satisfies, which allows you to see +if the version number of the browser satisfies a certain range. It uses the +semver library to do all the range calculations but here is a small summary of +the supported range styles: + +* `>1.2.3` Greater than a specific version. +* `<1.2.3` Less than. +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`. +* `~1.2.3` := `>=1.2.3 <1.3.0`. +* `~1.2` := `>=1.2.0 <2.0.0`. +* `~1` := `>=1.0.0 <2.0.0`. +* `1.2.x` := `>=1.2.0 <1.3.0`. +* `1.x` := `>=1.0.0 <2.0.0`. + +As it requires the `semver` module to function you need to install it +seperately: + +``` +npm install semver --save +``` + +#### Agent.satisfies('range style here'); + +Check if the agent matches the supplied range. + +```js +var agent = useragent.parse(req.headers['user-agent']); +agent.satisfies('15.x || >=19.5.0 || 25.0.0 - 17.2.3'); // true +agent.satisfies('>16.12.0'); // false +``` +--- + +### Migrations + +For small changes between version please review the [changelog][changelog]. + +#### Upgrading from 1.10 to 2.0.0 + +- `useragent.fromAgent` has been removed. +- `agent.toJSON` now returns an Object, use `JSON.stringify(agent)` for the old + behaviour. +- `agent.os` is now an `OperatingSystem` instance with version numbers. If you + still a string only representation do `agent.os.toString()`. +- `semver` has been removed from the dependencies, so if you are using the + `require('useragent/features')` you need to add it to your own dependencies + +#### Upgrading from 0.1.2 to 1.0.0 + +- `useragent.browser(ua)` has been renamed to `useragent.is(ua)`. +- `useragent.parser(ua, jsua)` has been renamed to `useragent.parse(ua, jsua)`. +- `result.pretty()` has been renamed to `result.toAgent()`. +- `result.V1` has been renamed to `result.major`. +- `result.V2` has been renamed to `result.minor`. +- `result.V3` has been renamed to `result.patch`. +- `result.prettyOS()` has been removed. +- `result.match` has been removed. + +--- + +### License + +MIT + +[browserscope]: http://www.browserscope.org/ +[benchmark]: /3rd-Eden/useragent/blob/master/benchmark/run.js +[changelog]: /3rd-Eden/useragent/blob/master/CHANGELOG.md +[npm]: http://npmjs.org diff --git a/node_modules/karma/node_modules/useragent/bin/testfiles.js b/node_modules/karma/node_modules/useragent/bin/testfiles.js new file mode 100755 index 00000000..f01a6d7a --- /dev/null +++ b/node_modules/karma/node_modules/useragent/bin/testfiles.js @@ -0,0 +1,24 @@ +#!/usr/bin/env node + +var request = require('request') + , path = require('path') + , fs = require('fs'); + +var files = { + 'pgts.yaml': 'https://raw.github.com/tobie/ua-parser/master/test_resources/pgts_browser_list.yaml' + , 'testcases.yaml': 'https://raw.github.com/tobie/ua-parser/master/test_resources/test_user_agent_parser.yaml' + , 'firefoxes.yaml': 'https://raw.github.com/tobie/ua-parser/master/test_resources/firefox_user_agent_strings.yaml' +}; + +/** + * Update the fixtures + */ + +Object.keys(files).forEach(function (key) { + request(files[key], function response (err, res, data) { + if (err || res.statusCode !== 200) return console.error('failed to update'); + + console.log('downloaded', files[key]); + fs.writeFileSync(path.join(__dirname, '..', 'tests', 'fixtures', key), data); + }); +}); diff --git a/node_modules/karma/node_modules/useragent/bin/update.js b/node_modules/karma/node_modules/useragent/bin/update.js new file mode 100755 index 00000000..28c25014 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/bin/update.js @@ -0,0 +1,17 @@ +#!/usr/bin/env node + +'use strict'; + +/** + * Update our definition file. + */ +require('../lib/update').update(function updating(err, data) { + if (err) { + console.error('Update unsuccessfull due to reasons'); + console.log(err.message); + console.log(err.stack); + + return; + } + console.log('Successfully fetched and generated new parsers from the internets.'); +}); diff --git a/node_modules/karma/node_modules/useragent/features/index.js b/node_modules/karma/node_modules/useragent/features/index.js new file mode 100644 index 00000000..5dab04aa --- /dev/null +++ b/node_modules/karma/node_modules/useragent/features/index.js @@ -0,0 +1,19 @@ +"use strict"; + +/** + * Plugin dependencies + */ +var Agent = require('../').Agent + , semver = require('semver'); + +/** + * Checks if the user agent's version can be satisfied agents the give + * ranged argument. This uses the semver libraries range construction. + * + * @param {String} ranged The range the version has to satisfie + * @returns {Boolean} + * @api public + */ +Agent.prototype.satisfies = function satisfies (range) { + return semver.satisfies(this.major + '.' + this.minor + '.' + this.patch, range); +}; diff --git a/node_modules/karma/node_modules/useragent/index.js b/node_modules/karma/node_modules/useragent/index.js new file mode 100644 index 00000000..f239a36e --- /dev/null +++ b/node_modules/karma/node_modules/useragent/index.js @@ -0,0 +1,598 @@ +'use strict'; + +/** + * This is where all the magic comes from, specially crafted for `useragent`. + */ +var regexps = require('./lib/regexps'); + +/** + * Reduce references by storing the lookups. + */ +// OperatingSystem parsers: +var osparsers = regexps.os + , osparserslength = osparsers.length; + +// UserAgent parsers: +var agentparsers = regexps.browser + , agentparserslength = agentparsers.length; + +// Device parsers: +var deviceparsers = regexps.device + , deviceparserslength = deviceparsers.length; + +/** + * The representation of a parsed user agent. + * + * @constructor + * @param {String} family The name of the browser + * @param {String} major Major version of the browser + * @param {String} minor Minor version of the browser + * @param {String} patch Patch version of the browser + * @param {String} source The actual user agent string + * @api public + */ +function Agent(family, major, minor, patch, source) { + this.family = family || 'Other'; + this.major = major || '0'; + this.minor = minor || '0'; + this.patch = patch || '0'; + this.source = source || ''; +} + +/** + * OnDemand parsing of the Operating System. + * + * @type {OperatingSystem} + * @api public + */ +Object.defineProperty(Agent.prototype, 'os', { + get: function lazyparse() { + var userAgent = this.source + , length = osparserslength + , parsers = osparsers + , i = 0 + , parser + , res; + + for (; i < length; i++) { + if (res = parsers[i][0].exec(userAgent)) { + parser = parsers[i]; + + if (parser[1]) res[1] = parser[1].replace('$1', res[1]); + break; + } + } + + return Object.defineProperty(this, 'os', { + value: !parser || !res + ? new OperatingSystem() + : new OperatingSystem( + res[1] + , parser[2] || res[2] + , parser[3] || res[3] + , parser[4] || res[4] + ) + }).os; + }, + + /** + * Bypass the OnDemand parsing and set an OperatingSystem instance. + * + * @param {OperatingSystem} os + * @api public + */ + set: function set(os) { + if (!(os instanceof OperatingSystem)) return false; + + return Object.defineProperty(this, 'os', { + value: os + }).os; + } +}); + +/** + * OnDemand parsing of the Device type. + * + * @type {Device} + * @api public + */ +Object.defineProperty(Agent.prototype, 'device', { + get: function lazyparse() { + var userAgent = this.source + , length = deviceparserslength + , parsers = deviceparsers + , i = 0 + , parser + , res; + + for (; i < length; i++) { + if (res = parsers[i][0].exec(userAgent)) { + parser = parsers[i]; + + if (parser[1]) res[1] = parser[1].replace('$1', res[1]); + break; + } + } + + return Object.defineProperty(this, 'device', { + value: !parser || !res + ? new Device() + : new Device( + res[1] + , parser[2] || res[2] + , parser[3] || res[3] + , parser[4] || res[4] + ) + }).device; + }, + + /** + * Bypass the OnDemand parsing and set an Device instance. + * + * @param {Device} device + * @api public + */ + set: function set(device) { + if (!(device instanceof Device)) return false; + + return Object.defineProperty(this, 'device', { + value: device + }).device; + } +}); +/*** Generates a string output of the parsed user agent. + * + * @returns {String} + * @api public + */ +Agent.prototype.toAgent = function toAgent() { + var output = this.family + , version = this.toVersion(); + + if (version) output += ' '+ version; + return output; +}; + +/** + * Generates a string output of the parser user agent and operating system. + * + * @returns {String} "UserAgent 0.0.0 / OS" + * @api public + */ +Agent.prototype.toString = function toString() { + var agent = this.toAgent() + , os = this.os !== 'Other' ? this.os : false; + + return agent + (os ? ' / ' + os : ''); +}; + +/** + * Outputs a compiled veersion number of the user agent. + * + * @returns {String} + * @api public + */ +Agent.prototype.toVersion = function toVersion() { + var version = ''; + + if (this.major) { + version += this.major; + + if (this.minor) { + version += '.' + this.minor; + + // Special case here, the patch can also be Alpha, Beta etc so we need + // to check if it's a string or not. + if (this.patch) { + version += (isNaN(+this.patch) ? ' ' : '.') + this.patch; + } + } + } + + return version; +}; + +/** + * Outputs a JSON string of the Agent. + * + * @returns {String} + * @api public + */ +Agent.prototype.toJSON = function toJSON() { + return { + family: this.family + , major: this.major + , minor: this.minor + , patch: this.patch + , device: this.device + , os: this.os + }; +}; + +/** + * The representation of a parsed Operating System. + * + * @constructor + * @param {String} family The name of the os + * @param {String} major Major version of the os + * @param {String} minor Minor version of the os + * @param {String} patch Patch version of the os + * @api public + */ +function OperatingSystem(family, major, minor, patch) { + this.family = family || 'Other'; + this.major = major || ''; + this.minor = minor || ''; + this.patch = patch || ''; +} + +/** + * Generates a stringified version of the Operating System. + * + * @returns {String} "Operating System 0.0.0" + * @api public + */ +OperatingSystem.prototype.toString = function toString() { + var output = this.family + , version = this.toVersion(); + + if (version) output += ' '+ version; + return output; +}; + +/** + * Generates the version of the Operating System. + * + * @returns {String} + * @api public + */ +OperatingSystem.prototype.toVersion = function toVersion() { + var version = ''; + + if (this.major) { + version += this.major; + + if (this.minor) { + version += '.' + this.minor; + + // Special case here, the patch can also be Alpha, Beta etc so we need + // to check if it's a string or not. + if (this.patch) { + version += (isNaN(+this.patch) ? ' ' : '.') + this.patch; + } + } + } + + return version; +}; + +/** + * Outputs a JSON string of the OS, values are defaulted to undefined so they + * are not outputed in the stringify. + * + * @returns {String} + * @api public + */ +OperatingSystem.prototype.toJSON = function toJSON(){ + return { + family: this.family + , major: this.major || undefined + , minor: this.minor || undefined + , patch: this.patch || undefined + }; +}; + +/** + * The representation of a parsed Device. + * + * @constructor + * @param {String} family The name of the os + * @api public + */ +function Device(family, major, minor, patch) { + this.family = family || 'Other'; + this.major = major || ''; + this.minor = minor || ''; + this.patch = patch || ''; +} + +/** + * Generates a stringified version of the Device. + * + * @returns {String} "Device 0.0.0" + * @api public + */ +Device.prototype.toString = function toString() { + var output = this.family + , version = this.toVersion(); + + if (version) output += ' '+ version; + return output; +}; + +/** + * Generates the version of the Device. + * + * @returns {String} + * @api public + */ +Device.prototype.toVersion = function toVersion() { + var version = ''; + + if (this.major) { + version += this.major; + + if (this.minor) { + version += '.' + this.minor; + + // Special case here, the patch can also be Alpha, Beta etc so we need + // to check if it's a string or not. + if (this.patch) { + version += (isNaN(+this.patch) ? ' ' : '.') + this.patch; + } + } + } + + return version; +}; + +/** + * Get string representation. + * + * @returns {String} + * @api public + */ +Device.prototype.toString = function toString() { + var output = this.family + , version = this.toVersion(); + + if (version) output += ' '+ version; + return output; +}; + +/** + * Outputs a JSON string of the Device, values are defaulted to undefined so they + * are not outputed in the stringify. + * + * @returns {String} + * @api public + */ +Device.prototype.toJSON = function toJSON() { + return { + family: this.family + , major: this.major || undefined + , minor: this.minor || undefined + , patch: this.patch || undefined + }; +}; + +/** + * Small nifty thick that allows us to download a fresh set regexs from t3h + * Int3rNetz when we want to. We will be using the compiled version by default + * but users can opt-in for updates. + * + * @param {Boolean} refresh Refresh the dataset from the remote + * @api public + */ +module.exports = function updater() { + try { + require('./lib/update').update(function updating(err, results) { + if (err) { + console.log('[useragent] Failed to update the parsed due to an error:'); + console.log('[useragent] '+ (err.message ? err.message : err)); + return; + } + + regexps = results; + + // OperatingSystem parsers: + osparsers = regexps.os; + osparserslength = osparsers.length; + + // UserAgent parsers: + agentparsers = regexps.browser; + agentparserslength = agentparsers.length; + + // Device parsers: + deviceparsers = regexps.device; + deviceparserslength = deviceparsers.length; + }); + } catch (e) { + console.error('[useragent] If you want to use automatic updating, please add:'); + console.error('[useragent] - request (npm install request --save)'); + console.error('[useragent] - yamlparser (npm install yamlparser --save)'); + console.error('[useragent] To your own package.json'); + } +}; + +// Override the exports with our newly set module.exports +exports = module.exports; + +/** + * Nao that we have setup all the different classes and configured it we can + * actually start assembling and exposing everything. + */ +exports.Device = Device; +exports.OperatingSystem = OperatingSystem; +exports.Agent = Agent; + +/** + * Parses the user agent string with the generated parsers from the + * ua-parser project on google code. + * + * @param {String} userAgent The user agent string + * @param {String} jsAgent Optional UA from js to detect chrome frame + * @returns {Agent} + * @api public + */ +exports.parse = function parse(userAgent, jsAgent) { + if (!userAgent) return new Agent(); + + var length = agentparserslength + , parsers = agentparsers + , i = 0 + , parser + , res; + + for (; i < length; i++) { + if (res = parsers[i][0].exec(userAgent)) { + parser = parsers[i]; + + if (parser[1]) res[1] = parser[1].replace('$1', res[1]); + if (!jsAgent) return new Agent( + res[1] + , parser[2] || res[2] + , parser[3] || res[3] + , parser[4] || res[4] + , userAgent + ); + + break; + } + } + + // Return early if we didn't find an match, but might still be able to parse + // the os and device, so make sure we supply it with the source + if (!parser || !res) return new Agent('', '', '', '', userAgent); + + // Detect Chrome Frame, but make sure it's enabled! So we need to check for + // the Chrome/ so we know that it's actually using Chrome under the hood. + if (jsAgent && ~jsAgent.indexOf('Chrome/') && ~userAgent.indexOf('chromeframe')) { + res[1] = 'Chrome Frame (IE '+ res[1] +'.'+ res[2] +')'; + + // Run the JavaScripted userAgent string through the parser again so we can + // update the version numbers; + parser = parse(jsAgent); + parser[2] = parser.major; + parser[3] = parser.minor; + parser[4] = parser.patch; + } + + return new Agent( + res[1] + , parser[2] || res[2] + , parser[3] || res[3] + , parser[4] || res[4] + , userAgent + ); +}; + +/** + * If you are doing a lot of lookups you might want to cache the results of the + * parsed user agent string instead, in memory. + * + * @TODO We probably want to create 2 dictionary's here 1 for the Agent + * instances and one for the userAgent instance mapping so we can re-use simular + * Agent instance and lower our memory consumption. + * + * @param {String} userAgent The user agent string + * @param {String} jsAgent Optional UA from js to detect chrome frame + * @api public + */ +var LRU = require('lru-cache')(5000); +exports.lookup = function lookup(userAgent, jsAgent) { + var key = (userAgent || '')+(jsAgent || '') + , cached = LRU.get(key); + + if (cached) return cached; + LRU.set(key, (cached = exports.parse(userAgent, jsAgent))); + + return cached; +}; + +/** + * Does a more inaccurate but more common check for useragents identification. + * The version detection is from the jQuery.com library and is licensed under + * MIT. + * + * @param {String} useragent The user agent + * @returns {Object} matches + * @api public + */ +exports.is = function is(useragent) { + var ua = (useragent || '').toLowerCase() + , details = { + chrome: false + , firefox: false + , ie: false + , mobile_safari: false + , mozilla: false + , opera: false + , safari: false + , webkit: false + , version: (ua.match(exports.is.versionRE) || [0, "0"])[1] + }; + + if (~ua.indexOf('webkit')) { + details.webkit = true; + + if (~ua.indexOf('chrome')) { + details.chrome = true; + } else if (~ua.indexOf('safari')) { + details.safari = true; + + if (~ua.indexOf('mobile') && ~ua.indexOf('apple')) { + details.mobile_safari = true; + } + } + } else if (~ua.indexOf('opera')) { + details.opera = true; + } else if (~ua.indexOf('mozilla') && !~ua.indexOf('compatible')) { + details.mozilla = true; + + if (~ua.indexOf('firefox')) details.firefox = true; + } else if (~ua.indexOf('msie')) { + details.ie = true; + } + + return details; +}; + +/** + * Parses out the version numbers. + * + * @type {RegExp} + * @api private + */ +exports.is.versionRE = /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/; + +/** + * Transform a JSON object back to a valid userAgent string + * + * @param {Object} details + * @returns {Agent} + */ +exports.fromJSON = function fromJSON(details) { + if (typeof details === 'string') details = JSON.parse(details); + + var agent = new Agent(details.family, details.major, details.minor, details.patch) + , os = details.os; + + // The device family was added in v2.0 + if ('device' in details) { + agent.device = new Device(details.device.family); + } else { + agent.device = new Device(); + } + + if ('os' in details && os) { + // In v1.1.0 we only parsed out the Operating System name, not the full + // version which we added in v2.0. To provide backwards compatible we should + // we should set the details.os as family + if (typeof os === 'string') { + agent.os = new OperatingSystem(os); + } else { + agent.os = new OperatingSystem(os.family, os.major, os.minor, os.patch); + } + } + + return agent; +}; + +/** + * Library version. + * + * @type {String} + * @api public + */ +exports.version = require('./package.json').version; diff --git a/node_modules/karma/node_modules/useragent/lib/regexps.js b/node_modules/karma/node_modules/useragent/lib/regexps.js new file mode 100644 index 00000000..fb271d4c --- /dev/null +++ b/node_modules/karma/node_modules/useragent/lib/regexps.js @@ -0,0 +1,2270 @@ +var parser; + +exports.browser = Object.create(null); + +parser = Object.create(null); +parser[0] = new RegExp("(SeaMonkey|Camino)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[0] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Pale[Mm]oon)/(\\d+)\\.(\\d+)\\.?(\\d+)?"); +parser[1] = "Pale Moon (Firefox Variant)"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[1] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Fennec)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)"); +parser[1] = "Firefox Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[2] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Fennec)/(\\d+)\\.(\\d+)(pre)"); +parser[1] = "Firefox Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[3] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Fennec)/(\\d+)\\.(\\d+)"); +parser[1] = "Firefox Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[4] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Mobile.*(Firefox)/(\\d+)\\.(\\d+)"); +parser[1] = "Firefox Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[5] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Namoroka|Shiretoko|Minefield)/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?)"); +parser[1] = "Firefox ($1)"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[6] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox)/(\\d+)\\.(\\d+)(a\\d+[a-z]*)"); +parser[1] = "Firefox Alpha"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[7] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox)/(\\d+)\\.(\\d+)(b\\d+[a-z]*)"); +parser[1] = "Firefox Beta"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[8] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox)-(?:\\d+\\.\\d+)?/(\\d+)\\.(\\d+)(a\\d+[a-z]*)"); +parser[1] = "Firefox Alpha"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[9] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox)-(?:\\d+\\.\\d+)?/(\\d+)\\.(\\d+)(b\\d+[a-z]*)"); +parser[1] = "Firefox Beta"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[10] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Namoroka|Shiretoko|Minefield)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?"); +parser[1] = "Firefox ($1)"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[11] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox).*Tablet browser (\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "MicroB"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[12] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(MozillaDeveloperPreview)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[13] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Flock)/(\\d+)\\.(\\d+)(b\\d+?)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[14] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(RockMelt)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[15] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Navigator)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Netscape"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[16] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Navigator)/(\\d+)\\.(\\d+)([ab]\\d+)"); +parser[1] = "Netscape"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[17] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Netscape6)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Netscape"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[18] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(MyIBrow)/(\\d+)\\.(\\d+)"); +parser[1] = "My Internet Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[19] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Opera Tablet).*Version/(\\d+)\\.(\\d+)(?:\\.(\\d+))?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[20] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Opera)/.+Opera Mobi.+Version/(\\d+)\\.(\\d+)"); +parser[1] = "Opera Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[21] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Opera Mobi"); +parser[1] = "Opera Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[22] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Opera Mini)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[23] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Opera Mini)/att/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[24] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Opera)/9.80.*Version/(\\d+)\\.(\\d+)(?:\\.(\\d+))?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[25] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(?:Mobile Safari).*(OPR)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Opera Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[26] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(?:Chrome).*(OPR)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Opera"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[27] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(hpw|web)OS/(\\d+)\\.(\\d+)(?:\\.(\\d+))?"); +parser[1] = "webOS Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[28] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(luakit)"); +parser[1] = "LuaKit"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[29] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Snowshoe)/(\\d+)\\.(\\d+).(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[30] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Lightning)/(\\d+)\\.(\\d+)([ab]?\\d+[a-z]*)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[31] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox)/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?) \\(Swiftfox\\)"); +parser[1] = "Swiftfox"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[32] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox)/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)? \\(Swiftfox\\)"); +parser[1] = "Swiftfox"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[33] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(rekonq)/(\\d+)\\.(\\d+)\\.?(\\d+)? Safari"); +parser[1] = "Rekonq"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[34] = parser; +parser = Object.create(null); +parser[0] = new RegExp("rekonq"); +parser[1] = "Rekonq"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[35] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(conkeror|Conkeror)/(\\d+)\\.(\\d+)\\.?(\\d+)?"); +parser[1] = "Conkeror"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[36] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(konqueror)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Konqueror"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[37] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(WeTab)-Browser"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[38] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Comodo_Dragon)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Comodo Dragon"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[39] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(YottaaMonitor|BrowserMob|HttpMonitor|YandexBot|Slurp|BingPreview|PagePeeker|ThumbShotsBot|WebThumb|URL2PNG|ZooShot|GomezA|Catchpoint bot|Willow Internet Crawler|Google SketchUp|Read%20Later)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[40] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Symphony) (\\d+).(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[41] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Minimo)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[42] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(CrMo)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Chrome Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[43] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(CriOS)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Chrome Mobile iOS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[44] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Chrome)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+) Mobile"); +parser[1] = "Chrome Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[45] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(chromeframe)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Chrome Frame"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[46] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(UCBrowser)[ /](\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "UC Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[47] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(UC Browser)[ /](\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[48] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(UC Browser|UCBrowser|UCWEB)(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "UC Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[49] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(SLP Browser)/(\\d+)\\.(\\d+)"); +parser[1] = "Tizen Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[50] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(SE 2\\.X) MetaSr (\\d+)\\.(\\d+)"); +parser[1] = "Sogou Explorer"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[51] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(baidubrowser)[/\\s](\\d+)"); +parser[1] = "Baidu Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[52] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(FlyFlow)/(\\d+)\\.(\\d+)"); +parser[1] = "Baidu Explorer"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[53] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Pingdom.com_bot_version_)(\\d+)\\.(\\d+)"); +parser[1] = "PingdomBot"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[54] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(facebookexternalhit)/(\\d+)\\.(\\d+)"); +parser[1] = "FacebookBot"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[55] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Twitterbot)/(\\d+)\\.(\\d+)"); +parser[1] = "TwitterBot"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[56] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Rackspace Monitoring)/(\\d+)\\.(\\d+)"); +parser[1] = "RackspaceBot"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[57] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(PyAMF)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[58] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(YaBrowser)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Yandex Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[59] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Chrome)/(\\d+)\\.(\\d+)\\.(\\d+).* MRCHROME"); +parser[1] = "Mail.ru Chromium Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[60] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(AOL) (\\d+)\\.(\\d+); AOLBuild (\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[61] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(AdobeAIR|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Epiphany|Shiira|Sunrise|Flock|Netscape|Lunascape|WebPilot|Vodafone|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|ThunderBrowse|Iris|UP\\.Browser|Bunjalloo|Google Earth|Raven for Mac|Openwave)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[62] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Chromium|Chrome)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[63] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|Vodafone|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|NetNewsWire|Space Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen Browser|Polaris|Abrowser|Planetweb|ICE Browser)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[64] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Chromium|Chrome)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[65] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[66] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iCab|Lunascape|Opera|Android|Jasmine|Polaris) (\\d+)\\.(\\d+)\\.?(\\d+)?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[67] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Kindle)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[68] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Donut"); +parser[1] = 0; +parser[2] = "1"; +parser[3] = "2"; +parser[4] = 0; +exports.browser[69] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Eclair"); +parser[1] = 0; +parser[2] = "2"; +parser[3] = "1"; +parser[4] = 0; +exports.browser[70] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Froyo"); +parser[1] = 0; +parser[2] = "2"; +parser[3] = "2"; +parser[4] = 0; +exports.browser[71] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Gingerbread"); +parser[1] = 0; +parser[2] = "2"; +parser[3] = "3"; +parser[4] = 0; +exports.browser[72] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Honeycomb"); +parser[1] = 0; +parser[2] = "3"; +parser[3] = 0; +parser[4] = 0; +exports.browser[73] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(IEMobile)[ /](\\d+)\\.(\\d+)"); +parser[1] = "IE Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[74] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(MSIE) (\\d+)\\.(\\d+).*XBLWP7"); +parser[1] = "IE Large Screen"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[75] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[76] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Firefox)/(\\d+)\\.(\\d+)(pre|[ab]\\d+[a-z]*)?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[77] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Obigo)InternetBrowser"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[78] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Obigo)\\-Browser"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[79] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Obigo|OBIGO)[^\\d]*(\\d+)(?:.(\\d+))?"); +parser[1] = "Obigo"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[80] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(MAXTHON|Maxthon) (\\d+)\\.(\\d+)"); +parser[1] = "Maxthon"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[81] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Maxthon|MyIE2|Uzbl|Shiira)"); +parser[1] = 0; +parser[2] = "0"; +parser[3] = 0; +parser[4] = 0; +exports.browser[82] = parser; +parser = Object.create(null); +parser[0] = new RegExp("PLAYSTATION 3.+WebKit"); +parser[1] = "NetFront NX"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[83] = parser; +parser = Object.create(null); +parser[0] = new RegExp("PLAYSTATION 3"); +parser[1] = "NetFront"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[84] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(PlayStation Portable)"); +parser[1] = "NetFront"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[85] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(PlayStation Vita)"); +parser[1] = "NetFront NX"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[86] = parser; +parser = Object.create(null); +parser[0] = new RegExp("AppleWebKit.+ (NX)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "NetFront NX"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[87] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Nintendo 3DS)"); +parser[1] = "NetFront NX"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[88] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(BrowseX) \\((\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[89] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(NCSA_Mosaic)/(\\d+)\\.(\\d+)"); +parser[1] = "NCSA Mosaic"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[90] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(POLARIS)/(\\d+)\\.(\\d+)"); +parser[1] = "Polaris"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[91] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Embider)/(\\d+)\\.(\\d+)"); +parser[1] = "Polaris"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[92] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(BonEcho)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Bon Echo"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[93] = parser; +parser = Object.create(null); +parser[0] = new RegExp("M?QQBrowser"); +parser[1] = "QQ Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[94] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPod).+Version/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Mobile Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[95] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPod).*Version/(\\d+)\\.(\\d+)"); +parser[1] = "Mobile Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[96] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPhone).*Version/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Mobile Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[97] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPhone).*Version/(\\d+)\\.(\\d+)"); +parser[1] = "Mobile Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[98] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPad).*Version/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Mobile Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[99] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPad).*Version/(\\d+)\\.(\\d+)"); +parser[1] = "Mobile Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[100] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPod|iPhone|iPad);.*CPU.*OS (\\d+)(?:_\\d+)?_(\\d+).*Mobile"); +parser[1] = "Mobile Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[101] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPod|iPhone|iPad)"); +parser[1] = "Mobile Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[102] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(AvantGo) (\\d+).(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[103] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(OneBrowser)/(\\d+).(\\d+)"); +parser[1] = "ONE Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[104] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Avant)"); +parser[1] = 0; +parser[2] = "1"; +parser[3] = 0; +parser[4] = 0; +exports.browser[105] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(QtCarBrowser)"); +parser[1] = 0; +parser[2] = "1"; +parser[3] = 0; +parser[4] = 0; +exports.browser[106] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iBrowser/Mini)(\\d+).(\\d+)"); +parser[1] = "iBrowser Mini"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[107] = parser; +parser = Object.create(null); +parser[0] = new RegExp("^(Nokia)"); +parser[1] = "Nokia Services (WAP) Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[108] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(NokiaBrowser)/(\\d+)\\.(\\d+).(\\d+)\\.(\\d+)"); +parser[1] = "Nokia Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[109] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(NokiaBrowser)/(\\d+)\\.(\\d+).(\\d+)"); +parser[1] = "Nokia Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[110] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(NokiaBrowser)/(\\d+)\\.(\\d+)"); +parser[1] = "Nokia Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[111] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(BrowserNG)/(\\d+)\\.(\\d+).(\\d+)"); +parser[1] = "Nokia Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[112] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Series60)/5\\.0"); +parser[1] = "Nokia Browser"; +parser[2] = "7"; +parser[3] = "0"; +parser[4] = 0; +exports.browser[113] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Series60)/(\\d+)\\.(\\d+)"); +parser[1] = "Nokia OSS Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[114] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(S40OviBrowser)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Ovi Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[115] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Nokia)[EN]?(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[116] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(BB10);"); +parser[1] = "BlackBerry WebKit"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[117] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(PlayBook).+RIM Tablet OS (\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "BlackBerry WebKit"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[118] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Black[bB]erry).+Version/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "BlackBerry WebKit"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[119] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Black[bB]erry)\\s?(\\d+)"); +parser[1] = "BlackBerry"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[120] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(OmniWeb)/v(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[121] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Blazer)/(\\d+)\\.(\\d+)"); +parser[1] = "Palm Blazer"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[122] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Pre)/(\\d+)\\.(\\d+)"); +parser[1] = "Palm Pre"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[123] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(ELinks)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[124] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(ELinks) \\((\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[125] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Links) \\((\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[126] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(QtWeb) Internet Browser/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[127] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Silk)/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?"); +parser[1] = "Amazon Silk"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[128] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(PhantomJS)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[129] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(AppleWebKit)/(\\d+)\\.?(\\d+)?\\+ .* Safari"); +parser[1] = "WebKit Nightly"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[130] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Version)/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari/"); +parser[1] = "Safari"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[131] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Safari)/\\d+"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[132] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(OLPC)/Update(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[133] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(OLPC)/Update()\\.(\\d+)"); +parser[1] = 0; +parser[2] = "0"; +parser[3] = 0; +parser[4] = 0; +exports.browser[134] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(SEMC\\-Browser)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[135] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Teleca)"); +parser[1] = "Teleca Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[136] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Phantom)/V(\\d+)\\.(\\d+)"); +parser[1] = "Phantom Browser"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[137] = parser; +parser = Object.create(null); +parser[0] = new RegExp("([MS]?IE) (\\d+)\\.(\\d+)"); +parser[1] = "IE"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[138] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Trident(.*)rv.(\\d+)\\.(\\d+)"); +parser[1] = "IE"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[139] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(python-requests)/(\\d+)\\.(\\d+)"); +parser[1] = "Python Requests"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[140] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Thunderbird)/(\\d+)\\.(\\d+)\\.?(\\d+)?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[141] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Wget)/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[142] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(curl)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "cURL"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.browser[143] = parser; + +exports.browser.length = 144; + +exports.device = Object.create(null); + +parser = Object.create(null); +parser[0] = new RegExp("HTC ([A-Z][a-z0-9]+) Build"); +parser[1] = "HTC $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[0] = parser; +parser = Object.create(null); +parser[0] = new RegExp("HTC ([A-Z][a-z0-9 ]+) \\d+\\.\\d+\\.\\d+\\.\\d+"); +parser[1] = "HTC $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[1] = parser; +parser = Object.create(null); +parser[0] = new RegExp("HTC_Touch_([A-Za-z0-9]+)"); +parser[1] = "HTC Touch ($1)"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[2] = parser; +parser = Object.create(null); +parser[0] = new RegExp("USCCHTC(\\d+)"); +parser[1] = "HTC $1 (US Cellular)"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[3] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Sprint APA(9292)"); +parser[1] = "HTC $1 (Sprint)"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[4] = parser; +parser = Object.create(null); +parser[0] = new RegExp("HTC ([A-Za-z0-9]+ [A-Z])"); +parser[1] = "HTC $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[5] = parser; +parser = Object.create(null); +parser[0] = new RegExp("HTC[-_/\\s]([A-Za-z0-9]+)"); +parser[1] = "HTC $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[6] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(ADR[A-Za-z0-9]+)"); +parser[1] = "HTC $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[7] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(HTC)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[8] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(QtCarBrowser)"); +parser[1] = "Tesla Model S"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[9] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(SamsungSGHi560)"); +parser[1] = "Samsung SGHi560"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[10] = parser; +parser = Object.create(null); +parser[0] = new RegExp("SonyEricsson([A-Za-z0-9]+)/"); +parser[1] = "Ericsson $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[11] = parser; +parser = Object.create(null); +parser[0] = new RegExp("PLAYSTATION 3"); +parser[1] = "PlayStation 3"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[12] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(PlayStation Portable)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[13] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(PlayStation Vita)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[14] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(KFOT Build)"); +parser[1] = "Kindle Fire"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[15] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(KFTT Build)"); +parser[1] = "Kindle Fire HD"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[16] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(KFJWI Build)"); +parser[1] = "Kindle Fire HD 8.9\" WiFi"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[17] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(KFJWA Build)"); +parser[1] = "Kindle Fire HD 8.9\" 4G"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[18] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Kindle Fire)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[19] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Kindle)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[20] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Silk)/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?"); +parser[1] = "Kindle Fire"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[21] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Android[\\- ][\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}; WOWMobile (.+) Build"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[22] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Android[\\- ][\\d]+\\.[\\d]+\\-update1; [A-Za-z]{2}\\-[A-Za-z]{2}; (.+) Build"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[23] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}; (.+) Build"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[24] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+;[A-Za-z]{2}\\-[A-Za-z]{2};(.+) Build"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[25] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Android[\\- ][\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}; (.+) Build"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[26] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; (.+) Build"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[27] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Android[\\- ][\\d]+\\.[\\d]+; (.+) Build"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[28] = parser; +parser = Object.create(null); +parser[0] = new RegExp("NokiaN([0-9]+)"); +parser[1] = "Nokia N$1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[29] = parser; +parser = Object.create(null); +parser[0] = new RegExp("NOKIA([A-Za-z0-9\\v-]+)"); +parser[1] = "Nokia $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[30] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Nokia([A-Za-z0-9\\v-]+)"); +parser[1] = "Nokia $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[31] = parser; +parser = Object.create(null); +parser[0] = new RegExp("NOKIA ([A-Za-z0-9\\-]+)"); +parser[1] = "Nokia $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[32] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Nokia ([A-Za-z0-9\\-]+)"); +parser[1] = "Nokia $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[33] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Lumia ([A-Za-z0-9\\-]+)"); +parser[1] = "Lumia $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[34] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Symbian"); +parser[1] = "Nokia"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[35] = parser; +parser = Object.create(null); +parser[0] = new RegExp("BB10; ([A-Za-z0-9\\- ]+)\\)"); +parser[1] = "BlackBerry $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[36] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(PlayBook).+RIM Tablet OS"); +parser[1] = "BlackBerry Playbook"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[37] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Black[Bb]erry ([0-9]+);"); +parser[1] = "BlackBerry $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[38] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Black[Bb]erry([0-9]+)"); +parser[1] = "BlackBerry $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[39] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Black[Bb]erry;"); +parser[1] = "BlackBerry"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[40] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Pre)/(\\d+)\\.(\\d+)"); +parser[1] = "Palm Pre"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[41] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Pixi)/(\\d+)\\.(\\d+)"); +parser[1] = "Palm Pixi"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[42] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Touch[Pp]ad)/(\\d+)\\.(\\d+)"); +parser[1] = "HP TouchPad"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[43] = parser; +parser = Object.create(null); +parser[0] = new RegExp("HPiPAQ([A-Za-z0-9]+)/(\\d+).(\\d+)"); +parser[1] = "HP iPAQ $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[44] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Palm([A-Za-z0-9]+)"); +parser[1] = "Palm $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[45] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Treo([A-Za-z0-9]+)"); +parser[1] = "Palm Treo $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[46] = parser; +parser = Object.create(null); +parser[0] = new RegExp("webOS.*(P160UNA)/(\\d+).(\\d+)"); +parser[1] = "HP Veer"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[47] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(AppleTV)"); +parser[1] = "AppleTV"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[48] = parser; +parser = Object.create(null); +parser[0] = new RegExp("AdsBot-Google-Mobile"); +parser[1] = "Spider"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[49] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Googlebot-Mobile/(\\d+).(\\d+)"); +parser[1] = "Spider"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[50] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPad) Simulator;"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[51] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPad);"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[52] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPod) touch;"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[53] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPod);"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[54] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPhone) Simulator;"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[55] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPhone);"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[56] = parser; +parser = Object.create(null); +parser[0] = new RegExp("acer_([A-Za-z0-9]+)_"); +parser[1] = "Acer $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[57] = parser; +parser = Object.create(null); +parser[0] = new RegExp("acer_([A-Za-z0-9]+)_"); +parser[1] = "Acer $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[58] = parser; +parser = Object.create(null); +parser[0] = new RegExp("ALCATEL-([A-Za-z0-9]+)"); +parser[1] = "Alcatel $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[59] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Alcatel-([A-Za-z0-9]+)"); +parser[1] = "Alcatel $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[60] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Amoi\\-([A-Za-z0-9]+)"); +parser[1] = "Amoi $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[61] = parser; +parser = Object.create(null); +parser[0] = new RegExp("AMOI\\-([A-Za-z0-9]+)"); +parser[1] = "Amoi $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[62] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Asus\\-([A-Za-z0-9]+)"); +parser[1] = "Asus $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[63] = parser; +parser = Object.create(null); +parser[0] = new RegExp("ASUS\\-([A-Za-z0-9]+)"); +parser[1] = "Asus $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[64] = parser; +parser = Object.create(null); +parser[0] = new RegExp("BIRD\\-([A-Za-z0-9]+)"); +parser[1] = "Bird $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[65] = parser; +parser = Object.create(null); +parser[0] = new RegExp("BIRD\\.([A-Za-z0-9]+)"); +parser[1] = "Bird $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[66] = parser; +parser = Object.create(null); +parser[0] = new RegExp("BIRD ([A-Za-z0-9]+)"); +parser[1] = "Bird $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[67] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Dell ([A-Za-z0-9]+)"); +parser[1] = "Dell $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[68] = parser; +parser = Object.create(null); +parser[0] = new RegExp("DoCoMo/2\\.0 ([A-Za-z0-9]+)"); +parser[1] = "DoCoMo $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[69] = parser; +parser = Object.create(null); +parser[0] = new RegExp("([A-Za-z0-9]+)_W\\;FOMA"); +parser[1] = "DoCoMo $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[70] = parser; +parser = Object.create(null); +parser[0] = new RegExp("([A-Za-z0-9]+)\\;FOMA"); +parser[1] = "DoCoMo $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[71] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Huawei([A-Za-z0-9]+)"); +parser[1] = "Huawei $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[72] = parser; +parser = Object.create(null); +parser[0] = new RegExp("HUAWEI-([A-Za-z0-9]+)"); +parser[1] = "Huawei $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[73] = parser; +parser = Object.create(null); +parser[0] = new RegExp("vodafone([A-Za-z0-9]+)"); +parser[1] = "Huawei Vodafone $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[74] = parser; +parser = Object.create(null); +parser[0] = new RegExp("i\\-mate ([A-Za-z0-9]+)"); +parser[1] = "i-mate $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[75] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Kyocera\\-([A-Za-z0-9]+)"); +parser[1] = "Kyocera $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[76] = parser; +parser = Object.create(null); +parser[0] = new RegExp("KWC\\-([A-Za-z0-9]+)"); +parser[1] = "Kyocera $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[77] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Lenovo\\-([A-Za-z0-9]+)"); +parser[1] = "Lenovo $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[78] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Lenovo_([A-Za-z0-9]+)"); +parser[1] = "Lenovo $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[79] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LG/([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[80] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LG-LG([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[81] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LGE-LG([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[82] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LGE VX([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[83] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LG ([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[84] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LGE LG\\-AX([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[85] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LG\\-([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[86] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LGE\\-([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[87] = parser; +parser = Object.create(null); +parser[0] = new RegExp("LG([A-Za-z0-9]+)"); +parser[1] = "LG $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[88] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(KIN)\\.One (\\d+)\\.(\\d+)"); +parser[1] = "Microsoft $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[89] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(KIN)\\.Two (\\d+)\\.(\\d+)"); +parser[1] = "Microsoft $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[90] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Motorola)\\-([A-Za-z0-9]+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[91] = parser; +parser = Object.create(null); +parser[0] = new RegExp("MOTO\\-([A-Za-z0-9]+)"); +parser[1] = "Motorola $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[92] = parser; +parser = Object.create(null); +parser[0] = new RegExp("MOT\\-([A-Za-z0-9]+)"); +parser[1] = "Motorola $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[93] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Nintendo WiiU)"); +parser[1] = "Nintendo Wii U"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[94] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Nintendo (DS|3DS|DSi|Wii);"); +parser[1] = "Nintendo $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[95] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Pantech([A-Za-z0-9]+)"); +parser[1] = "Pantech $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[96] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Philips([A-Za-z0-9]+)"); +parser[1] = "Philips $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[97] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Philips ([A-Za-z0-9]+)"); +parser[1] = "Philips $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[98] = parser; +parser = Object.create(null); +parser[0] = new RegExp("SAMSUNG-([A-Za-z0-9\\-]+)"); +parser[1] = "Samsung $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[99] = parser; +parser = Object.create(null); +parser[0] = new RegExp("SAMSUNG\\; ([A-Za-z0-9\\-]+)"); +parser[1] = "Samsung $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[100] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Dreamcast"); +parser[1] = "Sega Dreamcast"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[101] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Softbank/1\\.0/([A-Za-z0-9]+)"); +parser[1] = "Softbank $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[102] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Softbank/2\\.0/([A-Za-z0-9]+)"); +parser[1] = "Softbank $1"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[103] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(WebTV)/(\\d+).(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[104] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(hiptop|avantgo|plucker|xiino|blazer|elaine|up.browser|up.link|mmp|smartphone|midp|wap|vodafone|o2|pocket|mobile|pda)"); +parser[1] = "Generic Smartphone"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[105] = parser; +parser = Object.create(null); +parser[0] = new RegExp("^(1207|3gso|4thp|501i|502i|503i|504i|505i|506i|6310|6590|770s|802s|a wa|acer|acs\\-|airn|alav|asus|attw|au\\-m|aur |aus |abac|acoo|aiko|alco|alca|amoi|anex|anny|anyw|aptu|arch|argo|bell|bird|bw\\-n|bw\\-u|beck|benq|bilb|blac|c55/|cdm\\-|chtm|capi|comp|cond|craw|dall|dbte|dc\\-s|dica|ds\\-d|ds12|dait|devi|dmob|doco|dopo|el49|erk0|esl8|ez40|ez60|ez70|ezos|ezze|elai|emul|eric|ezwa|fake|fly\\-|fly_|g\\-mo|g1 u|g560|gf\\-5|grun|gene|go.w|good|grad|hcit|hd\\-m|hd\\-p|hd\\-t|hei\\-|hp i|hpip|hs\\-c|htc |htc\\-|htca|htcg)"); +parser[1] = "Generic Feature Phone"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[106] = parser; +parser = Object.create(null); +parser[0] = new RegExp("^(htcp|htcs|htct|htc_|haie|hita|huaw|hutc|i\\-20|i\\-go|i\\-ma|i230|iac|iac\\-|iac/|ig01|im1k|inno|iris|jata|java|kddi|kgt|kgt/|kpt |kwc\\-|klon|lexi|lg g|lg\\-a|lg\\-b|lg\\-c|lg\\-d|lg\\-f|lg\\-g|lg\\-k|lg\\-l|lg\\-m|lg\\-o|lg\\-p|lg\\-s|lg\\-t|lg\\-u|lg\\-w|lg/k|lg/l|lg/u|lg50|lg54|lge\\-|lge/|lynx|leno|m1\\-w|m3ga|m50/|maui|mc01|mc21|mcca|medi|meri|mio8|mioa|mo01|mo02|mode|modo|mot |mot\\-|mt50|mtp1|mtv |mate|maxo|merc|mits|mobi|motv|mozz|n100|n101|n102|n202|n203|n300|n302|n500|n502|n505|n700|n701|n710|nec\\-|nem\\-|newg|neon)"); +parser[1] = "Generic Feature Phone"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[107] = parser; +parser = Object.create(null); +parser[0] = new RegExp("^(netf|noki|nzph|o2 x|o2\\-x|opwv|owg1|opti|oran|ot\\-s|p800|pand|pg\\-1|pg\\-2|pg\\-3|pg\\-6|pg\\-8|pg\\-c|pg13|phil|pn\\-2|pt\\-g|palm|pana|pire|pock|pose|psio|qa\\-a|qc\\-2|qc\\-3|qc\\-5|qc\\-7|qc07|qc12|qc21|qc32|qc60|qci\\-|qwap|qtek|r380|r600|raks|rim9|rove|s55/|sage|sams|sc01|sch\\-|scp\\-|sdk/|se47|sec\\-|sec0|sec1|semc|sgh\\-|shar|sie\\-|sk\\-0|sl45|slid|smb3|smt5|sp01|sph\\-|spv |spv\\-|sy01|samm|sany|sava|scoo|send|siem|smar|smit|soft|sony|t\\-mo|t218|t250|t600|t610|t618|tcl\\-|tdg\\-|telm|tim\\-|ts70|tsm\\-|tsm3|tsm5|tx\\-9|tagt)"); +parser[1] = "Generic Feature Phone"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[108] = parser; +parser = Object.create(null); +parser[0] = new RegExp("^(talk|teli|topl|tosh|up.b|upg1|utst|v400|v750|veri|vk\\-v|vk40|vk50|vk52|vk53|vm40|vx98|virg|vite|voda|vulc|w3c |w3c\\-|wapj|wapp|wapu|wapm|wig |wapi|wapr|wapv|wapy|wapa|waps|wapt|winc|winw|wonu|x700|xda2|xdag|yas\\-|your|zte\\-|zeto|aste|audi|avan|blaz|brew|brvw|bumb|ccwa|cell|cldc|cmd\\-|dang|eml2|fetc|hipt|http|ibro|idea|ikom|ipaq|jbro|jemu|jigs|keji|kyoc|kyok|libw|m\\-cr|midp|mmef|moto|mwbp|mywa|newt|nok6|o2im|pant|pdxg|play|pluc|port|prox|rozo|sama|seri|smal|symb|treo|upsi|vx52|vx53|vx60|vx61|vx70|vx80|vx81|vx83|vx85|wap\\-|webc|whit|wmlb|xda\\-|xda_)"); +parser[1] = "Generic Feature Phone"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[109] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(bot|borg|google(^tv)|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|silk|snappy|speedy|spider|voila|vortex|voyager|zao|zeal|fast\\-webcrawler|converacrawler|dataparksearch|findlinks|crawler)"); +parser[1] = "Spider"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.device[110] = parser; + +exports.device.length = 111; + +exports.os = Object.create(null); + +parser = Object.create(null); +parser[0] = new RegExp("(Android) (\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[0] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android)\\-(\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[1] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Donut"); +parser[1] = 0; +parser[2] = "1"; +parser[3] = "2"; +parser[4] = 0; +exports.os[2] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Eclair"); +parser[1] = 0; +parser[2] = "2"; +parser[3] = "1"; +parser[4] = 0; +exports.os[3] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Froyo"); +parser[1] = 0; +parser[2] = "2"; +parser[3] = "2"; +parser[4] = 0; +exports.os[4] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Gingerbread"); +parser[1] = 0; +parser[2] = "2"; +parser[3] = "3"; +parser[4] = 0; +exports.os[5] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Android) Honeycomb"); +parser[1] = 0; +parser[2] = "3"; +parser[3] = 0; +parser[4] = 0; +exports.os[6] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Silk-Accelerated=[a-z]{4,5})"); +parser[1] = "Android"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[7] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows (?:NT 5\\.2|NT 5\\.1))"); +parser[1] = "Windows XP"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[8] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(XBLWP7)"); +parser[1] = "Windows Phone"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[9] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows NT 6\\.1)"); +parser[1] = "Windows 7"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[10] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows NT 6\\.0)"); +parser[1] = "Windows Vista"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[11] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Win 9x 4\\.90)"); +parser[1] = "Windows Me"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[12] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 7|Windows NT 4\\.0|Windows Vista|Windows 2000|Windows 3.1)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[13] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows NT 6\\.2; ARM;)"); +parser[1] = "Windows RT"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[14] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows NT 6\\.2)"); +parser[1] = "Windows 8"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[15] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows NT 5\\.0)"); +parser[1] = "Windows 2000"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[16] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows Phone) (\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[17] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows Phone) OS (\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[18] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows ?Mobile)"); +parser[1] = "Windows Mobile"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[19] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(WinNT4.0)"); +parser[1] = "Windows NT 4.0"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[20] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Win98)"); +parser[1] = "Windows 98"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[21] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Tizen)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[22] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Mac OS X) (\\d+)[_.](\\d+)(?:[_.](\\d+))?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[23] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Mac_PowerPC"); +parser[1] = "Mac OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[24] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(?:PPC|Intel) (Mac OS X)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[25] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(CPU OS|iPhone OS) (\\d+)_(\\d+)(?:_(\\d+))?"); +parser[1] = "iOS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[26] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPhone|iPad|iPod); Opera"); +parser[1] = "iOS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[27] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(iPhone|iPad|iPod).*Mac OS X.*Version/(\\d+)\\.(\\d+)"); +parser[1] = "iOS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[28] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(AppleTV)/(\\d+)\\.(\\d+)"); +parser[1] = "ATV OS X"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[29] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(CrOS) [a-z0-9_]+ (\\d+)\\.(\\d+)(?:\\.(\\d+))?"); +parser[1] = "Chrome OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[30] = parser; +parser = Object.create(null); +parser[0] = new RegExp("([Dd]ebian)"); +parser[1] = "Debian"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[31] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Linux Mint)(?:/(\\d+))?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[32] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Mandriva)(?: Linux)?/(?:[\\d.-]+m[a-z]{2}(\\d+).(\\d))?"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[33] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Symbian[Oo][Ss])/(\\d+)\\.(\\d+)"); +parser[1] = "Symbian OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[34] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Symbian/3).+NokiaBrowser/7\\.3"); +parser[1] = "Symbian^3 Anna"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[35] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Symbian/3).+NokiaBrowser/7\\.4"); +parser[1] = "Symbian^3 Belle"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[36] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Symbian/3)"); +parser[1] = "Symbian^3"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[37] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Series 60|SymbOS|S60)"); +parser[1] = "Symbian OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[38] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(MeeGo)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[39] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Symbian [Oo][Ss]"); +parser[1] = "Symbian OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[40] = parser; +parser = Object.create(null); +parser[0] = new RegExp("Series40;"); +parser[1] = "Nokia Series 40"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[41] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(BB10);.+Version/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "BlackBerry OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[42] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Black[Bb]erry)[0-9a-z]+/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?"); +parser[1] = "BlackBerry OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[43] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Black[Bb]erry).+Version/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?"); +parser[1] = "BlackBerry OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[44] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(RIM Tablet OS) (\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "BlackBerry Tablet OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[45] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Play[Bb]ook)"); +parser[1] = "BlackBerry Tablet OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[46] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Black[Bb]erry)"); +parser[1] = "BlackBerry OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[47] = parser; +parser = Object.create(null); +parser[0] = new RegExp("\\(Mobile;.+Firefox/\\d+\\.\\d+"); +parser[1] = "Firefox OS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[48] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(BREW)[ /](\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[49] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(BREW);"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[50] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Brew MP|BMP)[ /](\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = "Brew MP"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[51] = parser; +parser = Object.create(null); +parser[0] = new RegExp("BMP;"); +parser[1] = "Brew MP"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[52] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(GoogleTV) (\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[53] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(GoogleTV)/[\\da-z]+"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[54] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(WebTV)/(\\d+).(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[55] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(hpw|web)OS/(\\d+)\\.(\\d+)(?:\\.(\\d+))?"); +parser[1] = "webOS"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[56] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(VRE);"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[57] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Fedora|Red Hat|PCLinuxOS)/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[58] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Red Hat|Puppy|PCLinuxOS)/(\\d+)\\.(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[59] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Red Hat|Slackware)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[60] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Windows|OpenBSD|FreeBSD|NetBSD|Android|WeTab)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[61] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Ubuntu|Kubuntu|Arch Linux|CentOS|Slackware|Gentoo|openSUSE|SUSE|Red Hat|Fedora|PCLinuxOS|Gentoo|Mageia)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[62] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Linux)/(\\d+)\\.(\\d+)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[63] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Linux|BSD)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[64] = parser; +parser = Object.create(null); +parser[0] = new RegExp("SunOS"); +parser[1] = "Solaris"; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[65] = parser; +parser = Object.create(null); +parser[0] = new RegExp("(Red Hat)"); +parser[1] = 0; +parser[2] = 0; +parser[3] = 0; +parser[4] = 0; +exports.os[66] = parser; + +exports.os.length = 67; \ No newline at end of file diff --git a/node_modules/karma/node_modules/useragent/lib/update.js b/node_modules/karma/node_modules/useragent/lib/update.js new file mode 100644 index 00000000..eb05092f --- /dev/null +++ b/node_modules/karma/node_modules/useragent/lib/update.js @@ -0,0 +1,202 @@ +'use strict'; + +/** + * Build in Native modules. + */ +var path = require('path') + , fs = require('fs') + , vm = require('vm'); + +/** + * Third party modules. + */ +var request = require('request') + , yaml = require('yamlparser'); + +exports.update = function update(callback) { + // Fetch the remote resource as that is frequently updated + request(exports.remote, function downloading(err, res, remote) { + if (err) return callback(err); + if (res.statusCode !== 200) return callback(new Error('Invalid statusCode returned')); + + // Also get some local additions that are missing from the source + fs.readFile(exports.local, 'utf8', function reading(err, local) { + if (err) return callback(err); + + // Parse the contents + exports.parse([ remote, local ], function parsing(err, results, source) { + callback(err, results); + + if (source && !err) { + fs.writeFile(exports.output, source, function idk(err) { + if (err) { + console.error('Failed to save the generated file due to reasons', err); + } + }); + } + }); + }); + }); +}; + +exports.parse = function parse(sources, callback) { + var results = {}; + + var data = sources.reduce(function parser(memo, data) { + // Try to repair some of the odd structures that are in the yaml files + // before parsing it so we generate a uniform structure: + + // Normalize the Operating system versions: + data = data.replace(/os_v([1-3])_replacement/gim, function replace(match, version) { + return 'v'+ version +'_replacement'; + }); + + // Make sure that we are able to parse the yaml string + try { data = yaml.eval(data); } + catch (e) { + callback(e); + callback = null; + return memo; + } + + // merge the data with the memo; + Object.keys(data).forEach(function (key) { + var results = data[key]; + memo[key] = memo[key] || []; + + for (var i = 0, l = results.length; i < l; i++) { + memo[key].push(results[i]); + } + }); + + return memo; + }, {}); + + [ + { + resource: 'user_agent_parsers' + , replacement: 'family_replacement' + , name: 'browser' + } + , { + resource: 'device_parsers' + , replacement: 'device_replacement' + , name: 'device' + } + , { + resource: 'os_parsers' + , replacement: 'os_replacement' + , name: 'os' + } + ].forEach(function parsing(details) { + results[details.resource] = results[details.resource] || []; + + var resources = data[details.resource] + , name = details.resource.replace('_parsers', '') + , resource + , parser; + + for (var i = 0, l = resources.length; i < l; i++) { + resource = resources[i]; + + // We need to JSON stringify the data to properly add slashes escape other + // kinds of crap in the RegularExpression. If we don't do thing we get + // some illegal token warnings. + parser = 'parser = Object.create(null);\n'; + parser += 'parser[0] = new RegExp('+ JSON.stringify(resource.regex) + ');\n'; + + // Check if we have replacement for the parsed family name + if (resource[details.replacement]) { + parser += 'parser[1] = "'+ resource[details.replacement].replace('"', '\\"') +'";'; + } else { + parser += 'parser[1] = 0;'; + } + + parser += '\n'; + + if (resource.v1_replacement) { + parser += 'parser[2] = "'+ resource.v1_replacement.replace('"', '\\"') +'";'; + } else { + parser += 'parser[2] = 0;'; + } + + parser += '\n'; + + if (resource.v2_replacement) { + parser += 'parser[3] = "'+ resource.v2_replacement.replace('"', '\\"') +'";'; + } else { + parser += 'parser[3] = 0;'; + } + + parser += '\n'; + + if (resource.v3_replacement) { + parser += 'parser[4] = "'+ resource.v3_replacement.replace('"', '\\"') +'";'; + } else { + parser += 'parser[4] = 0;'; + } + + parser += '\n'; + parser += 'exports.'+ details.name +'['+ i +'] = parser;'; + results[details.resource].push(parser); + } + }); + + // Generate a correct format + exports.generate(results, callback); +}; + +exports.generate = function generate(results, callback) { + var regexps = [ + 'var parser;' + , 'exports.browser = Object.create(null);' + , results.user_agent_parsers.join('\n') + , 'exports.browser.length = '+ results.user_agent_parsers.length +';' + + , 'exports.device = Object.create(null);' + , results.device_parsers.join('\n') + , 'exports.device.length = '+ results.device_parsers.length +';' + + , 'exports.os = Object.create(null);' + , results.os_parsers.join('\n') + , 'exports.os.length = '+ results.os_parsers.length +';' + ].join('\n\n'); + + // Now that we have generated the structure for the RegExps export file we + // need to validate that we created a JavaScript compatible file, if we would + // write the file without checking it's content we could be breaking the + // module. + var sandbox = { + exports: {} // Emulate a module context, so everything is attached here + }; + + // Crossing our fingers that it worked + try { vm.runInNewContext(regexps, sandbox, 'validating.vm'); } + catch (e) { return callback(e, null, regexps); } + + callback(undefined, sandbox.exports, regexps); +}; + +/** + * The location of the ua-parser regexes yaml file. + * + * @type {String} + * @api private + */ +exports.remote = 'https://raw.github.com/tobie/ua-parser/master/regexes.yaml'; + +/** + * The location of our local regexes yaml file. + * + * @type {String} + * @api private + */ +exports.local = path.resolve(__dirname, '..', 'static', 'user_agent.after.yaml'); + +/** + * The the output location for the generated regexps file + * + * @type {String} + * @api private + */ +exports.output = path.resolve(__dirname, '..', 'lib', 'regexps.js'); diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/.npmignore b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/.npmignore new file mode 100644 index 00000000..07e6e472 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/.npmignore @@ -0,0 +1 @@ +/node_modules diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/AUTHORS b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/AUTHORS new file mode 100644 index 00000000..016d7fbe --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/AUTHORS @@ -0,0 +1,8 @@ +# Authors, sorted by whether or not they are me +Isaac Z. Schlueter +Carlos Brito Lage +Marko Mikulicic +Trent Mick +Kevin O'Hara +Marco Rogers +Jesse Dailey diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/LICENSE b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/LICENSE new file mode 100644 index 00000000..05a40109 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/README.md b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/README.md new file mode 100644 index 00000000..9aeb3164 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/README.md @@ -0,0 +1,88 @@ +# lru cache + +A cache object that deletes the least-recently-used items. + +## Usage: + +```javascript +var LRU = require("lru-cache") + , options = { max: 500 + , length: function (n) { return n * 2 } + , dispose: function (key, n) { n.close() } + , maxAge: 1000 * 60 * 60 } + , cache = LRU(options) + , otherCache = LRU(50) // sets just the max size + +cache.set("key", "value") +cache.get("key") // "value" + +cache.reset() // empty the cache +``` + +If you put more stuff in it, then items will fall out. + +If you try to put an oversized thing in it, then it'll fall out right +away. + +## Options + +* `max` The maximum size of the cache, checked by applying the length + function to all values in the cache. Not setting this is kind of + silly, since that's the whole purpose of this lib, but it defaults + to `Infinity`. +* `maxAge` Maximum age in ms. Items are not pro-actively pruned out + as they age, but if you try to get an item that is too old, it'll + drop it and return undefined instead of giving it to you. +* `length` Function that is used to calculate the length of stored + items. If you're storing strings or buffers, then you probably want + to do something like `function(n){return n.length}`. The default is + `function(n){return 1}`, which is fine if you want to store `n` + like-sized things. +* `dispose` Function that is called on items when they are dropped + from the cache. This can be handy if you want to close file + descriptors or do other cleanup tasks when items are no longer + accessible. Called with `key, value`. It's called *before* + actually removing the item from the internal cache, so if you want + to immediately put it back in, you'll have to do that in a + `nextTick` or `setTimeout` callback or it won't do anything. +* `stale` By default, if you set a `maxAge`, it'll only actually pull + stale items out of the cache when you `get(key)`. (That is, it's + not pre-emptively doing a `setTimeout` or anything.) If you set + `stale:true`, it'll return the stale value before deleting it. If + you don't set this, then it'll return `undefined` when you try to + get a stale entry, as if it had already been deleted. + +## API + +* `set(key, value)` +* `get(key) => value` + + Both of these will update the "recently used"-ness of the key. + They do what you think. + +* `del(key)` + + Deletes a key out of the cache. + +* `reset()` + + Clear the cache entirely, throwing away all values. + +* `has(key)` + + Check if a key is in the cache, without updating the recent-ness + or deleting it for being stale. + +* `forEach(function(value,key,cache), [thisp])` + + Just like `Array.prototype.forEach`. Iterates over all the keys + in the cache, in order of recent-ness. (Ie, more recently used + items are iterated over first.) + +* `keys()` + + Return an array of the keys in the cache. + +* `values()` + + Return an array of the values in the cache. diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/lib/lru-cache.js b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/lib/lru-cache.js new file mode 100644 index 00000000..4ae51ac3 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,242 @@ +;(function () { // closure for web browsers + +if (typeof module === 'object' && module.exports) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + this.LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function naiveLength () { return 1 } + +function LRUCache (options) { + if (!(this instanceof LRUCache)) { + return new LRUCache(options) + } + + var max + if (typeof options === 'number') { + max = options + options = { max: max } + } + + if (!options) options = {} + + max = options.max + + var lengthCalculator = options.length || naiveLength + + if (typeof lengthCalculator !== "function") { + lengthCalculator = naiveLength + } + + if (!max || !(typeof max === "number") || max <= 0 ) { + // a little bit silly. maybe this should throw? + max = Infinity + } + + var allowStale = options.stale || false + + var maxAge = options.maxAge || null + + var dispose = options.dispose + + var cache = Object.create(null) // hash of items by key + , lruList = Object.create(null) // list of items in order of use recency + , mru = 0 // most recently used + , lru = 0 // least recently used + , length = 0 // number of items in the list + , itemCount = 0 + + + // resize the cache when the max changes. + Object.defineProperty(this, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + max = mL + // if it gets above double max, trim right away. + // otherwise, do it whenever it's convenient. + if (length > max) trim() + } + , get : function () { return max } + , enumerable : true + }) + + // resize the cache when the lengthCalculator changes. + Object.defineProperty(this, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + lengthCalculator = naiveLength + length = itemCount + for (var key in cache) { + cache[key].length = 1 + } + } else { + lengthCalculator = lC + length = 0 + for (var key in cache) { + cache[key].length = lengthCalculator(cache[key].value) + length += cache[key].length + } + } + + if (length > max) trim() + } + , get : function () { return lengthCalculator } + , enumerable : true + }) + + Object.defineProperty(this, "length", + { get : function () { return length } + , enumerable : true + }) + + + Object.defineProperty(this, "itemCount", + { get : function () { return itemCount } + , enumerable : true + }) + + this.forEach = function (fn, thisp) { + thisp = thisp || this + var i = 0; + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + i++ + var hit = lruList[k] + fn.call(thisp, hit.value, hit.key, this) + } + } + + this.keys = function () { + var keys = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + keys[i++] = hit.key + } + return keys + } + + this.values = function () { + var values = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + values[i++] = hit.value + } + return values + } + + this.reset = function () { + if (dispose) { + for (var k in cache) { + dispose(k, cache[k].value) + } + } + cache = {} + lruList = {} + lru = 0 + mru = 0 + length = 0 + itemCount = 0 + } + + // Provided for debugging/dev purposes only. No promises whatsoever that + // this API stays stable. + this.dump = function () { + return cache + } + + this.dumpLru = function () { + return lruList + } + + this.set = function (key, value) { + if (hOP(cache, key)) { + // dispose of the old one before overwriting + if (dispose) dispose(key, cache[key].value) + if (maxAge) cache[key].now = Date.now() + cache[key].value = value + this.get(key) + return true + } + + var len = lengthCalculator(value) + var age = maxAge ? Date.now() : 0 + var hit = new Entry(key, value, mru++, len, age) + + // oversized objects fall out of cache automatically. + if (hit.length > max) { + if (dispose) dispose(key, value) + return false + } + + length += hit.length + lruList[hit.lu] = cache[key] = hit + itemCount ++ + + if (length > max) trim() + return true + } + + this.has = function (key) { + if (!hOP(cache, key)) return false + var hit = cache[key] + if (maxAge && (Date.now() - hit.now > maxAge)) { + return false + } + return true + } + + this.get = function (key) { + if (!hOP(cache, key)) return + var hit = cache[key] + if (maxAge && (Date.now() - hit.now > maxAge)) { + this.del(key) + return allowStale ? hit.value : undefined + } + shiftLU(hit) + hit.lu = mru ++ + lruList[hit.lu] = hit + return hit.value + } + + this.del = function (key) { + del(cache[key]) + } + + function trim () { + while (lru < mru && length > max) + del(lruList[lru]) + } + + function shiftLU(hit) { + delete lruList[ hit.lu ] + while (lru < mru && !lruList[lru]) lru ++ + } + + function del(hit) { + if (hit) { + if (dispose) dispose(hit.key, hit.value) + length -= hit.length + itemCount -- + delete cache[ hit.key ] + shiftLU(hit) + } + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, mru, len, age) { + this.key = key + this.value = value + this.lu = mru + this.length = len + this.now = age +} + +})() diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/package.json b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/package.json new file mode 100644 index 00000000..229a2045 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/package.json @@ -0,0 +1,63 @@ +{ + "name": "lru-cache", + "description": "A cache object that deletes the least-recently-used items.", + "version": "2.2.4", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "scripts": { + "test": "tap test --gc" + }, + "main": "lib/lru-cache.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-lru-cache.git" + }, + "devDependencies": { + "tap": "", + "weak": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" + }, + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + { + "name": "Carlos Brito Lage", + "email": "carlos@carloslage.net" + }, + { + "name": "Marko Mikulicic", + "email": "marko.mikulicic@isti.cnr.it" + }, + { + "name": "Trent Mick", + "email": "trentm@gmail.com" + }, + { + "name": "Kevin O'Hara", + "email": "kevinohara80@gmail.com" + }, + { + "name": "Marco Rogers", + "email": "marco.rogers@gmail.com" + }, + { + "name": "Jesse Dailey", + "email": "jesse.dailey@gmail.com" + } + ], + "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n , options = { max: 500\n , length: function (n) { return n * 2 }\n , dispose: function (key, n) { n.close() }\n , maxAge: 1000 * 60 * 60 }\n , cache = LRU(options)\n , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset() // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum size of the cache, checked by applying the length\n function to all values in the cache. Not setting this is kind of\n silly, since that's the whole purpose of this lib, but it defaults\n to `Infinity`.\n* `maxAge` Maximum age in ms. Items are not pro-actively pruned out\n as they age, but if you try to get an item that is too old, it'll\n drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n items. If you're storing strings or buffers, then you probably want\n to do something like `function(n){return n.length}`. The default is\n `function(n){return 1}`, which is fine if you want to store `n`\n like-sized things.\n* `dispose` Function that is called on items when they are dropped\n from the cache. This can be handy if you want to close file\n descriptors or do other cleanup tasks when items are no longer\n accessible. Called with `key, value`. It's called *before*\n actually removing the item from the internal cache, so if you want\n to immediately put it back in, you'll have to do that in a\n `nextTick` or `setTimeout` callback or it won't do anything.\n* `stale` By default, if you set a `maxAge`, it'll only actually pull\n stale items out of the cache when you `get(key)`. (That is, it's\n not pre-emptively doing a `setTimeout` or anything.) If you set\n `stale:true`, it'll return the stale value before deleting it. If\n you don't set this, then it'll return `undefined` when you try to\n get a stale entry, as if it had already been deleted.\n\n## API\n\n* `set(key, value)`\n* `get(key) => value`\n\n Both of these will update the \"recently used\"-ness of the key.\n They do what you think.\n\n* `del(key)`\n\n Deletes a key out of the cache.\n\n* `reset()`\n\n Clear the cache entirely, throwing away all values.\n\n* `has(key)`\n\n Check if a key is in the cache, without updating the recent-ness\n or deleting it for being stale.\n\n* `forEach(function(value,key,cache), [thisp])`\n\n Just like `Array.prototype.forEach`. Iterates over all the keys\n in the cache, in order of recent-ness. (Ie, more recently used\n items are iterated over first.)\n\n* `keys()`\n\n Return an array of the keys in the cache.\n\n* `values()`\n\n Return an array of the values in the cache.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-lru-cache/issues" + }, + "homepage": "https://github.com/isaacs/node-lru-cache", + "_id": "lru-cache@2.2.4", + "_from": "lru-cache@2.2.x" +} diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/s.js b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/s.js new file mode 100644 index 00000000..c2a9e548 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/s.js @@ -0,0 +1,25 @@ +var LRU = require('lru-cache'); + +var max = +process.argv[2] || 10240; +var more = 1024; + +var cache = LRU({ + max: max, maxAge: 86400e3 +}); + +// fill cache +for (var i = 0; i < max; ++i) { + cache.set(i, {}); +} + +var start = process.hrtime(); + +// adding more items +for ( ; i < max+more; ++i) { + cache.set(i, {}); +} + +var end = process.hrtime(start); +var msecs = end[0] * 1E3 + end[1] / 1E6; + +console.log('adding %d items took %d ms', more, msecs.toPrecision(5)); diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/basic.js b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/basic.js new file mode 100644 index 00000000..55d52633 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/basic.js @@ -0,0 +1,317 @@ +var test = require("tap").test + , LRU = require("../") + +test("basic", function (t) { + var cache = new LRU({max: 10}) + cache.set("key", "value") + t.equal(cache.get("key"), "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.length, 1) + t.equal(cache.max, 10) + t.end() +}) + +test("least recently set", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.get("a") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), "A") + t.end() +}) + +test("del", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.del("a") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("max", function (t) { + var cache = new LRU(3) + + // test changing the max, verify that the LRU items get dropped. + cache.max = 100 + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + + // now remove the max restriction, and try again. + cache.max = "hello" + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + // should trigger an immediate resize + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + t.end() +}) + +test("reset", function (t) { + var cache = new LRU(10) + cache.set("a", "A") + cache.set("b", "B") + cache.reset() + t.equal(cache.length, 0) + t.equal(cache.max, 10) + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.end() +}) + + +// Note: `.dump()` is a debugging tool only. No guarantees are made +// about the format/layout of the response. +test("dump", function (t) { + var cache = new LRU(10) + var d = cache.dump(); + t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache") + cache.set("a", "A") + var d = cache.dump() // { a: { key: "a", value: "A", lu: 0 } } + t.ok(d.a) + t.equal(d.a.key, "a") + t.equal(d.a.value, "A") + t.equal(d.a.lu, 0) + + cache.set("b", "B") + cache.get("b") + d = cache.dump() + t.ok(d.b) + t.equal(d.b.key, "b") + t.equal(d.b.value, "B") + t.equal(d.b.lu, 2) + + t.end() +}) + + +test("basic with weighed length", function (t) { + var cache = new LRU({ + max: 100, + length: function (item) { return item.size } + }) + cache.set("key", {val: "value", size: 50}) + t.equal(cache.get("key").val, "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.lengthCalculator(cache.get("key")), 50) + t.equal(cache.length, 50) + t.equal(cache.max, 100) + t.end() +}) + + +test("weighed length item too large", function (t) { + var cache = new LRU({ + max: 10, + length: function (item) { return item.size } + }) + t.equal(cache.max, 10) + + // should fall out immediately + cache.set("key", {val: "value", size: 50}) + + t.equal(cache.length, 0) + t.equal(cache.get("key"), undefined) + t.end() +}) + +test("least recently set with weighed length", function (t) { + var cache = new LRU({ + max:8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.set("d", "DDDD") + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("c"), "CCC") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten with weighed length", function (t) { + var cache = new LRU({ + max: 8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.get("a") + cache.get("b") + cache.set("d", "DDDD") + t.equal(cache.get("c"), undefined) + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("b"), "BB") + t.equal(cache.get("a"), "A") + t.end() +}) + +test("set returns proper booleans", function(t) { + var cache = new LRU({ + max: 5, + length: function (item) { return item.length } + }) + + t.equal(cache.set("a", "A"), true) + + // should return false for max exceeded + t.equal(cache.set("b", "donuts"), false) + + t.equal(cache.set("b", "B"), true) + t.equal(cache.set("c", "CCCC"), true) + t.end() +}) + +test("drop the old items", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + cache.set("a", "A") + + setTimeout(function () { + cache.set("b", "b") + t.equal(cache.get("a"), "A") + }, 25) + + setTimeout(function () { + cache.set("c", "C") + // timed out + t.notOk(cache.get("a")) + }, 60) + + setTimeout(function () { + t.notOk(cache.get("b")) + t.equal(cache.get("c"), "C") + }, 90) + + setTimeout(function () { + t.notOk(cache.get("c")) + t.end() + }, 155) +}) + +test("disposal function", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + dispose: function (k, n) { + disposed = n + } + }) + + cache.set(1, 1) + cache.set(2, 2) + t.equal(disposed, 1) + cache.set(3, 3) + t.equal(disposed, 2) + cache.reset() + t.equal(disposed, 3) + t.end() +}) + +test("disposal function on too big of item", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + length: function (k) { + return k.length + }, + dispose: function (k, n) { + disposed = n + } + }) + var obj = [ 1, 2 ] + + t.equal(disposed, false) + cache.set("obj", obj) + t.equal(disposed, obj) + t.end() +}) + +test("has()", function(t) { + var cache = new LRU({ + max: 1, + maxAge: 10 + }) + + cache.set('foo', 'bar') + t.equal(cache.has('foo'), true) + cache.set('blu', 'baz') + t.equal(cache.has('foo'), false) + t.equal(cache.has('blu'), true) + setTimeout(function() { + t.equal(cache.has('blu'), false) + t.end() + }, 15) +}) + +test("stale", function(t) { + var cache = new LRU({ + maxAge: 10, + stale: true + }) + + cache.set('foo', 'bar') + t.equal(cache.get('foo'), 'bar') + t.equal(cache.has('foo'), true) + setTimeout(function() { + t.equal(cache.has('foo'), false) + t.equal(cache.get('foo'), 'bar') + t.equal(cache.get('foo'), undefined) + t.end() + }, 15) +}) + +test("lru update via set", function(t) { + var cache = LRU({ max: 2 }); + + cache.set('foo', 1); + cache.set('bar', 2); + cache.del('bar'); + cache.set('baz', 3); + cache.set('qux', 4); + + t.equal(cache.get('foo'), undefined) + t.equal(cache.get('bar'), undefined) + t.equal(cache.get('baz'), 3) + t.equal(cache.get('qux'), 4) + t.end() +}) diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/foreach.js b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/foreach.js new file mode 100644 index 00000000..eefb80d9 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/foreach.js @@ -0,0 +1,52 @@ +var test = require('tap').test +var LRU = require('../') + +test('forEach', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 9 + l.forEach(function (val, key, cache) { + t.equal(cache, l) + t.equal(key, i.toString()) + t.equal(val, i.toString(2)) + i -= 1 + }) + + // get in order of most recently used + l.get(6) + l.get(8) + + var order = [ 8, 6, 9, 7, 5 ] + var i = 0 + + l.forEach(function (val, key, cache) { + var j = order[i ++] + t.equal(cache, l) + t.equal(key, j.toString()) + t.equal(val, j.toString(2)) + }) + + t.end() +}) + +test('keys() and values()', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + t.similar(l.keys(), ['9', '8', '7', '6', '5']) + t.similar(l.values(), ['1001', '1000', '111', '110', '101']) + + // get in order of most recently used + l.get(6) + l.get(8) + + t.similar(l.keys(), ['8', '6', '9', '7', '5']) + t.similar(l.values(), ['1000', '110', '1001', '111', '101']) + + t.end() +}) diff --git a/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/memory-leak.js b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/memory-leak.js new file mode 100644 index 00000000..7af45b02 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/node_modules/lru-cache/test/memory-leak.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node --expose_gc + +var weak = require('weak'); +var test = require('tap').test +var LRU = require('../') +var l = new LRU({ max: 10 }) +var refs = 0 +function X() { + refs ++ + weak(this, deref) +} + +function deref() { + refs -- +} + +test('no leaks', function (t) { + // fill up the cache + for (var i = 0; i < 100; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var start = process.memoryUsage() + + // capture the memory + var startRefs = refs + + // do it again, but more + for (var i = 0; i < 10000; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var end = process.memoryUsage() + t.equal(refs, startRefs, 'no leaky refs') + + console.error('start: %j\n' + + 'end: %j', start, end); + t.pass(); + t.end(); +}) diff --git a/node_modules/karma/node_modules/useragent/package.json b/node_modules/karma/node_modules/useragent/package.json new file mode 100644 index 00000000..9bdd8ecf --- /dev/null +++ b/node_modules/karma/node_modules/useragent/package.json @@ -0,0 +1,69 @@ +{ + "name": "useragent", + "version": "2.0.7", + "description": "Fastest, most accurate & effecient user agent string parser, uses Browserscope's research for parsing", + "author": { + "name": "Arnout Kazemier" + }, + "main": "./index.js", + "keywords": [ + "agent", + "browser", + "browserscope", + "os", + "parse", + "parser", + "ua", + "ua-parse", + "ua-parser", + "user agent", + "user", + "user-agent", + "useragent", + "version" + ], + "maintainers": [ + { + "name": "Arnout Kazemier", + "email": "info@3rd-Eden.com", + "url": "http://www.3rd-Eden.com" + } + ], + "license": { + "type": "MIT", + "url": "https://github.com/3rd-Eden/useragent/blob/master/LICENSE" + }, + "repository": { + "type": "git", + "url": "http://github.com/3rd-Eden/useragent.git" + }, + "devDependencies": { + "should": "*", + "mocha": "*", + "long-stack-traces": "0.1.x", + "yamlparser": "0.0.x", + "request": "2.9.x", + "semver": "1.0.x", + "pre-commit": "0.0.x" + }, + "pre-commit": [ + "test", + "update" + ], + "scripts": { + "test": "mocha $(find test -name '*.test.js')", + "qa": "mocha --ui exports $(find test -name '*.qa.js')", + "update": "node ./bin/update.js" + }, + "dependencies": { + "lru-cache": "2.2.x" + }, + "readme": "# useragent - high performance user agent parser for Node.js\n\nUseragent originated as port of [browserscope.org][browserscope]'s user agent\nparser project also known as ua-parser. Useragent allows you to parse user agent\nstring with high accuracy by using hand tuned dedicated regular expressions for\nbrowser matching. This database is needed to ensure that every browser is\ncorrectly parsed as every browser vendor implements it's own user agent schema.\nThis is why regular user agent parsers have major issues because they will\nmost likely parse out the wrong browser name or confuse the render engine version\nwith the actual version of the browser.\n\n---\n\n### Build status [![BuildStatus](https://secure.travis-ci.org/3rd-Eden/useragent.png?branch=master)](http://travis-ci.org/3rd-Eden/useragent)\n\n---\n\n### High performance\n\nThe module has been developed with a benchmark driven approach. It has a\npre-compiled library that contains all the Regular Expressions and uses deferred\nor on demand parsing for Operating System and device information. All this\nengineering effort has been worth it as [this benchmark shows][benchmark]:\n\n```\nStarting the benchmark, parsing 62 useragent strings per run\n\nExecuted benchmark against node module: \"useragent\"\nCount (61), Cycles (5), Elapsed (5.559), Hz (1141.3739447904327)\n\nExecuted benchmark against node module: \"useragent_parser\"\nCount (29), Cycles (3), Elapsed (5.448), Hz (545.6817291171243)\n\nExecuted benchmark against node module: \"useragent-parser\"\nCount (16), Cycles (4), Elapsed (5.48), Hz (304.5373431830105)\n\nExecuted benchmark against node module: \"ua-parser\"\nCount (54), Cycles (3), Elapsed (5.512), Hz (1018.7561434659247)\n\nModule: \"useragent\" is the user agent fastest parser.\n```\n\n---\n\n### Installation\n\nInstallation is done using the Node Package Manager (NPM). If you don't have\nNPM installed on your system you can download it from\n[npmjs.org][npm]\n\n```\nnpm install useragent --save\n```\n\nThe `--save` flag tells NPM to automatically add it to your `package.json` file.\n\n---\n\n### API\n\n\nInclude the `useragent` parser in you node.js application:\n\n```js\nvar useragent = require('useragent');\n```\n\nThe `useragent` library allows you do use the automatically installed RegExp\nlibrary or you can fetch it live from the remote servers. So if you are\nparanoid and always want your RegExp library to be up to date to match with\nagent the widest range of `useragent` strings you can do:\n\n```js\nvar useragent = require('useragent');\nuseragent(true);\n```\n\nThis will async load the database from the server and compile it to a proper\nJavaScript supported format. If it fails to compile or load it from the remote\nlocation it will just fall back silently to the shipped version. If you want to\nuse this feature you need to add `yamlparser` and `request` to your package.json\n\n```\nnpm install yamlparser --save\nnpm install request --save\n```\n\n#### useragent.parse(useragent string[, js useragent]);\n\nThis is the actual user agent parser, this is where all the magic is happening.\nThe function accepts 2 arguments, both should be a `string`. The first argument\nshould the user agent string that is known on the server from the\n`req.headers.useragent` header. The other argument is optional and should be\nthe user agent string that you see in the browser, this can be send from the\nbrowser using a xhr request or something like this. This allows you detect if\nthe user is browsing the web using the `Chrome Frame` extension.\n\nThe parser returns a Agent instance, this allows you to output user agent\ninformation in different predefined formats. See the Agent section for more\ninformation.\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\n\n// example for parsing both the useragent header and a optional js useragent\nvar agent2 = useragent.parse(req.headers['user-agent'], req.query.jsuseragent);\n```\n\nThe parse method returns a `Agent` instance which contains all details about the\nuser agent. See the Agent section of the API documentation for the available\nmethods.\n\n#### useragent.lookup(useragent string[, js useragent]);\n\nThis provides the same functionality as above, but it caches the user agent\nstring and it's parsed result in memory to provide faster lookups in the\nfuture. This can be handy if you expect to parse a lot of user agent strings.\n\nIt uses the same arguments as the `useragent.parse` method and returns exactly\nthe same result, but it's just cached.\n\n```js\nvar agent = useragent.lookup(req.headers['user-agent']);\n```\n\nAnd this is a serious performance improvement as shown in this benchmark:\n\n```\nExecuted benchmark against method: \"useragent.parse\"\nCount (49), Cycles (3), Elapsed (5.534), Hz (947.6844321931629)\n\nExecuted benchmark against method: \"useragent.lookup\"\nCount (11758), Cycles (3), Elapsed (5.395), Hz (229352.03831239208)\n```\n\n#### useragent.fromJSON(obj);\n\nTransforms the JSON representation of a `Agent` instance back in to a working\n`Agent` instance\n\n```js\nvar agent = useragent.parse(req.headers['user-agent'])\n , another = useragent.fromJSON(JSON.stringify(agent));\n\nconsole.log(agent == another);\n```\n\n#### useragent.is(useragent string).browsername;\n\nThis api provides you with a quick and dirty browser lookup. The underlying\ncode is usually found on client side scripts so it's not the same quality as\nour `useragent.parse` method but it might be needed for legacy reasons.\n\n`useragent.is` returns a object with potential matched browser names\n\n```js\nuseragent.is(req.headers['user-agent']).firefox // true\nuseragent.is(req.headers['user-agent']).safari // false\nvar ua = useragent.is(req.headers['user-agent'])\n\n// the object\n{\n version: '3'\n webkit: false\n opera: false\n ie: false\n chrome: false\n safari: false\n mobile_safari: false\n firefox: true\n}\n```\n\n---\n\n### Agents, OperatingSystem and Device instances\n\nMost of the methods mentioned above return a Agent instance. The Agent exposes\nthe parsed out information from the user agent strings. This allows us to\nextend the agent with more methods that do not necessarily need to be in the\ncore agent instance, allowing us to expose a plugin interface for third party\ndevelopers and at the same time create a uniform interface for all versioning.\n\nThe Agent has the following property\n\n- `family` The browser family, or browser name, it defaults to Other.\n- `major` The major version number of the family, it defaults to 0.\n- `minor` The minor version number of the family, it defaults to 0.\n- `patch` The patch version number of the family, it defaults to 0.\n\nIn addition to the properties mentioned above, it also has 2 special properties,\nwhich are:\n\n- `os` OperatingSystem instance\n- `device` Device instance\n\nWhen you access those 2 properties the agent will do on demand parsing of the\nOperating System or/and Device information.\n\nThe OperatingSystem has the same properties as the Agent, for the Device we\ndon't have any versioning information available, so only the `family` property is\nset there. If we cannot find the family, they will default to `Other`.\n\nThe following methods are available:\n\n#### Agent.toAgent();\n\nReturns the family and version number concatinated in a nice human readable\nstring.\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.toAgent(); // 'Chrome 15.0.874'\n```\n\n#### Agent.toString();\n\nReturns the results of the `Agent.toAgent()` but also adds the parsed operating\nsystem to the string in a human readable format.\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.toString(); // 'Chrome 15.0.874 / Mac OS X 10.8.1'\n\n// as it's a to string method you can also concat it with another string\n'your useragent is ' + agent;\n// 'your useragent is Chrome 15.0.874 / Mac OS X 10.8.1'\n```\n#### Agent.toVersion();\n\nReturns the version of the browser in a human readable string.\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.toVersion(); // '15.0.874'\n```\n\n#### Agent.toJSON();\n\nGenerates a JSON representation of the Agent. By using the `toJSON` method we\nautomatically allow it to be stringified when supplying as to the\n`JSON.stringify` method.\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.toJSON(); // returns an object\n\nJSON.stringify(agent);\n```\n\n#### OperatingSystem.toString();\n\nGenerates a stringified version of operating system;\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.os.toString(); // 'Mac OSX 10.8.1'\n```\n\n#### OperatingSystem.toVersion();\n\nGenerates a stringified version of operating system's version;\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.os.toVersion(); // '10.8.1'\n```\n\n#### OperatingSystem.toJSON();\n\nGenerates a JSON representation of the OperatingSystem. By using the `toJSON`\nmethod we automatically allow it to be stringified when supplying as to the\n`JSON.stringify` method.\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.os.toJSON(); // returns an object\n\nJSON.stringify(agent.os);\n```\n\n#### Device.toString();\n\nGenerates a stringified version of device;\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.device.toString(); // 'Asus A100'\n```\n\n#### Device.toVersion();\n\nGenerates a stringified version of device's version;\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.device.toVersion(); // '' , no version found but could also be '0.0.0'\n```\n\n#### Device.toJSON();\n\nGenerates a JSON representation of the Device. By using the `toJSON` method we\nautomatically allow it to be stringified when supplying as to the\n`JSON.stringify` method.\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.device.toJSON(); // returns an object\n\nJSON.stringify(agent.device);\n```\n\n### Adding more features to the useragent\n\nAs I wanted to keep the core of the user agent parser as clean and fast as\npossible I decided to move some of the initially planned features to a new\n`plugin` file.\n\nThese extensions to the Agent prototype can be loaded by requiring the\n`useragent/features` file:\n\n```js\nvar useragent = require('useragent');\nrequire('useragent/features');\n```\n\nThe initial release introduces 1 new method, satisfies, which allows you to see\nif the version number of the browser satisfies a certain range. It uses the\nsemver library to do all the range calculations but here is a small summary of\nthe supported range styles:\n\n* `>1.2.3` Greater than a specific version.\n* `<1.2.3` Less than.\n* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`.\n* `~1.2.3` := `>=1.2.3 <1.3.0`.\n* `~1.2` := `>=1.2.0 <2.0.0`.\n* `~1` := `>=1.0.0 <2.0.0`.\n* `1.2.x` := `>=1.2.0 <1.3.0`.\n* `1.x` := `>=1.0.0 <2.0.0`.\n\nAs it requires the `semver` module to function you need to install it\nseperately:\n\n```\nnpm install semver --save\n```\n\n#### Agent.satisfies('range style here');\n\nCheck if the agent matches the supplied range.\n\n```js\nvar agent = useragent.parse(req.headers['user-agent']);\nagent.satisfies('15.x || >=19.5.0 || 25.0.0 - 17.2.3'); // true\nagent.satisfies('>16.12.0'); // false\n```\n---\n\n### Migrations\n\nFor small changes between version please review the [changelog][changelog].\n\n#### Upgrading from 1.10 to 2.0.0\n\n- `useragent.fromAgent` has been removed.\n- `agent.toJSON` now returns an Object, use `JSON.stringify(agent)` for the old\n behaviour.\n- `agent.os` is now an `OperatingSystem` instance with version numbers. If you\n still a string only representation do `agent.os.toString()`.\n- `semver` has been removed from the dependencies, so if you are using the\n `require('useragent/features')` you need to add it to your own dependencies\n\n#### Upgrading from 0.1.2 to 1.0.0\n\n- `useragent.browser(ua)` has been renamed to `useragent.is(ua)`.\n- `useragent.parser(ua, jsua)` has been renamed to `useragent.parse(ua, jsua)`.\n- `result.pretty()` has been renamed to `result.toAgent()`.\n- `result.V1` has been renamed to `result.major`.\n- `result.V2` has been renamed to `result.minor`.\n- `result.V3` has been renamed to `result.patch`.\n- `result.prettyOS()` has been removed.\n- `result.match` has been removed.\n\n---\n\n### License\n\nMIT\n\n[browserscope]: http://www.browserscope.org/\n[benchmark]: /3rd-Eden/useragent/blob/master/benchmark/run.js\n[changelog]: /3rd-Eden/useragent/blob/master/CHANGELOG.md\n[npm]: http://npmjs.org\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/3rd-Eden/useragent/issues" + }, + "homepage": "https://github.com/3rd-Eden/useragent", + "_id": "useragent@2.0.7", + "_from": "useragent@~2.0.4" +} diff --git a/node_modules/karma/node_modules/useragent/static/user_agent.after.yaml b/node_modules/karma/node_modules/useragent/static/user_agent.after.yaml new file mode 100644 index 00000000..66b0b0b7 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/static/user_agent.after.yaml @@ -0,0 +1,14 @@ +user_agent_parsers: + # browsers + - regex: '(Thunderbird)/(\d+)\.(\d+)\.?(\d+)?' + + # command line tools + - regex: '(Wget)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*)' + + - regex: '(curl)/(\d+)\.(\d+)\.(\d+)' + family_replacement: 'cURL' + +os_parsers: + - regex: '(Red Hat)' + +device_parsers: diff --git a/node_modules/karma/node_modules/useragent/test/features.test.js b/node_modules/karma/node_modules/useragent/test/features.test.js new file mode 100644 index 00000000..a6c3ee3a --- /dev/null +++ b/node_modules/karma/node_modules/useragent/test/features.test.js @@ -0,0 +1,16 @@ +describe('useragent/features', function () { + 'use strict'; + + var useragent = require('../') + , features = require('../features') + , ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.24 Safari/535.2"; + + describe('#satisfies', function () { + it('should satisfy that range selector', function () { + var agent = useragent.parse(ua); + + agent.satisfies('15.x || >=19.5.0 || 25.0.0 - 17.2.3').should.be_true; + agent.satisfies('>16.12.0').should.be_false; + }); + }); +}); diff --git a/node_modules/karma/node_modules/useragent/test/fixtures/firefoxes.yaml b/node_modules/karma/node_modules/useragent/test/fixtures/firefoxes.yaml new file mode 100644 index 00000000..8c0d50b7 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/test/fixtures/firefoxes.yaml @@ -0,0 +1,1386 @@ +# http://people.mozilla.com/~dwitte/ua.txt +# +# The following are some example User Agent strings for various versions of +# Firefox and other Gecko-based browsers. Many of these have been modified by +# extensions, external applications, distributions, and users. The version number +# for Firefox 5.0 (and the corresponding Gecko version) is tentative. See +# https://developer.mozilla.org/En/Gecko_User_Agent_String_Reference for more +# details. Credit to http://useragentstring.com/ for providing some of these +# strings. + +test_cases: + # Firefox 4.0 (prerelease) + - user_agent_string: Mozilla/5.0 (Windows NT 6.0; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b6pre) Gecko/20100903 Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; rv:2.0b6pre) Gecko/20100903 Firefox/4.0b6pre Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + - user_agent_string: Mozilla/5.0 (X11; Linux i686; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + + # Firefox 4.0.1 + - user_agent_string: Mozilla/5.0 (Windows NT 5.2; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (WindowsCE 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 + family: 'Firefox' + major: '4' + minor: '0' + patch: '1' + + # Firefox 4.0 (prerelease) + - user_agent_string: Mozilla/5.0 (Windows NT 6.0; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b6pre) Gecko/20100903 Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; rv:2.0b6pre) Gecko/20100903 Firefox/4.0b6pre Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + - user_agent_string: Mozilla/5.0 (X11; Linux i686; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: b6pre + + # Firefox 5.0 (version number tentative -- not yet released) + - user_agent_string: Mozilla/5.0 (Windows NT 5.2; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (WindowsCE 6.0; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux i686; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux x86_64; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux armv7l; rv:2.1.1) Gecko/ Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + + # Firefox 3.6 + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.8) Gecko/20100804 Gentoo Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.8) Gecko/20100723 SUSE/3.6.8-0.1.1 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.2.8) Gecko/20100722 Ubuntu/10.04 (lucid) Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; fi-FI; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.8) Gecko/20100727 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.9.2.8) Gecko/20100725 Gentoo Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; FreeBSD i386; de-CH; rv:1.9.2.8) Gecko/20100729 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 GTB7.1 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; he; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 GTB7.1 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0C) + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2.3) Gecko/20121221 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.8) Gecko/20100722 BTRS86393 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0C) + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-TW; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E) + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; ro; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en; rv:1.9.2.8) Gecko/20100805 Firefox/3.6.8 + family: 'Firefox' + major: '3' + minor: '6' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.7) Gecko/20100723 Fedora/3.6.7-1.fc13 Firefox/3.6.7 + family: 'Firefox' + major: '3' + minor: '6' + patch: '7' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.7) Gecko/20100726 CentOS/3.6-3.el5.centos Firefox/3.6.7 + family: 'Firefox' + major: '3' + minor: '6' + patch: '7' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; hu; rv:1.9.2.7) Gecko/20100713 Firefox/3.6.7 GTB7.1 + family: 'Firefox' + major: '3' + minor: '6' + patch: '7' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.9.2.7) Gecko/20100713 Firefox/3.6.7 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '7' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6 GTB7.1 + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6 GTB7.0 + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.6) Gecko/20100628 Ubuntu/10.04 (lucid) Firefox/3.6.6 + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-PT; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; it; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 GTB7.1 + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; nl; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 ( .NET CLR 3.5.30729; .NET4.0E) + family: 'Firefox' + major: '3' + minor: '6' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.4) Gecko/20100614 Ubuntu/10.04 (lucid) Firefox/3.6.4 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.4) Gecko/20100625 Gentoo Firefox/3.6.4 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; ja; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 GTB7.1 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; cs; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.9.2.4) Gecko/20100523 Firefox/3.6.4 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.4) Gecko/20100527 Firefox/3.6.4 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.4) Gecko/20100527 Firefox/3.6.4 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.4) Gecko/20100523 Firefox/3.6.4 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-CA; rv:1.9.2.4) Gecko/20100523 Firefox/3.6.4 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 GTB7.0 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.4) Gecko/20100513 Firefox/3.6.4 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.4) Gecko/20100503 Firefox/3.6.4 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; nb-NO; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; ko; rv:1.9.2.4) Gecko/20100523 Firefox/3.6.4 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4 GTB7.0 + family: 'Firefox' + major: '3' + minor: '6' + patch: '4' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.2.3) Gecko/20100403 Fedora/3.6.3-4.fc13 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3) Gecko/20100403 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.3) Gecko/20100401 SUSE/3.6.3-1.1 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; ko-KR; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100404 Ubuntu/10.04 (lucid) Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; es-ES; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.0 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-GB; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; nl; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; fr; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; it; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; hu; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.1 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.1 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.0 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; es-ES; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; cs; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; ca; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; sv-SE; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; pl; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; nl; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.9.2.3) Gecko/20100403 Firefox/3.6.3 + family: 'Firefox' + major: '3' + minor: '6' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.7; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2 + family: 'Firefox' + major: '3' + minor: '6' + patch: '2' + + # Firefox 3.5 + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; it; rv:1.9.1.9) Gecko/20100402 Ubuntu/9.10 (karmic) Firefox/3.5.9 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; it; rv:1.9.1.9) Gecko/20100330 Fedora/3.5.9-2.fc12 Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.9) Gecko/20100317 SUSE/3.5.9-0.1.1 Firefox/3.5.9 GTB7.0 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; es-CL; rv:1.9.1.9) Gecko/20100402 Ubuntu/9.10 (karmic) Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; cs-CZ; rv:1.9.1.9) Gecko/20100317 SUSE/3.5.9-0.1.1 Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; nl; rv:1.9.1.9) Gecko/20100401 Ubuntu/9.10 (karmic) Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; hu-HU; rv:1.9.1.9) Gecko/20100330 Fedora/3.5.9-1.fc12 Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.1.9) Gecko/20100317 SUSE/3.5.9-0.1 Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100401 Ubuntu/9.10 (karmic) Firefox/3.5.9 GTB7.1 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100315 Ubuntu/9.10 (karmic) Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.4) Gecko/20091028 Ubuntu/9.10 (karmic) Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; tr; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 GTB7.1 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; hu; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; et; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; nl; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; es-ES; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 GTB5 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 GTB7.0 (.NET CLR 3.0.30618) + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; ca; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 GTB7.0 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '9' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; ru; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc12 Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; es-ES; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc11 Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.8) Gecko/20100318 Gentoo Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc12 Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc12 Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; es-AR; rv:1.9.1.8) Gecko/20100214 Ubuntu/9.10 (karmic) Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.8) Gecko/20100214 Ubuntu/9.10 (karmic) Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; FreeBSD i386; ja-JP; rv:1.9.1.8) Gecko/20100305 Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; sl; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 (.NET CLR 3.5.30729) FirePHP/0.4 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 GTB6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 GTB7.0 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '8' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2) Gecko/20100305 Gentoo Firefox/3.5.7 + family: 'Firefox' + major: '3' + minor: '5' + patch: '7' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; cs-CZ; rv:1.9.1.7) Gecko/20100106 Ubuntu/9.10 (karmic) Firefox/3.5.7 + family: 'Firefox' + major: '3' + minor: '5' + patch: '7' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.1.7) Gecko/20091222 SUSE/3.5.7-1.1.1 Firefox/3.5.7 + family: 'Firefox' + major: '3' + minor: '5' + patch: '7' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '7' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '7' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.2; fr; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.0.04506.648) + family: 'Firefox' + major: '3' + minor: '5' + patch: '7' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; fa; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 + family: 'Firefox' + major: '3' + minor: '5' + patch: '7' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 MRA 5.5 (build 02842) Firefox/3.5.7 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '7' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.6) Gecko/20100117 Gentoo Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.6) Gecko/20091216 Fedora/3.5.6-1.fc11 Firefox/3.5.6 GTB6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.1.6) Gecko/20091201 SUSE/3.5.6-1.1.1 Firefox/3.5.6 GTB6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.6) Gecko/20100118 Gentoo Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6 GTB6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6 GTB7.0 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.6) Gecko/20091201 SUSE/3.5.6-1.1.1 Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.9.1.6) Gecko/20100107 Fedora/3.5.6-1.fc12 Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; ca; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; it; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 ( .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; id; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 MRA 5.4 (build 02647) Firefox/3.5.6 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 MRA 5.5 (build 02842) Firefox/3.5.6 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 MRA 5.5 (build 02842) Firefox/3.5.6 + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 GTB6 (.NET CLR 3.5.30729) FBSMTWB + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729) FBSMTWB + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729) + family: 'Firefox' + major: '3' + minor: '5' + patch: '6' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; sv-SE; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 + family: 'Firefox' + major: '3' + minor: '5' + patch: '3' + + # Firefox on the next Gecko major release (preliminary) + - user_agent_string: Mozilla/5.0 (Windows NT 5.2; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (WindowsCE 6.0; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux armv7l; rv:2.0.1) Gecko Firefox/5.0.1 + family: 'Firefox' + major: '5' + minor: '0' + patch: '1' + +# # Fennec 2.0.1 (not yet released) +# - user_agent_string: Mozilla/5.0 (Android; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1 +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: '1' +# - user_agent_string: Mozilla/5.0 (Maemo; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1 +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: '1' +# - user_agent_string: Mozilla/5.0 (X11; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1 +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: '1' +# - user_agent_string: Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1 +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: '1' +# - user_agent_string: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1 +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: '1' +# +# # Fennec 2.0 (prerelease) +# - user_agent_string: Mozilla/5.0 (Android; Linux armv7l; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre Fennec/2.0b1pre +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: 'a1pre' +# - user_agent_string: Mozilla/5.0 (X11; Linux i686; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre Fennec/2.0b1pre +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: 'a1pre' +# - user_agent_string: Mozilla/5.0 (Windows NT 5.1; rv:2.0b6pre) Gecko/20100902 Firefox/4.0b6pre Fennec/2.0b1pre +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: 'a1pre' +# - user_agent_string: Mozilla/5.0 (X11; Linux armv7l; rv:2.0b4pre) Gecko/20100818 Firefox/4.0b4pre Fennec/2.0a1pre +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: 'a1pre' +# - user_agent_string: Mozilla/5.0 (X11; Linux armv7l; rv:2.0b4pre) Gecko/20100812 Firefox/4.0b4pre Fennec/2.0a1pre +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: 'a1pre' +# - user_agent_string: Mozilla/5.0 (X11; Linux armv7l; rv:2.0b3pre) Gecko/20100730 Firefox/4.0b3pre Fennec/2.0a1pre +# family: 'Fennec' +# major: '2' +# minor: '0' +# patch: 'a1pre' + + # Camino 2.2 (not yet released) + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.4; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1 + family: 'Camino' + major: '2' + minor: '2' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1 + family: 'Camino' + major: '2' + minor: '2' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1 + family: 'Camino' + major: '2' + minor: '2' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; PPC Mac OS X 10.4; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1 + family: 'Camino' + major: '2' + minor: '2' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; PPC Mac OS X 10.5; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1 + family: 'Camino' + major: '2' + minor: '2' + patch: '1' + + # Camino 2.0 + - user_agent_string: Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.4; en; rv:1.9.0.19) Gecko/2010051911 Camino/2.0.3 (like Firefox/3.0.19) + family: 'Camino' + major: '2' + minor: '0' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; nl; rv:1.9.0.19) Gecko/2010051911 Camino/2.0.3 (MultiLang) (like Firefox/3.0.19) + family: 'Camino' + major: '2' + minor: '0' + patch: '3' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en; rv:1.9.0.18) Gecko/2010021619 Camino/2.0.2 (like Firefox/3.0.18) + family: 'Camino' + major: '2' + minor: '0' + patch: '2' + + # Camino 1.6 + - user_agent_string: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; it; rv:1.8.1.21) Gecko/20090327 Camino/1.6.7 (MultiLang) (like Firefox/2.0.0.21pre) + family: 'Camino' + major: '1' + minor: '6' + patch: '7' + - user_agent_string: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en; rv:1.8.1.21) Gecko/20090327 Camino/1.6.7 (like Firefox/2.0.0.21pre) + family: 'Camino' + major: '1' + minor: '6' + patch: '7' + + # Camino 1.5 + - user_agent_string: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en; rv:1.8.1.12) Gecko/20080206 Camino/1.5.5 + family: 'Camino' + major: '1' + minor: '5' + patch: '5' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X Mach-O; en; rv:1.8.1.12) Gecko/20080206 Camino/1.5.5 + family: 'Camino' + major: '1' + minor: '5' + patch: '5' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en; rv:1.8.1.11) Gecko/20071128 Camino/1.5.4 + family: 'Camino' + major: '1' + minor: '5' + patch: '4' + - user_agent_string: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en; rv:1.8.1.6) Gecko/20070809 Camino/1.5.1 + family: 'Camino' + major: '1' + minor: '5' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en; rv:1.8.1.6) Gecko/20070809 Camino/1.5.1 + family: 'Camino' + major: '1' + minor: '5' + patch: '1' +# +# # Thunderbird 3.1 +# - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; sv-SE; rv:1.9.2.8) Gecko/20100802 Thunderbird/3.1.2 ThunderBrowse/3.3.2 +# family: 'Thunderbird' +# major: '3' +# minor: '1' +# patch: '2' +# - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.2.8) Gecko/20100802 Thunderbird/3.1.2 +# family: 'Thunderbird' +# major: '3' +# minor: '1' +# patch: '2' +# - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.7) Gecko/20100713 Lightning/1.0b2 Thunderbird/3.1.1 ThunderBrowse/3.3.1 +# family: 'Thunderbird' +# major: '3' +# minor: '1' +# patch: '1' +# +# # Thunderbird 3.0 +# - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.10) Gecko/20100621 Fedora/3.0.5-1.fc13 Lightning/1.0b2pre Thunderbird/3.0.5 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '5' +# - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.10) Gecko/20100512 Lightning/1.0b1 Thunderbird/3.0.5 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '5' +# - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100423 Thunderbird/3.0.4 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '4' +# - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1.9) Gecko/20100317 Lightning/1.0b1 Thunderbird/3.0.4 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '4' +# - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '4' +# - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; pl; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '4' +# - user_agent_string: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '4' +# - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.8) Gecko/20100408 Thunderbird/3.0.3 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '3' +# - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.9.1.7) Gecko/20100111 Thunderbird/3.0.1 ThunderBrowse/3.2.8.1 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '1' +# - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-CA; rv:1.9.1.7) Gecko/20100111 Thunderbird/3.0.1 ThunderBrowse/3.2.8.1 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '1' +# - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.9.1.7) Gecko/20100111 Thunderbird/3.0.1 ThunderBrowse/3.2.8.1 +# family: 'Thunderbird' +# major: '3' +# minor: '0' +# patch: '1' + + # SeaMonkey 2.1.1 (not yet released) + - user_agent_string: Mozilla/5.0 (Windows NT 5.2; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (WindowsCE 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + - user_agent_string: Mozilla/5.0 (X11; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 SeaMonkey/2.1.1 + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: '1' + + # SeaMonkey 2.1 (prerelease) + - user_agent_string: Mozilla/5.0 (Windows; Windows NT 5.2; rv:2.0b3pre) Gecko/20100803 SeaMonkey/2.1a3pre + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: 'a3pre' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.3a4pre) Gecko/20100404 SeaMonkey/2.1a1pre + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: 'a1pre' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-CA; rv:1.9.3a3pre) Gecko/20100312 SeaMonkey/2.1a1pre + family: 'SeaMonkey' + major: '2' + minor: '1' + patch: 'a1pre' + + # SeaMonkey 2.0 + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.11) Gecko/20100721 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.11) Gecko/20100714 SUSE/2.0.6-2.1 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux ia64; de; rv:1.9.1.11) Gecko/20100820 Lightning/1.0b2pre SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.11) Gecko/20100722 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.11) Gecko/20100701 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 9.0; en-US; rv:1.9.1.11) Gecko/20100701 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.11) Gecko/20100701 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.11) Gecko/20100722 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.11) Gecko/20100701 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.11) Gecko/20100701 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.9.1.11) Gecko/20100701 SeaMonkey/2.0.6 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-CA; rv:1.9.1.11pre) Gecko/20100630 SeaMonkey/2.0.6pre + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6pre' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-CA; rv:1.9.1.11pre) Gecko/20100629 SeaMonkey/2.0.6pre + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6pre' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.11pre) Gecko/20100515 SeaMonkey/2.0.6pre + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6pre' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.11pre) Gecko/20100508 SeaMonkey/2.0.6pre + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '6pre' + - user_agent_string: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.10) Gecko/20100504 Lightning/1.0b1 Mnenhy/0.8.2 SeaMonkey/2.0.5 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '5' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.1.10) Gecko/20100504 Lightning/1.0b1 SeaMonkey/2.0.5 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '5' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.10) Gecko/20100504 Lightning/1.0b1 SeaMonkey/2.0.5 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '5' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.9) Gecko/20100428 Lightning/1.0b1 SeaMonkey/2.0.4 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '4' + - user_agent_string: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100317 SUSE/2.0.4-3.2 Lightning/1.0b1 SeaMonkey/2.0.4 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.9) Gecko/20100317 Lightning/1.0b1 SeaMonkey/2.0.4 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '4' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.8) Gecko/20100205 SeaMonkey/2.0.3 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '3' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.7) Gecko/20100104 SeaMonkey/2.0.2 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '2' + - user_agent_string: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20100104 SeaMonkey/2.0.2 + family: 'SeaMonkey' + major: '2' + minor: '0' + patch: '2' diff --git a/node_modules/karma/node_modules/useragent/test/fixtures/pgts.yaml b/node_modules/karma/node_modules/useragent/test/fixtures/pgts.yaml new file mode 100644 index 00000000..2210b824 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/test/fixtures/pgts.yaml @@ -0,0 +1,62356 @@ +test_cases: + - user_agent_string: "abot/0.1 (abot; http://www.abot.com; abot@abot.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Ace Explorer" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ACS-NF/3.0 NEC-c616/001.00" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ACS-NF/3.0 NEC-e616/001.01 (www.proxomitron.de)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ActiveBookmark 1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; AI)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AIM" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AIM/30 (Mozilla 1.24b; Windows; I; 32-bit)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "aipbot/1.0 (aipbot; http://www.aipbot.com; aipbot@aipbot.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Alizee iPod 2005 (Beta; Mac OS X)" + family: "Mobile Safari" + major: + minor: + patch: + - user_agent_string: "alpha 06" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.5 (compatible; alpha/06; AmigaOS 1337)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ALPHA/06_(Win98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "amaya/8.3 libwww/5.4.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AmigaOS AmigaVoyager" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Arexx (AmigaVoyager/2.95; AmigaOS/MC680x0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Voyager; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.6 (compatible; AmigaVoyager; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AmigaVoyager/2.95 (compatible; MC680x0; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01 (compatible; AmigaVoyager/2.95; AmigaOS/MC680x0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AmigaVoyager/3.3.122 (AmigaOS/PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AmigaVoyager/3.4.4 (MorphOS/PPC native)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Amiga Voyager" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; AnsearchBot/1.0; +http://www.ansearch.com.au/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; ANTFresco 1.20; RISC OS 3.11)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.04 (compatible; ANTFresco/2.13; RISC OS 4.02)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.04 (compatible; NCBrowser/2.35 (1.45.2.1); ANTFresco/2.17; RISC OS-NC 5.13 Laz1UK1802)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; ANTFresco 2.20; RISC OS 3.11)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AOLserver-Tcl/3.5.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AOL 8.0 (compatible; AOL 8.0; DOS; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AOL/8.0 (Lindows 2003)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "aolbrowser/1.1 InterCon-Web-Library/1.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ArachnetAgent 2.3/4.78 (TuringOS; Turing Machine; 0.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Arexx ( ; ; AmigaOS 3.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Arexx (AmigaVoyager/2.95; AmigaOS/MC680x0; Mod-X by Pe)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Arexx (compatible; AmigaVoyager/2.95; AmigaOS" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Arexx (compatible; AmigaVoyager/2.95; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ARexx (compatible; ARexx; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Arexx (compatible; MSIE 6.0; AmigaOS5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Arexx (compatible; MSIE 6.0; AmigaOS5.0) IBrowse 4.0" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; ARexx; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; ARexx; AmigaOS; Avant Browser [avantbrowser.com]; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; arexx)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "ArtfaceBot (compatible; MSIE 6.0; Mozilla/4.0; Windows NT 5.1;)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Astra/1.0 (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Astra/2.0 (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Atari/2600b (compatible; 2port; Wood Grain)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Atari/2600 (GalaxianOS; U; en-US) cartridge/$29.95" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Auto-Proxy Downloader" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Advanced Browser (http://www.avantbrowser.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Avant Browser (http://www.avantbrowser.com)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Avant Browser [avantbrowser.com])" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com])" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]; .NET CLR 1.0.3705)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com])" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; .NET CLR 1.0.3705)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Avant Browser/1.2.789rel1 (http://www.avantbrowser.com)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Avantgo 5.5" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; AvantGo 5.2; FreeBSD)" + family: "AvantGo" + major: '5' + minor: '2' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; AvantGo 6.0; FreeBSD)" + family: "AvantGo" + major: '6' + minor: '0' + patch: + - user_agent_string: "Amiga" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AmigaOS" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Amiga OS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Aweb/2.3 (AmigaOS 3.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Amiga-AWeb/3.4APL" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; AWEB 3.4 SE; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Amiga-AWeb/3.4.167SE" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Amiga-AWeb/3.5.05 beta" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; BecomeBot/2.2.1; MSIE 6.0 compatible; +http://www.become.com/webmasters.html)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "BlackBerry7730/3.7.1 UP.Link/5.1.2.5" + family: "Blackberry" + major: '7730' + minor: + patch: + - user_agent_string: "UPG1 UP/4.0 (compatible; Blazer 1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Bobby/3.3 RPT-HTTPClient/0.3-3E" + family: "Other" + major: + minor: + patch: + - user_agent_string: "boitho.com-dc/0.70 ( http://www.boitho.com/dcbot.html )" + family: "Other" + major: + minor: + patch: + - user_agent_string: "boitho.com-dc/0.71 ( http://www.boitho.com/dcbot.html )" + family: "Other" + major: + minor: + patch: + - user_agent_string: "$BotName/$BotVersion [en] (UNIX; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Brain/1.0 [de] (Human RAW 1.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Browsers Part 4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Buscaplus Robi/1.0 (http://www.buscaplus.com/robi/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "BuyGet/1.0 Agent-Admin/webmaster@kfda.go.kr" + family: "Other" + major: + minor: + patch: + - user_agent_string: "CacheBot/0.445 (compatible, http://www.cachebot.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "CDM-8900" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Cerberian Drtrs Version-3.2-Build-1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.0; Update a; AK; Windows 95) via proxy gateway CERN-HTTPD/3.0 libwww/2.17" + family: "IE" + major: '3' + minor: '0' + patch: + - user_agent_string: "cfetch/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "CFNetwork/1.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonP900/R101 Profile/MIDP-2.0 Configuration/CLDC-1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonP900/R102 Profile/MIDP-2.0 Configuration/CLDC-1.0 Rev/MR4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonP910i/R3A SEMC-Browser/Symbian/3.0 Profile/MIDP-2.0 Configuration/CLDC-1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT610/R101 Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT610/R201 Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT610/R201 Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Link/5.1.2.1 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT610/R401 Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT610/R401 Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Link/5.1.1.3 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonZ600/R401 Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonK700i/R2AA SEMC-Browser/4.0.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 (Google WAP Proxy/1.0)" + family: "SEMC-Browser" + major: '4' + minor: '0' + patch: + - user_agent_string: "SonyEricssonK700i/R2AE SEMC-Browser/4.0.3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.2.3.15.0 (Google WAP Proxy/1.0)" + family: "SEMC-Browser" + major: '4' + minor: '0' + patch: + - user_agent_string: "Clushbot/3.31-BinaryFury (+http://www.clush.com/bot.html)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 1.0; Commodore64)" + family: "IE" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 2.0; Commodore64)" + family: "IE" + major: '2' + minor: '0' + patch: + - user_agent_string: "Contiki/1.0 (Commodore 64; http://dunkels.com/adam/contiki/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ConveraMultiMediaCrawler/0.1 (+http://www.authoritativeweb.com/crawl)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "CosmixCrawler/0.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "crawler (ISSpider-3.0; http://www.yoururlgoeshere.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Crawler0.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.0 (compatible; Crazy Browser 1.0.1; FreeBSD 3.2-RELEASE i386)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Crazy Browser 1.0.5; .NET CLR 1.0.3705)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FREE; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MyIE2; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; APCMAG; NetCaptor 6.5.0B7; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; 3305; Versatel.de ISDN 0404; Crazy Browser 1.0.5; onlineTV; www.cdesign.de)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; Crazy Browser 1.0.5; Tyco Electronics 01/2003)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {4CBEAFB3-10C9-497A-B016-7FEBFBD707E9}; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; brip1; RainBird 1.01/HT; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Crazy Browser 1.0.5; FDM)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Crazy Browser 1.0.5; .NET CLR 1.0.3705)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Crazy Browser 1.0.5; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Crazy Browser 1.0.5; iRider 2.20.0018)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; OptusNetDSL6; Crazy Browser 1.0.5; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Crazy Browser 1.0.5; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A5020528-0A08-4436-8CD1-D02C46132E5A}; SV1; Crazy Browser 1.0.5; CustomExchangeBrowser; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=vBB1c.00; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 1.0.5; Alexa Toolbar)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 1.0.5; .NET CLR 1.0.3705)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 1.0.5; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 1.0.5; (R1 1.1); .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 1.0.5; (R1 1.5))" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 1.0.5; SV1; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; FunWebProducts; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GoogleBot; Crazy Browser 1.0.5; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; SV1; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Katiesoft 7; Crazy Browser 1.0.5; .NET CLR 1.0.3705)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Crazy Browser 1.0.5; Alexa Toolbar)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Socantel; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 1.0.5; .NET CLR 1.0.3705)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 1.0.5; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 1.0.5; .NET CLR 1.1.4322; FDM)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 1.0.5; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iebar; Crazy Browser 1.0.5)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Texas Instruments; MyIE2; Crazy Browser 1.0.5; .NET CLR 1.0.3705)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.ASPSimply.com; Crazy Browser 1.0.5; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Crazy Browser 1.0.5; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "Crazy Browser" + major: '1' + minor: '0' + patch: '5' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Crazy Browser 2.0.0 Beta 1)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; YPC 3.0.1; yie6; Crazy Browser 2.0.0 Beta 1)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 2.0.0 Beta 1)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crazy Browser 2.0.0 Beta 1; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 2.0.0 Beta 1)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 2.0.0 Beta 1; .NET CLR 1.0.3705)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 2.0.0 Beta 1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Crazy Browser 2.0.0 Beta 1; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts-MyTotalSearch; Maxthon; Crazy Browser 2.0.0 Beta 1)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; Deepnet Explorer 1.3.2; Crazy Browser 2.0.0 Beta 1; .NET CLR 1.1.4322)" + family: "Crazy Browser" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "curl/7.10.2 (powerpc-apple-darwin7.0) libcurl/7.10.2 OpenSSL/0.9.7b zlib/1.1.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.10.6 (i386-redhat-linux-gnu) libcurl/7.10.6 OpenSSL/0.9.7a ipv6 zlib/1.1.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.10.6 (i386-redhat-linux-gnu) libcurl/7.10.6 OpenSSL/0.9.7a ipv6 zlib/1.2.0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.11.2 (i686-pc-linux-gnu) libcurl/7.10.2 OpenSSL/0.9.6i ipv6 zlib/1.1.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.12.0 (i686-pc-linux-gnu) libcurl/7.12.0 OpenSSL/0.9.7e ipv6 zlib/1.2.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.7.2 (powerpc-apple-darwin6.0) libcurl 7.7.2 (OpenSSL 0.9.6b)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.7.3 (i686-pc-linux-gnu) libcurl 7.7.3 (OpenSSL 0.9.6)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.7.3 (win32) libcurl 7.7.3 (OpenSSL 0.9.6)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.9.3 (powerpc-ibm-aix4.3.3.0) libcurl 7.9.3 (OpenSSL 0.9.6m)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.9.5 (i386-redhat-linux-gnu) libcurl 7.9.5 (OpenSSL 0.9.6b) (ipv6 enabled)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "curl/7.9.8 (i386-redhat-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.7a) (ipv6 enabled)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "DA 5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "DA 5.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "daemon (AmigaOS; alpha/06; AmigaOS mod-x)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "DataFountains/DMOZ Downloader" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; DB Browse 4.3; DB OS 6.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "deepak-USC/ISI" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Deepnet Explorer" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Deepnet Explorer 1.0.1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Dillo/0.6.4" + family: "Dillo" + major: '0' + minor: '6' + patch: '4' + - user_agent_string: "Dillo/0.7.3" + family: "Dillo" + major: '0' + minor: '7' + patch: '3' + - user_agent_string: "Dillo/0.8.0" + family: "Dillo" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Dillo/0.8.0-pre" + family: "Dillo" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Dillo/0.8.1" + family: "Dillo" + major: '0' + minor: '8' + patch: '1' + - user_agent_string: "Dillo/0.8.2" + family: "Dillo" + major: '0' + minor: '8' + patch: '2' + - user_agent_string: "Dillo/0.8.2-pre" + family: "Dillo" + major: '0' + minor: '8' + patch: '2' + - user_agent_string: "Dillo/0.8.3" + family: "Dillo" + major: '0' + minor: '8' + patch: '3' + - user_agent_string: "Dillo/0.8.3-rc2" + family: "Dillo" + major: '0' + minor: '8' + patch: '3' + - user_agent_string: "Dillo/0.8.4" + family: "Dillo" + major: '0' + minor: '8' + patch: '4' + - user_agent_string: "Dillo/0.8.5-pre" + family: "Dillo" + major: '0' + minor: '8' + patch: '5' + - user_agent_string: "Dillo/27951.4" + family: "Dillo" + major: '27951' + minor: '4' + patch: + - user_agent_string: "dloader(NaverRobot)/1.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; DLW 2.0; Win32)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "DoCoMo/1.0/D503iS/c10" + family: "Other" + major: + minor: + patch: + - user_agent_string: "DoCoMo/1.0/P502i/c10 (Google CHTML Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "DoCoMo/2.0 F900i(c100;TB;W22H12),gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "DoCoMo/2.0 N900i(c100;TB;W24H12)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Doris/1.10 [en] (Symbian)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Doris/1.17 [en] (Symbian)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Download.exe(1.1) (+http://www.sql-und-xml.de/freeware-tools/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Download Master" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Download Ninja 7.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "EasyDL/3.04 http://keywen.com/Encyclopedia/Bot" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks (0.10rc1; Linux 2.6.9-gentoo-r10 i686; 80x25)" + family: "Links" + major: '0' + minor: '10' + patch: + - user_agent_string: "ELinks (0.4.2; cygwin; 700)" + family: "Links" + major: '0' + minor: '4' + patch: + - user_agent_string: "ELinks (0.4.2; Linux; )" + family: "Links" + major: '0' + minor: '4' + patch: + - user_agent_string: "ELinks (0.4pre18; Linux 2.2.22 i686; 80x25)" + family: "Links" + major: '0' + minor: '4' + patch: + - user_agent_string: "ELinks (0.4pre5; Linux 2.2.20-compact i586; 80x30)" + family: "Links" + major: '0' + minor: '4' + patch: + - user_agent_string: "ELinks (0.4pre5; Linux 2.2.20 i586; 138x44)" + family: "Links" + major: '0' + minor: '4' + patch: + - user_agent_string: "ELinks (0.4pre5; Linux 2.4.23 i686; 114x27)" + family: "Links" + major: '0' + minor: '4' + patch: + - user_agent_string: "ELinks (0.4pre5; Linux 2.4.24 i686; 132x34)" + family: "Links" + major: '0' + minor: '4' + patch: + - user_agent_string: "ELinks (0.4pre5; Linux 2.6.0 i686; 176x66)" + family: "Links" + major: '0' + minor: '4' + patch: + - user_agent_string: "ELinks (0.9.3)" + family: "Links" + major: '0' + minor: '9' + patch: + - user_agent_string: "ELinks (0.9.CVS; Linux 2.6.5 i686; 169x55)" + family: "Links" + major: '0' + minor: '9' + patch: + - user_agent_string: "ELinks/0.9.CVS (textmode; Linux 2.4.18-1-386 i686; 80x25-3)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.1 (textmode; FreeBSD 4.10-PRERELEASE i386; 132x43)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.1 (textmode; FreeBSD 4.10-STABLE i386; 132x43)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.1 (textmode; Linux 2.4.26 i686; 128x48)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.1 (textmode; Linux 2.6.3-7mdksmp i686; 80x25)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.1 (textmode; Linux 2.6.6 i686; 128x54)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.1 (textmode; Linux; 80x24)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.1 (textmode; Linux; 80x25)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.2rc2 (textmode; Linux 2.4.26-lck1 i486; 80x25)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.2rc4 (textmode; Linux 2.4.20-8 i686; 105x46)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.2rc7 (textmode; Linux 2.4.29-1 i686; 190x75)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.2 (textmode; Linux; 157x52)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.3 (textmode; Linux 2.6.10 i686; 80x25)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.3 (textmode; Linux 2.6.7-20050106 i686; 80x34)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.3 (textmode; Linux 2.6.8-1-386 i686; 160x64)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.3 (textmode; Linux 2.6.8.1 i686; 118x82)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ELinks/0.9.3 (textmode; Linux 2.6.8-mdp04 i686; 80x25)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Enigma Browser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "EricssonT68/R101 (;; ;; ;; Smartphone; SDA/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Explorer /5.02 (Windows 95; U) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Explorer /5.02 (Windows 95; U) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; FastWeb; Windows NT 5.1; OMEGA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "FavOrg" + family: "Other" + major: + minor: + patch: + - user_agent_string: "FDM 1.x" + family: "Other" + major: + minor: + patch: + - user_agent_string: "FindAnISP.com_ISP_Finder_v99a" + family: "Other" + major: + minor: + patch: + - user_agent_string: "findlinks/0.901e (+http://wortschatz.uni-leipzig.de/findlinks/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Firefox/1.0 (Windows; U; Win98; en-US; Localization; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Firefox/1.0.1 (Windows NT 5.1; U; pl-PL)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "FireFox (X11; Linux i686; pl-PL); slackware; FireFox;" + family: "Other" + major: + minor: + patch: + - user_agent_string: "FlashGet" + family: "Other" + major: + minor: + patch: + - user_agent_string: "FOOZWAK (zeep; 47.3; CheeseMatic 9.1; T312461; iOpus-I-M; BucketChunk 4.1; Shronk; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "FreshDownload/4.40" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Funky Little Browser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Galeon (IE4 compatible; Galeon; Windows XP)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Galeon (PPC; U; Windows NT 5.1; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Galeon; Windows NT 5.1;)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (IE4 compatible; Galeon; Windows NT 5.1;)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (IE4 compatible; Galeon; Windows XP)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 Galeon 1.2.5 (X11; Linux i686; U;) Gecko/0-pie MSIE 6.0" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-IE; rv:1.6) Gecko Galeon" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 Galeon/1.0.2 (X11; Linux i686; U)" + family: "Galeon" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 Galeon/1.0.3 (X11; Linux i686; U)" + family: "Galeon" + major: '1' + minor: '0' + patch: '3' + - user_agent_string: "Mozilla/5.0 Galeon/1.0.3 (X11; Linux i686; U;) Gecko/20020214" + family: "Galeon" + major: '1' + minor: '0' + patch: '3' + - user_agent_string: "Mozilla/5.0 Galeon/1.0.3 (X11; Linux i686; U;) Gecko/20020325" + family: "Galeon" + major: '1' + minor: '0' + patch: '3' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.0 (X11; Linux i686; U)" + family: "Galeon" + major: '1' + minor: '2' + patch: '0' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.0 (X11; Linux i686; U;) Gecko/20020408" + family: "Galeon" + major: '1' + minor: '2' + patch: '0' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.11 (X11; Linux i686; U;) Gecko/0" + family: "Galeon" + major: '1' + minor: '2' + patch: '11' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.11 (X11; Linux i686; U;) Gecko/20030417" + family: "Galeon" + major: '1' + minor: '2' + patch: '11' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.11 (X11; Linux i686; U;) Gecko/20030703" + family: "Galeon" + major: '1' + minor: '2' + patch: '11' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.11 (X11; Linux i686; U;) Gecko/20030708" + family: "Galeon" + major: '1' + minor: '2' + patch: '11' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.11 (X11; Linux i686; U;) Gecko/20030716" + family: "Galeon" + major: '1' + minor: '2' + patch: '11' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.11 (X11; Linux i686; U;) Gecko/20030822" + family: "Galeon" + major: '1' + minor: '2' + patch: '11' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.13 (X11; Linux i686; U;) Gecko/20040308" + family: "Galeon" + major: '1' + minor: '2' + patch: '13' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.13 (X11; Linux i686; U;) Gecko/20041004" + family: "Galeon" + major: '1' + minor: '2' + patch: '13' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.5 (X11; Linux i586; U;) Gecko/20020605" + family: "Galeon" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.5 (X11; Linux i686; U)" + family: "Galeon" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.5 (X11; Linux i686; U;) Gecko/0" + family: "Galeon" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.5 (X11; Linux i686; U;) Gecko/20020605" + family: "Galeon" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.5 (X11; Linux i686; U;) Gecko/20020623 Debian/1.2.5-0.woody.1" + family: "Galeon" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.5 (X11; Linux i686; U;) Gecko/20020809" + family: "Galeon" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.6 (X11; Linux i686; U;) Gecko/20020827" + family: "Galeon" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.6 (X11; Linux i686; U;) Gecko/20020830" + family: "Galeon" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.6 (X11; Linux i686; U;) Gecko/20021105" + family: "Galeon" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20021203" + family: "Galeon" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20021226 Debian/1.2.7-6" + family: "Galeon" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20030131" + family: "Galeon" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20030401" + family: "Galeon" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20030622" + family: "Galeon" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.7 (X11; Linux ppc; U;) Gecko/20030130" + family: "Galeon" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.8 (X11; Linux i686; U;) Gecko/20030317" + family: "Galeon" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 Galeon/1.2.8 (X11; Linux i686; U;) Gecko/20030328" + family: "Galeon" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Galeon/1.3.10" + family: "Galeon" + major: '1' + minor: '3' + patch: '10' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Galeon/1.3.10 (Debian package 1.3.10-3)" + family: "Galeon" + major: '1' + minor: '3' + patch: '10' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Galeon/1.3.11a (Debian package 1.3.11a-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '11' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Galeon/1.3.11a (Debian package 1.3.11a-2)" + family: "Galeon" + major: '1' + minor: '3' + patch: '11' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040814 Galeon/1.3.11a" + family: "Galeon" + major: '1' + minor: '3' + patch: '11' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.6) Gecko/20040115 Galeon/1.3.12" + family: "Galeon" + major: '1' + minor: '3' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20031015 Galeon/1.3.12" + family: "Galeon" + major: '1' + minor: '3' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040115 Galeon/1.3.12" + family: "Galeon" + major: '1' + minor: '3' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040308 Galeon/1.3.12" + family: "Galeon" + major: '1' + minor: '3' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040331 Galeon/1.3.12" + family: "Galeon" + major: '1' + minor: '3' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; hu; rv:1.6) Gecko/20040229 Galeon/1.3.12" + family: "Galeon" + major: '1' + minor: '3' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; PL; rv:1.6) Gecko/20040115 Galeon/1.3.12" + family: "Galeon" + major: '1' + minor: '3' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20031115 Galeon/1.3.13" + family: "Galeon" + major: '1' + minor: '3' + patch: '13' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040116 Galeon/1.3.13" + family: "Galeon" + major: '1' + minor: '3' + patch: '13' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040122 Galeon/1.3.13 (Debian package 1.3.13-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '13' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040122 Galeon/1.3.13 (Debian package 1.3.13-2)" + family: "Galeon" + major: '1' + minor: '3' + patch: '13' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040130 Galeon/1.3.13" + family: "Galeon" + major: '1' + minor: '3' + patch: '13' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040305 Galeon/1.3.13" + family: "Galeon" + major: '1' + minor: '3' + patch: '13' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040312 Galeon/1.3.13 (Debian package 1.3.13-2)" + family: "Galeon" + major: '1' + minor: '3' + patch: '13' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040402 Galeon/1.3.14" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040426 Galeon/1.3.14" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040501 Galeon/1.3.14" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20040928 Galeon/1.3.14 (Debian package 1.3.14a-0jds4)" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20040107 Galeon/1.3.14" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040122 Galeon/1.3.14 (Debian package 1.3.14a-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040124 Galeon/1.3.14" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040309 Galeon/1.3.14" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040312 Galeon/1.3.14" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Galeon/1.3.14 (Debian package 1.3.14a-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Galeon/1.3.14 (Debian package 1.3.14acvs20040504-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040528 Galeon/1.3.14 (Debian package 1.3.14acvs20040520-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '14' + - user_agent_string: "Mozilla/5.0 (compatible; Galeon/1.3.15; Atari 2600)" + family: "Galeon" + major: '1' + minor: '3' + patch: '15' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Galeon/1.3.15 (Debian package 1.3.15-2)" + family: "Galeon" + major: '1' + minor: '3' + patch: '15' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040510 Galeon/1.3.15" + family: "Galeon" + major: '1' + minor: '3' + patch: '15' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040528 Galeon/1.3.15 (Debian package 1.3.15-2)" + family: "Galeon" + major: '1' + minor: '3' + patch: '15' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040618 Galeon/1.3.15" + family: "Galeon" + major: '1' + minor: '3' + patch: '15' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040624 Galeon/1.3.15" + family: "Galeon" + major: '1' + minor: '3' + patch: '15' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040624 Galeon/1.3.15 (Debian package 1.3.15-3)" + family: "Galeon" + major: '1' + minor: '3' + patch: '15' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040710 Galeon/1.3.16" + family: "Galeon" + major: '1' + minor: '3' + patch: '16' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040510 Galeon/1.3.16" + family: "Galeon" + major: '1' + minor: '3' + patch: '16' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040726 Galeon/1.3.16 (Debian package 1.3.16-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '16' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040802 Galeon/1.3.16 (Debian package 1.3.16-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '16' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040805 Galeon/1.3.16 (Debian package 1.3.16-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '16' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040810 Galeon/1.3.16 (Debian package 1.3.16-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '16' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040724 Galeon/1.3.16" + family: "Galeon" + major: '1' + minor: '3' + patch: '16' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.2) Gecko/20040824 Galeon/1.3.17" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040805 Galeon/1.3.17 (Debian package 1.3.17-2.0.1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040803 Galeon/1.3.17" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040804 Galeon/1.3.17" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040818 Galeon/1.3.17" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040820 Galeon/1.3.17 (Debian package 1.3.17-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040906 Galeon/1.3.17" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040921 Galeon/1.3.17" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041007 Galeon/1.3.17 (Debian package 1.3.17-2)" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.7.2) Gecko/20040808 Galeon/1.3.17" + family: "Galeon" + major: '1' + minor: '3' + patch: '17' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041130 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041221 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041224 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20041007 Galeon/1.3.18 (Debian package 1.3.18-1.1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20041228 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040916 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040922 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040928 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041007 Galeon/1.3.18 (Debian package 1.3.18-1.1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041223 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Galeon/1.3.18" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Galeon/1.3.18 (Debian package 1.3.18-2)" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.3) Gecko/20041007 Galeon/1.3.18 (Debian package 1.3.18-1.1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '18' + - user_agent_string: "Mozilla/5.0 (This is not Lynx/Please do not arrest user; X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041027 Galeon/1.3.19" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041224 Galeon/1.3.19" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020 Galeon/1.3.19" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041027 Galeon/1.3.19" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Galeon/1.3.19 (Debian package 1.3.19-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Galeon/1.3.19 (Debian package 1.3.19-3)" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Galeon/1.3.19 (Debian package 1.3.19-4)" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050106 Galeon/1.3.19 (Debian package 1.3.19-1ubuntu1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050216 Galeon/1.3.19" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 Galeon/1.3.19" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041230 Galeon/1.3.19" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050106 Galeon/1.3.19 (Debian package 1.3.19-3)" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041221 Galeon/1.3.19.99" + family: "Galeon" + major: '1' + minor: '3' + patch: '19' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Galeon/1.3.20 (Debian package 1.3.20-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '20' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050106 Galeon/1.3.20 (Debian package 1.3.20-1ubuntu4)" + family: "Galeon" + major: '1' + minor: '3' + patch: '20' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050324 Galeon/1.3.20 (Debian package 1.3.20-1)" + family: "Galeon" + major: '1' + minor: '3' + patch: '20' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586) Gecko/20030311 Galeon/1.3.3" + family: "Galeon" + major: '1' + minor: '3' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20030311 Galeon/1.3.3" + family: "Galeon" + major: '1' + minor: '3' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20030428 Galeon/1.3.3" + family: "Galeon" + major: '1' + minor: '3' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386) Gecko/0 Galeon/1.3.4" + family: "Galeon" + major: '1' + minor: '3' + patch: '4' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586) Gecko/20030807 Galeon/1.3.5" + family: "Galeon" + major: '1' + minor: '3' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20030530 Galeon/1.3.5" + family: "Galeon" + major: '1' + minor: '3' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20030807 Galeon/1.3.5" + family: "Galeon" + major: '1' + minor: '3' + patch: '5' + - user_agent_string: "Galeon/1.3.7 (IE4 compatible; Galeon; Windows XP) Galeon/1.3.7 Debian/1.3.7.20030803-1" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Galeon/1.3.7 (IE4 compatible; I; Mac_PowerPC)" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Galeon/1.3.7 (IE4 compatible; I; Windows XP) Galeon/1.3.7 Debian/1.3.7.20030803-1" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386) Gecko/0 Galeon/1.3.7" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20030610 Galeon/1.3.7" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20030630 Galeon/1.3.7" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20040107 Galeon/1.3.7" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20040319 Galeon/1.3.7" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20040323 Galeon/1.3.7" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20040428 Galeon/1.3.7" + family: "Galeon" + major: '1' + minor: '3' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.4) Gecko/20030630 Galeon/1.3.8" + family: "Galeon" + major: '1' + minor: '3' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.4) Gecko/20030630 Galeon/1.3.8" + family: "Galeon" + major: '1' + minor: '3' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030630 Galeon/1.3.8" + family: "Galeon" + major: '1' + minor: '3' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.4) Gecko/20030630 Galeon/1.3.8" + family: "Galeon" + major: '1' + minor: '3' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.4) Gecko/20030630 Galeon/1.3.8" + family: "Galeon" + major: '1' + minor: '3' + patch: '8' + - user_agent_string: "Galeon/1.3.9 Mozilla/1.4 HTML/4.01 XHTML/1.0 CSS/2.1" + family: "Galeon" + major: '1' + minor: '3' + patch: '9' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030915 Galeon/1.3.9" + family: "Galeon" + major: '1' + minor: '3' + patch: '9' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20031015 Galeon/1.3.9" + family: "Galeon" + major: '1' + minor: '3' + patch: '9' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.4) Gecko/20030930 Galeon/1.3.9" + family: "Galeon" + major: '1' + minor: '3' + patch: '9' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20030311 Galeon/1.3.3,gzip(gfe) (via translate.google.com)" + family: "Galeon" + major: '1' + minor: '3' + patch: '3' + - user_agent_string: "GetRight/5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "GetRight/5.0.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "GetRight/5.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Go-Ahead-Got-It/1.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "googlebot/2.1 (+http://www.googlebot.com/bot.html" + family: "Other" + major: + minor: + patch: + - user_agent_string: "googlebot/2.1; +http://www.google.com/bot.html" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Googlebot (+http://www.google.com/bot.html)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Googlebot/2.1 (compatible; MSIE; Windows)" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Googlebot/2.1 (+http://www.googlebot.com/bot.html) (compatible; MSIE 6.0; )" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Googlebot/2.1+(+http://www.google.com/bot.html)" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.0 (MobilePhone SCP-5500/US/1.0) NetFront/3.0 MMP/2.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" + family: "NetFront" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (MobilePhone SCP-5500/US/1.0) NetFront/3.0 MMP/2.0 FAKE (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" + family: "NetFront" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.)" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "GoogleBot/2.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Googlebot-Image/1.0 (+http://www.googlebot.com/bot.html" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; grub-client-2.6.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Grubclient-2.2-internal-beta)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Grubclient; windows; SV1; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "grub crawler" + family: "Other" + major: + minor: + patch: + - user_agent_string: "grub crawler(http://www.grub.org)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "gsa-crawler (Enterprise; GID-01742;gsatesting@rediffmail.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Happy-Browser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "HLoader" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Homerweb" + family: "Other" + major: + minor: + patch: + - user_agent_string: "HooWWWer/2.1.0 (+http://cosco.hiit.fi/search/hoowwwer/ | mailto:crawler-infohiit.fi)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Hop 0.7 (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Hozilla/9.0 (Macintosh; U; PC Mac OS X; en-us) SnappleWebKit/69 (KHTML, like your mom) Safari/69" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (Win95; I; HTTPClient 1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Hyperlink/2.5e (Commodore 64)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ia_archiver-web.archive.org" + family: "Other" + major: + minor: + patch: + - user_agent_string: "alpha/06 (compatible; IBrowse; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "IBrowse (AmigaOS; alpha/06; AmigaOS mod-x)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "IBrowse(compatible; alpha/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "IBrowse (compatible; alpha/06; AmigaOS/PPC; SV1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "IBrowse/1.12demo (AmigaOS 3.0)" + family: "IBrowse" + major: '1' + minor: '12' + patch: + - user_agent_string: "IBrowse/2.2 (Windows V45)" + family: "IBrowse" + major: '2' + minor: '2' + patch: + - user_agent_string: "IBrowse/2.2 (Windows V50)" + family: "IBrowse" + major: '2' + minor: '2' + patch: + - user_agent_string: "IBrowse/2.3 (AmigaOS 3.0)" + family: "IBrowse" + major: '2' + minor: '3' + patch: + - user_agent_string: "IBrowse/2.3 (AmigaOS 3.1)" + family: "IBrowse" + major: '2' + minor: '3' + patch: + - user_agent_string: "IBrowse/2.3 (AmigaOS 3.9)" + family: "IBrowse" + major: '2' + minor: '3' + patch: + - user_agent_string: "IBrowse/2.3 (AmigaOS 3.9))" + family: "IBrowse" + major: '2' + minor: '3' + patch: + - user_agent_string: "IBrowse/2.3 (AmigaOS 4.0)" + family: "IBrowse" + major: '2' + minor: '3' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; IBrowse 2.3; AmigaOS4.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AmigaOS4.0) IBrowse 2.3" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; IBrowse 3.0; AmigaOS4.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "iCab" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 (compatible; iCab 2.9.1; Macintosh; U; PPC; Mac OS X)" + family: "iCab" + major: '2' + minor: '9' + patch: '1' + - user_agent_string: "iCab/2.9.5 (Macintosh; U; PPC; Mac OS X)" + family: "iCab" + major: '2' + minor: '9' + patch: '5' + - user_agent_string: "Mozilla/4.5 (compatible; iCab 2.9.6; Macintosh; U; PPC)" + family: "iCab" + major: '2' + minor: '9' + patch: '6' + - user_agent_string: "Mozilla/4.5 (compatible; iCab 2.9.7; Macintosh; U; PPC)" + family: "iCab" + major: '2' + minor: '9' + patch: '7' + - user_agent_string: "Mozilla/4.5 (compatible; iCab 2.9.7; Macintosh; U; PPC; Mac OS X)" + family: "iCab" + major: '2' + minor: '9' + patch: '7' + - user_agent_string: "iCab/2.9.8 (Macintosh; U; PPC)" + family: "iCab" + major: '2' + minor: '9' + patch: '8' + - user_agent_string: "iCab/2.9.8 (Macintosh; U; PPC; Mac OS X)" + family: "iCab" + major: '2' + minor: '9' + patch: '8' + - user_agent_string: "Mozilla/4/5 (compatible; iCab 2.9.8; Macintosh; U; 68K" + family: "iCab" + major: '2' + minor: '9' + patch: '8' + - user_agent_string: "Mozilla/4.5 (compatible; iCab 2.9.8; Macintosh; U; PPC)" + family: "iCab" + major: '2' + minor: '9' + patch: '8' + - user_agent_string: "Mozilla/4.5 (compatible; iCab 2.9.8; Macintosh; U; PPC; Mac OS X)" + family: "iCab" + major: '2' + minor: '9' + patch: '8' + - user_agent_string: "Mozilla/5.0 (compatible; iCab 2.9.8; Macintosh; U, PPC; Mac OS X)" + family: "iCab" + major: '2' + minor: '9' + patch: '8' + - user_agent_string: "iCab/3.0 (Macintosh; U; PPC; Mac OS X)" + family: "iCab" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; iCab 3.0; Macintosh; U; PPC; Mac OS X)" + family: "iCab" + major: '3' + minor: '0' + patch: + - user_agent_string: "ICE Browser/5.05 (Java 1.4.1; Windows 2000 5.0 x86)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ICEBrowser 5.31" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ICE Browser/v5_4_3 (Java 1.4.2_01; Windows XP 5.1 x86)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ICE Browser/v5_4_3_1 (Java 1.4.2_01; Windows XP 5.1 x86)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "IEAutoDiscovery" + family: "Other" + major: + minor: + patch: + - user_agent_string: "IE test" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Internet Explorer 5x" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Internet Explorer 5.x" + family: "Other" + major: + minor: + patch: + - user_agent_string: "IQSearch" + family: "Other" + major: + minor: + patch: + - user_agent_string: "itunes" + family: "Other" + major: + minor: + patch: + - user_agent_string: "iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "iTunes/4.7 (Macintosh; U; PPC Mac OS X 10.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Jakarta Commons-HttpClient/2.0final" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Jakarta Commons-HttpClient/2.0.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Jakarta Commons-HttpClient/2.0rc1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Jakarta Commons-HttpClient/2.0rc2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Jakarta Commons-HttpClient/3.0-beta1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Jakarta Commons-HttpClient/3.0-rc1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Jakarta Commons-HttpClient" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Jakarta Commons-HttpClient/2.0.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java(TM) 2 Runtime Environment, Standard Edition" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java1.1.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java1.3.1_03" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java1.4.0_02" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.1_01" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.1_02" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.1_04" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.1_05" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.2_01" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.2_03" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.2_04" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.2_05" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.4.2_06" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.5.0_01" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Java/1.5.0-beta2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "jBrowser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "JoBo/1.4beta (http://www.matuschek.net/jobo.html)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "JoeDog/1.00 [en] (X11; I; Siege 2.59)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Kittiecentral.com; HTTP)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Kittiecentral.com; HTTPConnect)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Kittiecentral.com; Index-Client)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Klondike/1.50 (WSP Win32) (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "KnowItAll(knowitall@cs.washington.edu)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Konqueror" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror; FreeBSD; http://www.cartedaffaire.net/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Konqueror/1.1.2" + family: "Konqueror" + major: '1' + minor: '1' + patch: '2' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.0.1; X11); Supports MD5-Digest; Supports gzip encoding" + family: "Konqueror" + major: '2' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.1.1; X11)" + family: "Konqueror" + major: '2' + minor: '1' + patch: '1' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.1.2; X11)" + family: "Konqueror" + major: '2' + minor: '1' + patch: '2' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.2-11; Linux)" + family: "Konqueror" + major: '2' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.2.1)" + family: "Konqueror" + major: '2' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.2.1; Linux)" + family: "Konqueror" + major: '2' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.2.2)" + family: "Konqueror" + major: '2' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.2.2-2; Linux)" + family: "Konqueror" + major: '2' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.2.2; FreeBSD)" + family: "Konqueror" + major: '2' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.2.2; Linux)" + family: "Konqueror" + major: '2' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/2.2.2; Linux 2.4.14-xfs; X11; i686)" + family: "Konqueror" + major: '2' + minor: '2' + patch: '2' + - user_agent_string: "Konqueror 3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0.0-10; Linux)" + family: "Konqueror" + major: '3' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0.0; FreeBSD)" + family: "Konqueror" + major: '3' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0.0; Linux)" + family: "Konqueror" + major: '3' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0; Darwin)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc1; i686 Linux; 20020101)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc4; i686 Linux; 20020313)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3; FreeBSD)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3; Linux)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3; Linux; X11)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0; i686 Linux; 20021215)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0.0-10; Linux 2.4.18-3smp)" + family: "Konqueror" + major: '3' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0.1 (CVS >= 20020327); Linux) Linspire (Lindows, Inc.)" + family: "Konqueror" + major: '3' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; CYGWIN_NT-5.1)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; de)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; de, DE, de_DE@euro)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; FreeBSD)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; i686 Linux; 20020802)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; i686 Linux; 20021111)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.20-4GB-athlon; X11; i686)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.20-4GB; X11)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.20; X11; i686)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.20-xfs; X11)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.21-20.0.1.ELsmp; X11; i686; , en_US, en, de)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.21-243-athlon)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.22-10mdk; X11; i686; en_GB, en_NZ, en)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.22-10mdk; X11; i686; fr, fr_FR)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.22-1.2115.nptl)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.22-4GB-athlon; X11; i686)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.22-aes; X11; i686)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.22-xfs; X11)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux 2.4.24-xfs; X11)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux; de, DE, de_DE@euro)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux; en_US, en)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux; i686)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux; X11; de, DE, de_DE@euro)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux; X11; en_GB)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux; X11; i686; , en_US, en)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; Linux; X11; i686; uk, uk_UA)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; OpenBSD)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1; SunOS)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1.3; OpenBSD 3.4)" + family: "Konqueror" + major: '3' + minor: '1' + patch: '3' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Darwin) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; , en_GB, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; en_US, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; FreeBSD 4.9-STABLE; X11; i386; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; FreeBSD) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2) KHTML/3.2.3 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.4.22) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.4.23-0; X11; i686) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.4.24-xfs; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.4.25-klg; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.4.26; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.4.27; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.3-15mdksmp; i686) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.3-7mdk) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.3-7mdk; X11; i686; en_US, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.4-52-default; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.4; i686) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.5) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.5; X11; i686; en_US, es, fr, it, en_US.UTF-8, en)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.5; X11; i686; en_US, es, fr, it, en_US.UTF-8, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.5; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.7-rc3-love2; X11; i686) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.7; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.8.1-10mdk) KHTML/3.2.3 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.8.1-12mdksmp) KHTML/3.2.3 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux 2.6.8.1; X11; i686; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; de, de_DE@euro) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; en_GB, en_GB.UTF-8, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; en_GB, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; en_US, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; en_US, zh_TW, en_US.UTF-8, zh_TW.UTF-8, zh) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; i686; en_US, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; i686) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux) KHTML/3.2.3 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; ) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux) (KHTML, like Gecko) WebWasher 3.3" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; X11; , en_US, en) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; X11; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; X11; es, es_ES, es_ES.UTF8) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; X11; i686) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; X11; ) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; Linux; X11; ru, en_US, ru_RU, ru_RU.KOI8-R, KOI8-R) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; NetBSD) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; OpenBSD) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2; x86_64; en_US) KHTML/3.2.3 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2.; Linux 2.4.20-gentoo-r2; X11; i" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2.2; Linux) (KHTML, like Gecko) - www.amorosi4u.de.vu" + family: "Konqueror" + major: '3' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2.3; FreeBSD 4.10-STABLE; X11; i386; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.2.3; OpenBSD 3.6)" + family: "Konqueror" + major: '3' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; FreeBSD 5.3-RELEASE-p2; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; FreeBSD) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.4.21-243-smp4G) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; konqueror/3.3; linux 2.4.21-243-smp4G) (KHTML, like Geko)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.4.24; X11; i686; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.4.27; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.10-1-386; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.10-1-686-smp) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.10-1-686; X11; i686; zh_TW) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.10-1-k7; X11; i686; en_US) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.10-gentoo-r2-ljr; X11; x86_64; en_US) KHTML/3.3.91 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.10; X11; i686; en_US) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.10; X11; i686) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.11.2; X11; i686; cs, en_US) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.7) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.7; X11; i686; fr, it, es, ru, de, en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.8.1-24mdk; X11; i686; sl) KHTML/3.3.92 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.8-1-686; X11; i686; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.8-2-686-smp) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.9-10.1.aur.4; X11; pl) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.9; X11) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; de, en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; de) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux) KHTML/3.3.91 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux) KHTML/3.3.92 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; ppc) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; X11; i686; en_US) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; X11; i686; es, en_US) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; X11; i686) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; X11; x86_64; de) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; Linux; x86_64) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; pl, en_US) KHTML/3.3.2 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; pl) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.3; X11; de) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.4; FreeBSD) KHTML/3.4.0 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '4' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.4; Linux 2.6.11-rc4; X11; en_US) KHTML/3.4.0 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '4' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.4; Linux; en_US) KHTML/3.4.0 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '4' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.4; Linux) KHTML/3.4.0 (like Gecko)" + family: "Konqueror" + major: '3' + minor: '4' + patch: + - user_agent_string: "Mozilla/6.0 (compatible; Konqueror/4.2; i686 FreeBSD 6.4; 20060308)" + family: "Konqueror" + major: '4' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc1; i686 Linux; 20020126)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc1; i686 Linux; 20020202)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc1; i686 Linux; 20020224)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc3; i686 Linux; 20020703)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc3; i686 Linux; 20020911)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc3; i686 Linux; 20021022)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.0-rc4; i686 Linux; 20020719)" + family: "Konqueror" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1-rc3; i686 Linux; 20020510)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1-rc4; i686 Linux; 20020710)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Konqueror/3.1-rc5; i686 Linux; 20020609)" + family: "Konqueror" + major: '3' + minor: '1' + patch: + - user_agent_string: "Kurzor/1.0 (Kurzor; http://adcenter.hu/docs/en/bot.html; cursor@easymail.hu)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Lament/7.8 (compatible; Netscape 5.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "larbin_2.6.3 (larbin-2.6.3@unspecified.mail)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "larbin_2.6.3 larbin-2.6.3@unspecified.mail" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LB-Crawler/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LG/U8110/v2.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "fetch libfetch/2.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "libwww-perl/5.79" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT306/R101 [Html2Wml/0.4.11 libwww-perl/5.79]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "testJapanequeDelicious/0.1 libwww-perl/5.803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "W3C-checklink/4.1 [4.14] libwww-perl/5.803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; Linkman)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Links" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Links (030709; Linux 2.6.7-bootsplash i686; fb)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LINKS Mozilla/2.0 (compatible; MSIE 10.0)" + family: "IE" + major: '10' + minor: '0' + patch: + - user_agent_string: "Links (0.92; Linux 2.2.14-5.0 i586)" + family: "Links" + major: '0' + minor: '92' + patch: + - user_agent_string: "Links (0.96; Linux 2.4.9-e.38.1RS i686)" + family: "Links" + major: '0' + minor: '96' + patch: + - user_agent_string: "Links (0.96; Unix)" + family: "Links" + major: '0' + minor: '96' + patch: + - user_agent_string: "Links (0.97pre3; Linux 2.4.18-6mdk i586)" + family: "Links" + major: '0' + minor: '97' + patch: + - user_agent_string: "Links (0.98; Darwin 7.6.0 Power Macintosh; 90x50)" + family: "Links" + major: '0' + minor: '98' + patch: + - user_agent_string: "Links/0.98 (fdafsd; Unix; 80x25)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Links (0.98; Linux 2.2.25 i586; 100x37)" + family: "Links" + major: '0' + minor: '98' + patch: + - user_agent_string: "Links (0.98; Linux 2.4.20 i686; 80x34)" + family: "Links" + major: '0' + minor: '98' + patch: + - user_agent_string: "Links (0.98; Linux 2.4.25-20040331b i686; 80x50)" + family: "Links" + major: '0' + minor: '98' + patch: + - user_agent_string: "Links (0.98; Unix)" + family: "Links" + major: '0' + minor: '98' + patch: + - user_agent_string: "Links (0.98; Unix; 100x37)" + family: "Links" + major: '0' + minor: '98' + patch: + - user_agent_string: "Links (0.99; Linux 2.6.8.1-4-386 i686; 198x66)" + family: "Links" + major: '0' + minor: '99' + patch: + - user_agent_string: "Links (0.99pre14; CYGWIN_NT-5.1 1.5.10(0.116/4/2) i686; 111x39)" + family: "Links" + major: '0' + minor: '99' + patch: + - user_agent_string: "Links (0.99pre8; Unix; 80x25)" + family: "Links" + major: '0' + minor: '99' + patch: + - user_agent_string: "Links (1.00pre10; Darwin 5.5 Power Macintosh; 80x24)" + family: "Links" + major: '1' + minor: '00' + patch: + - user_agent_string: "Links (1.00pre12; Linux 2.6.10-grsec i686; 139x54) (Debian pkg 0.99+1.00pre12-1)" + family: "Links" + major: '1' + minor: '00' + patch: + - user_agent_string: "Links (1.00pre12; Linux 2.6.2 i586; 80x24) (Debian pkg 0.99+1.00pre12-1)" + family: "Links" + major: '1' + minor: '00' + patch: + - user_agent_string: "Links (1.00pre3; SunOS 5.9 i86pc; 80x24)" + family: "Links" + major: '1' + minor: '00' + patch: + - user_agent_string: "Links (2.0; FreeBSD 4.7-RELEASE i386; 80x24)" + family: "Links" + major: '2' + minor: '0' + patch: + - user_agent_string: "Links 2.0 (http://gossamer-threads.com/scripts/links/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Links (2.0pre1; Linux 2.4.24-grsec i686; 80x25)" + family: "Links" + major: '2' + minor: '0' + patch: + - user_agent_string: "Links (2.0pre6; Linux 2.2.16 i686; x)" + family: "Links" + major: '2' + minor: '0' + patch: + - user_agent_string: "Links (2.1pre11; FreeBSD 4.9-RELEASE i386; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; FreeBSD 5.2.1-RELEASE i386; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.4.20-20.7asp i686; 80x24)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.4.22-10mdk i686; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.4.24 i686; 87x32)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.4.25-gentoo-r2 i686; 100x37)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.4.25-gentoo-r2 i686; 160x64)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.4.26-gentoo-r6 i686; 122x43)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.6.5-gentoo i686; 122x40)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.6.6-rc1 i686; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.6.7-gentoo-r14 i686; fb)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre11; Linux 2.6.7-ide4 i586; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre12; Linux 2.2.19-7.0.16smp i686; 128x47)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre13; Linux 2.4.7-10 i686; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre13; Linux 2.6.3-4mdk i686; 100x37)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; FreeBSD 4.9-RELEASE i386; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; FreeBSD 5.1-RELEASE i386; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; FreeBSD 5.2.1-RELEASE i386; 80x50)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; Linux 2.4.26-bsd21h i686; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; Linux 2.6.4-52-default i686; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; Linux 2.6.4-54.5-default i686; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; Linux 2.6.5-7.104-default i686; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; Linux 2.6.5 i686; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; OpenBSD 3.4 i386)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre14; OpenBSD 3.6 i386)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; CYGWIN_NT-5.0 1.3.1(0.38/3/2) i686; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; FreeBSD 4.10-RELEASE i386; 131x85)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; FreeBSD 4.10-RELEASE i386; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; FreeBSD 5.2-CURRENT i386; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; FreeBSD 5.3-RELEASE i386; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; FreeBSD 5.3-RELEASE i386; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; FreeBSD 5.3-RELEASE-p5 i386; 78x28)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; FreeBSD 5.3-STABLE i386; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.2.14-5.0 i586; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.2.16 i586; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.4.18-27.7.x i586; svgalib)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.4.22-1.2115.nptl i686; braille)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.4.26 i586; 128x48)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.4.26 i686; 128x48)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.4.26 i686; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.4.27 i586; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.10-gentoo-r4 i686; 141x52)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.10-gentoo-r4n i686; fb)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.10-gentoo-r5 i686; 100x38)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.10-gentoo-r6 i686; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.6tlahuizcalpacuhtli i486; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.9-gentoo-r1-g4 ppc; 160x53)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.9-gentoo-r1 i686; 128x48)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.9-gentoo-r1 x86_64; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; Linux 2.6.9 i686; 128x48)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; NetBSD 2.99.11 amd64; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre15; OpenBSD 3.6 i386; x)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre16; Linux 2.6.9-buz i686; 128x47)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre17; FreeBSD 5.4-PRERELEASE i386; 80x60)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre17; Linux 2.4.18-rmk7-pxa3-embedix armv5tel; 73x33)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre7; Linux 2.6.9 i686; 80x25)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre9; Linux 2.4.25 i686; fb)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "Links (2.1pre; Linux)" + family: "Links" + major: '2' + minor: '1' + patch: + - user_agent_string: "LinkSweeper/1.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Linspire Internet Suite" + family: "Other" + major: + minor: + patch: + - user_agent_string: "lmspider (lmspider@scansoft.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Lotus-Notes/5.0; Windows-NT)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Lotus-Notes/6.0; Windows-NT)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH/3.02a (http://www.learntohack.nil)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH browser 3.02a" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH Browser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH Browser 3.02" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH Browser/3.02a" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH Browser 3.02a (compatible; mozilla ; Windows NT 5.1; SV1; http://www.learntohack.nil; .NET CLR 1.1.4322; http://www.learntohack.nil)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH Browser 3.02a (compatible; MSIE 6.0; Windows NT 5.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "LTH Browser 3.02a (compatible; MSIE 6.0; Windows NT 5.1; SV1; http://www.learntohack.nil; .NET CLR 1.1.4322; http://www.learntohack.nil)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "LTH Browser 3.02a (http://www.learntohack.nil)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH Browser/3.02a (http://www.learntohack.nil)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LTH Browser/3.02 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "lwp-request/2.06" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LWP::Simple/5.50" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LWP::Simple/5.68" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LWP::Simple/5.76" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LWP::Simple/5.79" + family: "Other" + major: + minor: + patch: + - user_agent_string: "LWP::Simple/5.800" + family: "Other" + major: + minor: + patch: + - user_agent_string: "lwp-trivial/1.34" + family: "Other" + major: + minor: + patch: + - user_agent_string: "lwp-trivial/1.38" + family: "Other" + major: + minor: + patch: + - user_agent_string: "lwp-trivial/1.40" + family: "Other" + major: + minor: + patch: + - user_agent_string: "lwp-trivial/1.41" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Lynx (compatible; MSIE 6.0; )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Lynx (SunOS 10)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Lynx/1.025 (CP/Build 16-bit)" + family: "Lynx" + major: '1' + minor: '025' + patch: + - user_agent_string: "Lynx/2.2 libwww/2.14" + family: "Lynx" + major: '2' + minor: '2' + patch: + - user_agent_string: "Lynx/2.6 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '6' + patch: + - user_agent_string: "Lynx/2.7.1ac-0.102+intl+csuite libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '7' + patch: '1' + - user_agent_string: "Lynx/2.7.1 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '7' + patch: '1' + - user_agent_string: "Lynx/2.7.2 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '7' + patch: '2' + - user_agent_string: "Lynx/2.8 (incompatible; NCSA HALOS; HAL9000" + family: "Lynx" + major: '2' + minor: '8' + patch: + - user_agent_string: "Lynx/2.8rel.2 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: + - user_agent_string: "Lynx/2.8.1rel.2 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: '1' + - user_agent_string: "Lynx/2.8.2rel.1 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: '2' + - user_agent_string: "Lynx/2.8.3dev.18 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: '3' + - user_agent_string: "Lynx/2.8.3dev.6 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: '3' + - user_agent_string: "Lynx/2.8.3dev.8 libwww-FM/2.14FM" + family: "Lynx" + major: '2' + minor: '8' + patch: '3' + - user_agent_string: "Lynx/2.8.3dev.9 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6" + family: "Lynx" + major: '2' + minor: '8' + patch: '3' + - user_agent_string: "Lynx/2.8.3rel.1 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: '3' + - user_agent_string: "Lynx/2.8.3rel.1 libwww-FM/2.14FM" + family: "Lynx" + major: '2' + minor: '8' + patch: '3' + - user_agent_string: "Lynx/2.8.3rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.4" + family: "Lynx" + major: '2' + minor: '8' + patch: '3' + - user_agent_string: "Lynx/2.8.3rel.1 libwww-FM/2.14 SSL-MM/1.4 OpenSSL/0.9.6" + family: "Lynx" + major: '2' + minor: '8' + patch: '3' + - user_agent_string: "Lynx/2.8.4rel.1" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 Dillo/0.7.3 pl (X11; Linux)" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/0.8.6" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6a" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6b" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6c" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6e" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6g" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7a" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7b" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7c" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.4rel.1-mirabilos libwww-FM/2.14FM SSL-MM/1.4.1 OpenSSL/0.9.6c" + family: "Lynx" + major: '2' + minor: '8' + patch: '4' + - user_agent_string: "Lynx/2.8.5dev.12 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7a" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.16 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.16 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6b" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.16 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7a" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.2 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6a" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6b" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.7 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7a" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.8 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6g" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5dev.9 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7-beta3" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5rel.1 libwww-FM/2.14" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/0.8.12" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.0.16" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7c" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7d" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.5rel.2 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7d" + family: "Lynx" + major: '2' + minor: '8' + patch: '5' + - user_agent_string: "Lynx/2.8.6dev.11 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7d" + family: "Lynx" + major: '2' + minor: '8' + patch: '6' + - user_agent_string: "Lynx/2.8.6dev.6 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7d" + family: "Lynx" + major: '2' + minor: '8' + patch: '6' + - user_agent_string: "LynX 0.01 beta" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MacNetwork/1.0 (Macintosh)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Metager2 (http://metager2.de/site/webmaster.php)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MicroSux 6.6.6 (fucked up v9.1) 2 bit" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Minstrel-Browse/1.0 (http://www.minstrel.org.uk/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Missigua Locator 1.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MnoGoSearch/3.2.31" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mosaic for Amiga/1.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.0 (compatible; NCSA Mosaic; Atari 800-ST)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mosaic/0.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA_Mosaic/1.0 (X11; FreeBSD 1.2.0 i286) via proxy gateway CERN-HTTPD/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA_Mosaic/2.0 (compatible; MSIE 6.0;Windows XP),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "NCSA_Mosaic/2.0 (Windows 3.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA_Mosaic/2.0 (Windows NT 5.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mosaic/2.1 (Amiga ARexx)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mosaic/2.1 (compatible; MSIE; Amiga ARexx; SV1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA_Mosaic/2.7b5 (X11;Linux 2.0.13 i386) libwww/2.12 modified" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA Mosaic/2.7b5 (X11;Linux 2.6.7 i686) libwww/2.12 modified" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA_Mosaic/2.7b5 (X11;Linux 2.6.7 i686) libwww/2.12 modified" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA Mosaic/2-7-6 (X11;OpenVMS V7.2 VAX)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Mosaic/2.8; Windows NT 5.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA_Mosaic/2.8 (X11; FreeBSD 5.2.1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA Mosaic/3.0.0 (Windows x86)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AIR_Mosaic(16bit)(demo)/v3.09.05.08" + family: "Other" + major: + minor: + patch: + - user_agent_string: "mMosaic/3.6.6 (X11;SunOS 5.8 sun4m)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MOT-V551/08.17.0FR MIB/2.2.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MovableType/3.0D" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozdex/0.06-dev (Mozdex; http://www.mozdex.com/bot.html; spider@mozdex.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "mozilla (compatible; MSIE 3.0; Mac_PowerPC)" + family: "IE" + major: '3' + minor: '0' + patch: + - user_agent_string: "alpha/06" + family: "Other" + major: + minor: + patch: + - user_agent_string: "alpha/06 (AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "alpha/06 (compatible; alpha/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ALPHA/06 (compatible; ALPHA/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ALPHA/06 (compatible; Win98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AmigaOS 3.4 S.E.K-Tron" + family: "Other" + major: + minor: + patch: + - user_agent_string: "AmigaOS 5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/0.001 (uncompatible; TuringOS; Turing Machine; 0.001; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/0.02 [fu] (Dos62; Panzer PzKpfw Mk VI; SK Yep, its official I'm a nazi, or an asshat whichever.)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/0.1 [es] (Windows NT 5.1; U) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.000 (AOS; U; en) Gecko/20050301" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.0 (Macintosh; 68K; U; en)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.1N (X11; I; SunOS 5.4 sun4m)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.4.1 (windows; U; NT4.0; en-us) Gecko/25250101" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.6 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040812 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla 1.7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla 1.7.2 (FreeBSD 5.2.1) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla 1.75 on Linux: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/2.01 (Win16; I) via HTTP/1.0 deep.space.star-travel.org/" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/2.0 (compatible ; MSIE 3.02; Windows CE; PPC; 240x320)" + family: "IE" + major: '3' + minor: '02' + patch: + - user_agent_string: "Mozilla/24.4 (X11; I; Linux 2.4 i686; U) [en-ES]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01-C-MACOS8 (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01SGoldC-SGI (X11; I; IRIX 6.3 IP32)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01 (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.04Gold (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.04 (Win16; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.04 (Win16; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.04 (X11; I; SunOS 5.5.1 sun4u) via HTTP/1.0 depraved-midget.onlinescanner.com/" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (DreamKey/2.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 [en] (AWV2.20f)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (Liberate DTV 1.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (Planetweb/2.100 JS SSL US; Dreamcast US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (Windows 98;U) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (Windows 98; Win 9x 4.90)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (x86 [en] Windows NT 5.1; Sun)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.x (I-Opener 1.1; Netpliance)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (0000000000; 0000 000; 0000000 00 000)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (0000000000; 0000 0000; 00000000000)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.00 [en] (Compatible; RISC OS 4.39; MSIE 5.01; Windows 98; Oregano 1.10)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (6; probably not the latest!; Windows 2005; H010818)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (AmigaOS 3.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (combatible; MSIE 6.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; alpha 06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; alpha/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; ALPHA/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; AmigaOS; Chimera)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; GoogleToolbar 2.0.113-big; Windows XP 5.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; ICS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; IE-Favorites-Check-0.5)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Mozilla 4; Linux; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0b1; X11; I; Linux 2.4.18 i686)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98)Gecko/20020604" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (Compatible; MSIE 5.5; Windows NT 4.0; QXW03002)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (Compatible; MSIE 5.5; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 ( compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AmigaOs)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla /4.0 (compatible; MSIE 6.0; i686 Linux)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; NetBSD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (Compatible; MSIE 6.0; SunOS 5.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (Compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 7.1; Windows NT 7.1; Blueberry Bulid 2473)" + family: "IE" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.0 (Compatible; Windows_NT 5.0; MSIE 6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (exemplo; msiex; amiga)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (fantomBrowser)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 ( http://www.brismee.com/ ; mailto:guy.brismee@advalvas.be ; NSA/666.666.666 ; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 ( http://www.brismee.com/ ; mailto:guy.brismee@laposte.net ; NSA/666.666.666 ; SV1; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (JemmaTheTourist;http://www.activtourist.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 look-alike" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (Macintosh; U; PPC Mac OS X; en)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (MobilePhone SCP-5500/US/1.0) NetFront/3.0 MMP/2.0" + family: "NetFront" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (Mozilla/4.0; 6.0; MSIE 6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (MSIE/6.0; compatible; Win98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (MSIE 6.0; Windows NT 5.1; .NET CLR 1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (PDA; SL-C860/1.0,OpenPDA/Qtopia/1.3.2) NetFront/3.0" + family: "NetFront" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (PDA; Windows CE/1.0.0) NetFront/3.0" + family: "NetFront" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.0 (); ; ; ()" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (SKIZZLE! Distributed Internet Spider v1.0 - www.SKIZZLE.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (SmartPhone; Symbian OS/0.9.1) NetFront/3.0" + family: "NetFront" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (stat 0.12) (statbot@gmail.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (SunOS 5.8)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (Windows NT 4.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (Windows XP 5.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20040803 Debian-1.7.5-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla 4.75 [en] (X11; I; Linux 2.2.25 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla 4.8 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla 5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (000000000; 0; 000 000 00 0 000000; 00000; 00000000) 00000000000000 0000000000" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (000000000; 0; 000 000 00 0; 00000) 000000000000000 0000000 0000 000000 0000000000" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (000000000; 0; 000 000 00 0; 00) 0000000000000000000 0000000 0000 000000 0000000000000" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (000000000; 0; 000 000 00 0; 00000) 0000000000000000000 0000000 0000 000000 0000000000000" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (000000000; 0; 000 000 00 0 000000; 00000; 00000000) 00000000000000 00000000000 000000000000000000" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (000000000; 0; 000 000 00 0; 00000) 0000000000000000000 0000000 0000 000000 0000000000000,gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.001 (Macintosh; N; PPC; ja) Gecko/25250101 MegaCorpBrowser/1.0 (MegaCorp, Inc.)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.001 (windows; U; NT4.0; en-us) Gecko/25250101" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0adfasdf" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (ALL YOUR BASE ARE BELONG TO US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (AmigaOS 3.5, Amiga, 0wnx0r3d by eric) Gecko/20020604" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (AmigaOS; sektron)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Atari; U; Atari 800; en-US) Gecko/20040206 Galaxian/2.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (BeOS; U; BeOS BePC; en-CA; rv:1.5b) Gecko/20050308 Firefox/1.0.1 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; 0.8) Gecko/20010208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.4) Gecko/20030701" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (CIA Secure OS; U; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Clustered-Search-Bot/1.0; support@clush.com; http://www.clush.com/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Mozilla/4.0; MSIE 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Gecko/20050105 Debian/1.7.5-1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; X11; Linux i686; Konqueror/3.2) (KHTML, like Gecko) Gentoo/2004" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (DeadPeopleTasteLikeChicken.biz)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [de] (OS/2; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en] (Windows NT 5.1; U; en-US;)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en] (Windows; U; en-US; rv:1.4)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en] (Windows; U; Win98; en-US; rv.0.9.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en] (Windows; U; WinNT5.1; en-GB; rv:1.4)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en] (Windows XP; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (FreeBSD; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2" + family: "K-Meleon" + major: '0' + minor: '8' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Google-Gbrowser/0.0.9a; Windows NT 5.1; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Hector)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 IE" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (incompatible; MSIE 6.9; Secret OS 3.2; FIB;)" + family: "IE" + major: '6' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Java 1.4.1_05; Windows XP 5.1 x86; en) ICEbrowser/v6_0_0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Java 1.4.2_02; Windows XP 5.1 x86; en) ICEbrowser/v6_0_0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Java 1.4.2_05; Windows XP 5.1 x86; en) ICEbrowser/v5_2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (kombpartilb; Verhsun; Plasdfjoi; SV1; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Linux i386; en-US) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-EN; rv:0.9.4)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC;) Gecko DEVONtech" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; Incompatible my ass! What if I don't want your jerky, elitist, ugly-assed CSS crap? Screw you!)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.6 (KHTML, like Gecko) NetNewsWire/2.0b10" + family: "NetNewsWire" + major: '2' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.6 (KHTML, like Gecko) NetNewsWire/2.0b22" + family: "NetNewsWire" + major: '2' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0+(Macintosh;+U;+PPC+Mac+OS+X;+en)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/103u (KHTML, like Gecko) safari/100" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/124 (KHTML, like Gecko)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/124 (KHTML, like Gecko, Safari) Shiira/0.9.1" + family: "Shiira" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko, Safari) Shiira/0.9.2" + family: "Shiira" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko, Safari) Shiira/0.9.2.2" + family: "Shiira" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.4 (KHTML, like Gecko, Safari) Shiira/0.9.2.2" + family: "Shiira" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5.6 (KHTML, like Gecko, Safari) Shiira/0.9.3" + family: "Shiira" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit (KHTML, like Gecko) AIQtech" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit (KHTML, like Gecko) DEVONtech" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/124 (KHTML, like Gecko) safari/125.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.2 (KHTML, like Gecko, Safari) Shiira/0.9.2.2" + family: "Shiira" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.22" + family: "OmniWeb" + major: '563' + minor: '22' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.29" + family: "OmniWeb" + major: '563' + minor: '29' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.33" + family: "OmniWeb" + major: '563' + minor: '33' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.34" + family: "OmniWeb" + major: '563' + minor: '34' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v496" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v549" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v558" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v558.43" + family: "OmniWeb" + major: '558' + minor: '43' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v558.46" + family: "OmniWeb" + major: '558' + minor: '46' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v558.48" + family: "OmniWeb" + major: '558' + minor: '48' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20020909 Chimera/0.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20030917 Camino/0.7" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/125.6 (KHTML, like Gecko, Safari) Shiira/0.9.3" + family: "Shiira" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; da-DK; rv:1.7.5) Gecko/20041217 MultiZilla/1.7.0.2b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; de-DE; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.6) Gecko/20050331 Camino/0.8.3" + family: "Camino" + major: '0' + minor: '8' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a2) Gecko/20040714" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a5) Gecko/20041114 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a5) Gecko/20041121 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20041201 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20050103 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20050111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b2) Gecko/20050224 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b2) Gecko/20050317 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b2) Gecko/20050401 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050115 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050116" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050127 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050130 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050131 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050203 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050217 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; fr-FR; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O) Gecko Camino" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; it-IT; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; zh-tw) AppleWebKit/125.5.6 (KHTML, like Gecko, Safari) Shiira/0.9.3" + family: "Shiira" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (MSIE 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (MSIE 6.0) Gecko/20011018" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla 5.0 (MSIE 6.0 Win 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (NetBSD 1.6.2; U) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (NetWare; U; NetWare 6.0.04; en-PL) ICEbrowser/5.4.3 NovellViewPort/3.4.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (No data found)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (not MSIE5.5; X11; U; HP-UX 9000/785; en-US; rv:1.1) Gecko/20020828" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 3; en-US; rv:1.6) Gecko/20040117" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.7.5) Gecko/20041220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.8a2) Gecko/20040719" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4; da-DK; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (ROIL FF/1.0; Windows NT 5.1 64-bit)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (RSS Reader Panel)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Sage)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (tTh @ Cette) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (U; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Unknown; 32-bit)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (U; PPC; en) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Version: 1251 Type:4565)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Version: 245 Type:180)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Version: 3247 Type:3276)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Version: 4445 Type:1763)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (VMS; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows 3.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U; en-CA) Gecko/20041107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U; rv:1.7.5) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1,de-DE)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win3.1; en-US; rv:1.0.0) Gecko/20020530" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-AT; 0.7) Gecko/20010109" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-AT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-GB; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-GB; rv:1.7.6) Gecko/20050321 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.0; CMCE) Gecko/20020530" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.2b) Gecko/20021016" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.8.0.1c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041220 K-Meleon/9.0" + family: "K-Meleon" + major: '9' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040707 MSIE/7.66" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8a1) Gecko/20040520" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8a3) Gecko/20040817" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8b2) Gecko/20050317 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8b2) Gecko/20050329 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8b) Gecko/20050217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:7.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; es-ES; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; hu; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pl-PL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pl-PL; rv:1.7.6) Gecko/20050319" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; PL; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pt-BR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; sv-SE; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; sv-SE; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-AT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.5) Gecko/20041220 K-Meleon/0.9" + family: "K-Meleon" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.8a6) Gecko/20050111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; fr-FR; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; PL; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; pt-BR; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; Bush knew, failed to act.)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.8a1) Gecko/20040520" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.5) Gecko/20041108 STFU/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.6) Gecko/20050321 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; el-GR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.5) Gecko/20041110 FireFox/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.6) Gecko/20050321 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; 0.7) Gecko/20010109" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; Like Navigator 6.2) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2b) Gecko/20020923 Phoenix/0.1" + family: "Phoenix" + major: '0' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2b) Gecko/20020929 Phoenix/0.2" + family: "Phoenix" + major: '0' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5b) Gecko/20030823 Mozilla Firebird/0.6.1+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5) Gecko/20031016" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2) Gecko/20040803 Mnenhy/0.6.0.104" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.3) Gecko/20040910 Mnenhy/0.6.0.101" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.3) Gecko/20040910 MultiZilla/1.6.0.0e" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.3) Gecko/20040910 MultiZilla/1.6.1.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.4) Gecko/20041002" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.4) Gecko/20041010 FireFox/0.9b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.4) Gecko/20041010 K-Meleon/0.9b" + family: "K-Meleon" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Plasmahuman/1.0 (Firefox 1.0 Get it. Now.)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.7.0.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.7.0.2d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041220 K-Meleon/0.9" + family: "K-Meleon" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050218" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050228 Firefox/1.0.1 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050308 Firefox/1.0.1 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040621" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a4) Gecko/20040927" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a5) Gecko/20041122,gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a5) Gecko/20041122 MultiZilla/1.7.0.0o" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a6) Gecko/20050109" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a6) Gecko/20050110" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a6) Gecko/20050111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a6) Gecko/20050111 Mnenhy/0.7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b2) Gecko/20050221" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b2) Gecko/20050314 Firefox/1.0+ (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b2) Gecko/20050323 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b2) Gecko/20050330 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050120" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050211" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050216" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-AR; rv:1.7.5) Gecko/20041108 Clab_Browser_1.0_www.cristalab.com/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-AR; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-AR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.7.6) Gecko/20050303 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fi-FI; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.0.0) Gecko/20020530" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.8a6+) Gecko/20050111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.8b+) Gecko/20050117" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7.6) Gecko/20050311 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; nl-NL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; nl-NL; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.7.2) Gecko/20040803 Mnenhy/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; PL; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pt-BR; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pt-BR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.7.4) Gecko/20040926" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; tr-TR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-TW; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ca-AD; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.7.6) Gecko/20050318 Firefox/1.0.2 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.7.6) Gecko/20050330 Firefox/1.0.2 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; da-DK; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; da-DK; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7.5) Gecko/20041108 Firefox/LukasHetzi" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.8a3) Gecko/20040817" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041107 Junglelemming/4.3.7.1 (Wesma Pictures)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041122 Muuuh/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.6) Gecko/20050223" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.6) Gecko/20050321 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-CA; rv:1.8b2) Gecko/20050312 Firefox/1.0+ (tinderbox beast)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.0.1) Gecko/20020823" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.0.2) Gecko/20021120" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.6) Gecko/20050316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.6) Gecko/20050321 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.2.1) Gecko/20021130,gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040709" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20040910 Mnenhy/0.6.0.104" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20040910 MultiZilla/1.6.0.0d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20040910 Sylera/2.1.20" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firechicken/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firematt/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Hypnotoad/1.0 (Firefox/1.0)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 IE/6.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Junglelemming/1.0 (Wesma Pictures)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Microsoft/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Mozilla/4.0/MSIE 6.0" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Mozilla/5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 MSIE/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107-RB Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217,gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.7.0.1c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.7.0.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.7.0.1j" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.8.0.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041219 Sylera/2.1.21" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041220 K-Meleon/0.9" + family: "K-Meleon" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041222 MOOX (M3)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050308 Firefox/0.9.6" + family: "Firefox" + major: '0' + minor: '9' + patch: '6' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050223" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1 (All your Firefox/1.0.1 are belong to Firesomething)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050223 Firelemur/1.0.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 CompeGPS/1.0.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Hypnotoad/1.0.1 (Firefox/1.0.1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Supergecko/1.0.1 (IE6)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050308 Firefox/1.0.1 (MOOX M1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US, rv:1.7.6) Gecko/20050308 Firefox/1.0.1 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050308 Firefox/1.0.1 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050308 Firefox/1.0.1 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050312 Firefox/1.0.1 (stipe)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050314 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050315 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050317 Seastarfish/1.0.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050319" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050323" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050324 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 FairFox/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Unknow/x" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a4) Gecko/20040927" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a5) Gecko/20041123 K-Meleon/0.9" + family: "K-Meleon" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a5) Gecko/20041217 Mozilla Sunbird/0.2RC1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20040101" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050107 MultiZilla/1.7.0.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050112" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050226" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050228 Firefox/1.0+ (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050307 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050313 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050315 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050319 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050320 Firefox/1.0+ (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050321 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050330 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050401" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050128 Mnenhy/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050131 Firefox/1.0+ (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050201" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050202 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050205" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050217 MultiZilla/1.7.0.2d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:) Gecko/20040309" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US;) Unchaos/Crawler" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-AR; rv:1.7.5) Gecko/20041210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; eu-ES; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; eu-ES; rv:1.7.3) Gecko/20040910,gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; eu-ES; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; eu-ES; rv:1.7.6) Gecko/20050225 Firefox/1.0.1,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fi-FI; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041108 Mozilla/4.0/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041108 Mozilla /4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 2000)/1.0" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041109 Firefox/1.0.1 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041217 MultiZilla/1.7.0.0o" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.8)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; he-IL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; hr-HR; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu-HU; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.3) Gecko/20040910 MultiZilla/1.6.3.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7.6) Gecko/20050311 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ko-KR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nb-NO; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.6) Gecko/20050321 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; PL; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; PL; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; PL; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.0.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.0.2) Gecko/20040823" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 xb0x/0.10.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sl-SI; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr-TR; rv:1.7.6) Gecko/20050321 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; uk-UA; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; cs-CZ; rv:1.7.6) Gecko/20050318 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-GB; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.5) Gecko/20041217 WebWasher 3.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.5) Gecko/20041220 K-Meleon/0.9" + family: "K-Meleon" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8b2) Gecko/20050307 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; fr-FR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; hu-HU; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; pl-PL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; ru-RU; rv:1.7.4) Gecko/20040926" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; ru-RU; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; tr-TR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-AT; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-DE; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows, U, WinNT4.0, en-US, rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; es-ES; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; es-ES; rv:1.7.6) Gecko/20050303 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; fi-FI; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; Windows 98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; ; Windows NT 5.1; rv:1.7.5) Gecko/20041107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux; en-US) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; DragonFly i386; en-US; rv:1.7.5) Gecko/20041112 Foobar/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; de-DE; rv:1.7.6) Gecko/20050322 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-GB; rv:1.7.5) Gecko/20041228" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20030702" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20030723" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20031008 Epiphany/1.0" + family: "Epiphany" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20031017" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5a) Gecko/20030926 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031203" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031207 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040128" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.2) Gecko/20040829" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.2) Gecko/20041016" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041201 Epiphany/1.4.6" + family: "Epiphany" + major: '1' + minor: '4' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041204 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041219" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041221 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050103" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050108" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050112" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050117" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050118" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050124" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050305" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050306" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.6) Gecko/20050302 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.6) Gecko/20050315 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7a) Gecko/20040311" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040701 Epiphany/1.2.8" + family: "Epiphany" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20050314 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.8a5) Gecko/20041214" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i686; en-US; rv:1.8a5) Gecko/20041106" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; HP-UX 9000/785; en-US; rv:1.6) Gecko/20040304" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; HP-UX 9000/785; en-US; rv:1.6) Gecko/20040816" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; HP-UX 9000/785; en-US; rv:1.6) Gecko/20040831" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; HP-UX 9000/800; en-US; rv:1.4) Gecko/20030730" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; IRIX64 IP28; en-US; rv:1.7.5) Gecko/R-A-C Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; IRIX64 IP30; en-US; rv:1.7.5) Gecko/R-A-C Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; IRIX64 IP35; en-US; rv:1.7.5) Gecko/20041230" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux 2.4.2-2 i686; en-US; 0.7) Gecko/20010316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux 2.4.2 i686, en) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux 2.6.11.4-gentoo-xD i686; pl-PL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux 2.6.3-FTSOJ i686; en-US; rv:1.6)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux 2.6.4 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux; fr-FR; rv:1.6) Gecko/20040207 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.0.2) Gecko/20030708" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20041209 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0-2ubuntu4-warty99)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20041219 Firefox/1.0 (Debian package 1.0+dfsg.1-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20050105 Debian/1.7.5-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.6) Gecko/20050325 Firefox/1.0.2 (Debian package 1.0.2-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; it-IT; rv:1.4.1) Gecko/20031030" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; da-DK; rv:1.7.5) Gecko/20041221" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686, de)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.4.2) Gecko/20040921" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6; 009f52b638a35a83ea5212109fc44eed;) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040115 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040116" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.2) Gecko/20040906" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.3) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20041218" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20041220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20041221" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20041231" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20050105 Debian/1.7.5-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20050125" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.8a5) Gecko/20041121" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.8a5) Gecko/20041122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.8a6) Gecko/20050111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.8b2) Gecko/20050317" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.6)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.2) Gecko/20040906" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.6) Gecko/20050301 Firefox/1.0.1 (Debian package 1.0.1-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.6) Gecko/20050306 Firefox/1.0.1 (Debian package 1.0.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; el-GR; rv:1.7.5) Gecko/20041209 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0-2ubuntu4-warty99)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.5) Gecko/20050312 Epiphany/1.4.8" + family: "Epiphany" + major: '1' + minor: '4' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.6) Gecko/20050315 Firefox/1.0 (Ubuntu package 1.0.1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.6) Gecko/20050325 Firefox/1.0.2 (Debian package 1.0.2-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20030401 Debian/1.0.2-2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20030821" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1; aggregator:Rojo; http://rojo.com/) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3.1) Gecko/20030721 wamcom.org" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031218" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040412" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20040805" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20041004" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20041010" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20050104" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20030522 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030702" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20040206" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030903 Firebird/0.6.1+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031030 MultiZilla/1.5.0.3l" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031125" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031222" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040625" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040914 Epiphany/1.2.5" + family: "Epiphany" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20050202 Linspire/1.6-5.1.0.50.linspire2.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20041029" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040803 MultiZilla/1.6.0.0e" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040806" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040810" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040901" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040917" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040918 Epiphany/1.4.6" + family: "Epiphany" + major: '1' + minor: '4' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040919 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040920" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040921" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040924 Debian/1.7.3-2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)" + family: "Epiphany" + major: '1' + minor: '4' + patch: '4' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040929" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040930" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041001 Epiphany/1.2.9" + family: "Epiphany" + major: '1' + minor: '2' + patch: '9' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041007 Epiphany/1.4.5" + family: "Epiphany" + major: '1' + minor: '4' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041007 Epiphany/1.4.6" + family: "Epiphany" + major: '1' + minor: '4' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041019 MultiZilla/1.7.0.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041023" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041105" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041202 Debian/1.7.3.x.1-39" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20050112" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5;) Gecko/20020604 OLYMPIAKOS SFP" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 firefox/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 IE/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Microsoft/IE6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 MSIE/5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041110 Firefox/1.1" + family: "Firefox" + major: '1' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041111 Firefox (MSIE 6.0)/1.0" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041111 Mozilla/1.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041118 Mozilla/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041217 Mnenhy/0.6.0.104" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041217 Mnenhy/0.7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041217 msie" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.7.0.2d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041219" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041220 MultiZilla/1.7.0.1f" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041222" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041223" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041224" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041226" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041226 Epiphany/1.4.7" + family: "Epiphany" + major: '1' + minor: '4' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041227" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041228 Epiphany/1.4.6" + family: "Epiphany" + major: '1' + minor: '4' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041229" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041229 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041231" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Debian/1.4-6 StumbleUpon/1.87" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Debian/1.7.5-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Epiphany/1.4.7" + family: "Epiphany" + major: '1' + minor: '4' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Epiphany/1.4.7 (Debian package 1.4.7-3)" + family: "Epiphany" + major: '1' + minor: '4' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 MultiZilla/1.7.0.1j" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050108" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050110 Spica/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050114 Microsoft/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050116" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050117" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050120" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050128" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050211 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050218" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050219 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050221 msie/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-6ubuntu1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050223 Firefox/1.0 (Debian package 1.0.x.2-15)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050309" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050302 HypnoToad/1.0.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050304 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050306 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050308 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050309 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050311 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050311 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050312 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050314 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050315 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050318 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050321 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050324 Debian/1.7.6-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050324 Epiphany/1.4.8 (Debian package 1.4.8-2)" + family: "Epiphany" + major: '1' + minor: '4' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050324 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050324 Firefox/1.0 (Ubuntu package 1.0.2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050325 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050325 Firefox/1.0.2 (Debian package 1.0.2-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050328 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050401 Firefox/1.0.2 (Debian package 1.0.2-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040618 Epiphany/1.2.6" + family: "Epiphany" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040903 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040907 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040909 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20041027 NaverBot/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a3) Gecko/20040729" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a3) Gecko/20040817" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a5) Gecko/20041121" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a5) Gecko/20041124" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a6) Gecko/20050107 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a6) Gecko/20050111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b2) Gecko/20050227" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050314" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; SkipStone 0.8.4) Gecko/20020722" + family: "SkipStone" + major: '0' + minor: '8' + patch: '4' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-AR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.5) Gecko/20031107 Debian/1.5-3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20050105 Debian/1.7.5-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20050105 Debian/1.7.5-1 StumbleUpon/1.999" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20050210 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.6) Gecko/20050303 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.6) Gecko/20050306 Firefox/1.0.1 (Debian package 1.0.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.6) Gecko/20050312 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fi-FI; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.4.2) Gecko/20040308" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.3) Gecko/20041020" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.5) Gecko/20050105 Debian/1.7.5-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.4.3) Gecko/20041004" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20050221 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-6ubuntu1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.6) Gecko/20050306 Firefox/1.0.1 (Debian package 1.0.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.6) Gecko/20050315 Firefox/1.0 (Ubuntu package 1.0.1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686) Gecko/20041107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; hu-HU; rv:1.7.5) Gecko/20041119 Firefox/1.0 (Debian package 1.0-3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; hu-HU; rv:1.7.6) Gecko/20050325 Firefox/1.0.2 (Debian package 1.0.2-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.4.3) Gecko/20041004" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.7.3) Gecko/20040922" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.7.3) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ko-KR; rv:1.7.5) Gecko/20041111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.6) Gecko/20040122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.5) Gecko/20050102" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.5) Gecko/20050111 Fedora/1.7.5-3.0.3.kde" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.6) Gecko/20050303 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.6) Gecko/20050306 Firefox/1.0.1 (Debian package 1.0.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.6) Gecko/20050322 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; PL; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; PL; rv:1.5) Gecko/20031020" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; PL; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.7.3) Gecko/20040930" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.7.5) Gecko/20050105 Debian/1.7.5-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041001 Superholio/0.10.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041020 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041113 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20050329 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.7.6) Gecko/20050315 Firefox/1.0 (Ubuntu package 1.0.1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; tr-TR; rv:1.7.2) Gecko/20040804 Epiphany/1.2.8" + family: "Epiphany" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i?86; en-US; rv:1.6) Gecko/20040116" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.3) Gecko/20041207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20050105 Debian/1.7.5-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20050107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20050221 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-6ubuntu1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.6) Gecko/20050306 Firefox/1.0.1 (Debian package 1.0.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.6) Gecko/20050325 Firefox/1.0.2 (Debian package 1.0.2-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux sparc; en-US; rv:1.5) Gecko/20041129" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; ca-AD; rv:1.7.5) Gecko/20050210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.3) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.3) Gecko/20041020" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050101" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050201" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050310" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.6) Gecko/20050228 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.6) Gecko/20050305" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; nl-NL; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.3) Gecko/20050117" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.5) Gecko/20041205 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.6) Gecko/20050308 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD macppc; en-US; rv:1.5) Gecko/20040102 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD macppc; en-US; rv:1.7.2) Gecko/20040825 Camino/0.8.1" + family: "Camino" + major: '0' + minor: '8' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.2.1) Gecko/20030228" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20040830 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20050110" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20050312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.7.6) Gecko/20050312 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; OpenVMS AlphaServer_ES40; en-US; rv:1.4) Gecko/20041126 FireFox/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OSF1 alpha; en-US; rv:1.4) Gecko/20030903" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.4) Gecko/20040126" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.4) Gecko/20040414" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.7.3) Gecko/20040919" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.7) Gecko/20041221" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.0.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.2) Gecko/20021211" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4) Gecko/20041214" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.3) Gecko/20040914" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.5) Gecko/20050105" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.6) Gecko/20050301 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.6) Gecko/20050313 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040629" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20041221" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; fr-FR; rv:1.7.5) Gecko/2004" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; System/V-POSIX alpha; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; UNICOS/mk 21164a(EV5.6) Cray T3E; en-US; huelk) Gecko/20040413 SynLabs/0.6.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X) Gecko/20021016" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.5 (compatible; alpha/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.666 [en] (X11; U; FreeBSD 4.5-STABLE i386)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.01 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 (BEOS; U ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (6.0; comtemptible)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 [en] (Atari 2600; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 [en] (Win32; Escape 5.03; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 [en] (Win32; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 [en] (X11; Linux 2.4.26 Sparc64) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 [en] (X11; Linux 2.6.10 Sparc 64) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 (Linux; Escape/5.0; acentic client)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.1 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.1 [ja] (X11; I; Linux 2.2.13-33cmc1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.2 [en] (BeOS; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.2 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7.00; msie" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7.02 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7.0 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7.1 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7.2 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7 [en] (Debian Sarge; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/9.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/9.0 (Atari2600; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/9.2 (Windows; U; Windows 3.11; en-US; rv:4.9.3) Gecko/20050213 Firefox/4.2" + family: "Firefox" + major: '4' + minor: '2' + patch: + - user_agent_string: "Mozilla/9.876 (alpha/06)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (compatible; X11; I; Linux 2.0.32 i586)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla Epinard" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla FireFox (compatible)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (FreeBSD 5.3-CURRENT)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (IE4 Compatible; I; Mac_PowerPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (IE5 Compatible; I; Mac_PowerPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla(IE Compatible)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (larbin2.6.3@unspecified.mail)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla Windows" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (X11; E; Linux )" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (X11; I; Linux 2.0.32 i286)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (X11; I; Linux 2.0.32 i586)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SEKTron alpha/06; AmigaOS" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 [en] (X11; U; Linux 2.6.4; en-US; rv:0.9.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:0.9.2) Gecko/2001" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010628" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.2.1) Gecko/20010901" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.3) Gecko/20010801" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4) Gecko/20010914" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4) Gecko/20010923" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux sparc64; en-US; rv:0.9.4) Gecko/20011029" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4.2) Gecko/20021112 CS 2000 7.0/7.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.5) Gecko/20011018" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en US; rv:0.9.6+)Gecko/20011122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.6+) Gecko/20011122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:0.9.8) Gecko/20020204" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:0.9.8) Gecko/20020204" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.8) Gecko/20020204" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (U; en-US; rv:0.9.9) Gecko/20020311" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.9) Gecko/20020408" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.9) Gecko/20020412 Debian/0.9.9-6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.9) Gecko/20020501" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.9) Gecko/20020513" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0rc1) Gecko/20020417" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0rc2) Gecko/20020510" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0rc3) Gecko/20020523" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0rc2) Gecko/20020510" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.0rc3) Gecko/20020524" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.0) Gecko/20020530" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.0.0) Gecko/20020530" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.0) Gecko/20020530" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.0) Gecko/20020530" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.0.0) Gecko/20020530" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.0.0) Gecko/20020605" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.0.0) Gecko/20020623 Debian/1.0.0-0.woody.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0+) Gecko/20020518" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020529" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020604" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020607" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020623 Debian/1.0.0-0.woody.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0; hi, Mom) Gecko/20020604" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.0.0) Gecko/20020529" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.0.0) Gecko/20020622 Debian/1.0.0-0.woody.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.0.0) Gecko/20020611" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20020730 AOL/7.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20020909" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20021023 Chimera/0.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20021219 Chimera/0.6+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.0.1) Gecko/20020830" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.0.1) Gecko/20020903" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20020809" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20020828" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20020830" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20020903" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20021003" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20021103" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20021105" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.2) Gecko/20021216" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20021120" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20021216" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20021216" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20030708" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20030716" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20031013" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.1) Gecko/20020826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.1) Gecko/20020826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1a) Gecko/20020611" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1b) Gecko/20020721" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.1) Gecko/20020826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-AT; rv:1.1) Gecko/20020826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.1) Gecko/20021005" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.1) Gecko/20030102" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.1) Gecko/20030104" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.1) Gecko/20020826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1a) Gecko/20020610" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.1) Gecko/20020827" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.1) Gecko/20020927" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/1.10 [en] (Compatible; RISC OS 4.37; Oregano 1.10)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Symbian OS/1.1.0)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2a) Gecko/20020910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2b) Gecko/20021016" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2) Gecko/20021126" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.2) Gecko/20021204" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2) Gecko/20021202" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2) Gecko/20021207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OSF1 alpha; en-US; rv:1.2) Gecko/20021205" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-GB; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; nl-NL; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.2.1) Gecko/20030324" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.2.1) Gecko/20030225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.2.1) Gecko/20021204" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.2.1) Gecko/20030225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1; aggregator:NewsMonster; http://www.newsmonster.org/) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021204" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021213 Debian/1.2.1-2.bunk" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20030124" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20030225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20030225,gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20030327" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20030502 Debian/1.2.1-9woody3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.2.1) Gecko/20030225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.2.1) Gecko/20030225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.2.1) Gecko/20030225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.2.1) Gecko/20030225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.2.1) Gecko/20030225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.2.1) Gecko/20021125" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.2.1) Gecko/20030228" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; ru-RU; rv:1.2.1) Gecko/20030721" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.2.1) Gecko/20030711" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; fr-FR; rv:1.2.1) Gecko/20030711" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 (X11; U; Linux 2.6.13 i686; en-US; rv:1.2.9) Gecko/20050612 MSIE (Debian FAST Browser) v15.23 - All rights reserved - Unix -
Error Processing table...
Line 43
" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.3) Gecko/20030616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.3a) Gecko/20021212" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.3b) Gecko/20030210" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.3; MultiZilla v1.4.0.3J) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.3a) Gecko/20021212" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.3b; MultiZilla v1.3.1 (a)) Gecko/20030210" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.3b) Gecko/20030323" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; HP-UX 9000/785; en-US; rv:1.3) Gecko/20030321" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.3) Gecko/20030313" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3a) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3b) Gecko/20030210" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030313" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030314" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030408" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030623" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030708 Debian/1.3-4.lindows43" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.3b) Gecko/20030317" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.3) Gecko/20030317" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.3a) Gecko/20021211" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.3) Gecko/20030314" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:1.3.1) Gecko/20030721 wamcom.org" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:1.3.1) Gecko/20030723 wamcom.org" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.3.1) Gecko/20030425" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.3.1) Gecko/20030425" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.3.1) Gecko/20030425" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; el-gr; rv:1.3.1) Gecko/20030425" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.3.1) Gecko/20030425" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.3.1) Gecko/20030425" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.3.1) Gecko/20030524" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.3.1) Gecko/20030525" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.3.1) Gecko/20040413" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.3.1) Gecko/20040528" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3.1) Gecko/20030425" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3.1) Gecko/20030428" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3.1) Gecko/20030517" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.3.1) Gecko/20030428" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030507" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030529" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-us; rv:1.4)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4a) Gecko/20030401" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4b) Gecko/20030507" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030529" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030612" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.4) Gecko/20030624/7.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.4a) Gecko/20030401" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20030709" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20030715" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20030730" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20031008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20040127" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20040324" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; HP-UX 9000/785; en-US; rv:1.4) Gecko/20030730" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ca; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; da-DK; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.4) Gecko/20030821" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4a) Gecko/20030401" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20030507" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030529" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030617" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030703" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030704" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030714 Debian/1.4-2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030716" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030728" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030730" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030805" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030807" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030818" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030821" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030908 Debian/1.4-4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030915" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030922" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20031110" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20031111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20031112" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20031119 Debian/1.4.0.x.1-20" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20031211" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20031212" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20040107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20040116" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Larbin/2.6.3 (larbin@unspecified.mail)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Larbin/2.6.3 larbin@unspecified.mail" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.4) Gecko/20031111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; gl-ES; rv:1.4) Gecko/20030703" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.4) Gecko/20030630" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.4) Gecko/20030922" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.4) Gecko/20030908" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenVMS AlphaServer_ES40; en-US; rv:1.4) Gecko/20030826 SWB/V1.4 (HP)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.4b) Gecko/20030523" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.4) Gecko/20040214" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.4) Gecko/20040510" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4) Gecko/20030701" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4) Gecko/20031128" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4) Gecko/20040414" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-0; en-US; rv:1.4.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4.1) Gecko/20031008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (MacOSX; U; MacOSX; en-US; rv:1.4.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.4.1) Gecko/20031014" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4.1) Gecko/20031008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4.1) Gecko/20031008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4.1; MultiZilla v1.5.0.2j) Gecko/20031008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4.1) Gecko/20031008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.4.1) Gecko/20031008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031008" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031008 Debian/1.4-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031030" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 MSIE" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20040312 Debian/1.4.1-0jds1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20040406" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.4.1) Gecko/20031030" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.4.1) Gecko/20031114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.4.1) Gecko/20040406" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.4.1) Gecko/20031030" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.4.1) Gecko/20031114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.4.1) Gecko/20031114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.4.1) Gecko/20031030" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.4.1) Gecko/20031114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.4.1) Gecko/20031209" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.4.1) Gecko/20031030" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.4.1) Gecko/20031114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4.1) Gecko/20031125" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.4.2) Gecko/20040220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.4.2) Gecko/20040301" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040301" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040308" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040323" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040326" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040330" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040428" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040921" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.4.2) Gecko/20040308" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.4.2) Gecko/20040308" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.4.2) Gecko/20040220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.4.3) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20040924" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.3) Gecko/20040930" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.4.3) Gecko/20040930" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.5b) Gecko/20030904" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.1" + family: "K-Meleon" + major: '0' + minor: '8' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2" + family: "K-Meleon" + major: '0' + minor: '8' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; es-ES; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; es-ES; rv:1.5) Gecko/20031007, Mozilla/5.0 (Windows; U; Win98; es-ES; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; PL; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.5b) Gecko/20030827" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; fr-FR; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5a) Gecko/20030718" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5b) Gecko/20030827" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5) Gecko/20030916" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5) Gecko/20030925" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5 ) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2" + family: "K-Meleon" + major: '0' + minor: '8' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; PL; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.5) Gecko/20031006" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.5b) Gecko/20030827" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.5b) Gecko/20030827" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5b) Gecko/20030827" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20030916" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20030925" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.5) Gecko/20031006" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-AT; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2" + family: "K-Meleon" + major: '0' + minor: '8' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; rv:1.5a; FreeBSD)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5a) Gecko/20030712" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5b) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031028" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20040102" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20040105" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20040110" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20040921" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; HP-UX 9000/785; en-US; rv:1.5) Gecko/20031027" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.5) Gecko/20031015" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.5) Gecko/20031031" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.5) Gecko/20031107 Debian/1.5-3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030718" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030827" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030831" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20030917" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20030925" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031009" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031024" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031031" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Debian/1.5-3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Debian/1.5-3 StumbleUpon/1.906" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031111 Debian/1.5-2.backports.org.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031115 Debian/1.5-3.he-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031202" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031211 Debian/1.5-2.0.0.lindows0.0.43.45+0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031224" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031231" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20040225 Debian/1.5-2.0.0.lindows0.0.65.45+0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20040414" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.5) Gecko/20031007 Debian/1.6-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.5) Gecko/20031007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.5a) Gecko/20030723" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.5) Gecko/20031016" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.5) Gecko/20031222" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.5.1) Gecko/20031120" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5.1) Gecko/20031207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.6b) Gecko/20031208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-AT; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.6) Gecko/20040113 Relativity" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.6) Gecko/20040206 MSIE/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.6; lwpc5440) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; et-EE; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; hu; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; ja-JP; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pl-PL; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-AT; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.6b) Gecko/20031208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; nl-NL; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; cs-CZ; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.6b) Gecko/20031208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6a) Gecko/20031030" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6a) Gecko/20031105" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6b) Gecko/20031208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 MSIE/5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Poweranemone/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Powergoat/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Powerpig/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.6+) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; nb-NO; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; PL; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.6) Gecko/20040407" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-TW; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ar; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.6b) Gecko/20031208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6a) Gecko/20020430" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6a) Gecko/20031030" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6b) Gecko/20031208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113 |sncwebguy|" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040119 MyIE2" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 GoogleBot/1.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 KPTX3/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Mozilla/5.0 StumbleUpon/1.904" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 msie/6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 MSIE/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Spacedonkey/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Telnet/4.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6; RattBrowser) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fi-FI; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.6) Gecko/20040113,gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nb-NO; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; PL; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-AT; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; fr-FR; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; pt-BR; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; DragonFly i386; en-US; rv:1.6) Gecko/20040518" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6a) Gecko/20031207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6a) Gecko/20040525" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040120" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040308" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040313" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040319" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040324" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040412" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040414" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040512" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; ru-RU; rv:1.6) Gecko/20040406" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.6) Gecko/20040122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040413" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040413 Debian/1.6-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040527" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040530 Debian/1.6-6.backports.org.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.6) Gecko/20040216 Debian/1.6.x.1-10" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-IE; rv:1.6) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-IE; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6a) Gecko/20031029" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6a) Gecko/20031103" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6b) Gecko/20031113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6b) Gecko/20031208" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6b) Gecko/20031210" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Fucking cocksmoker" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040112" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040116" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040117" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040119" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040122 Debian/1.6-0.backports.org.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040122 Debian/1.6-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040122 Debian Sarge" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040123" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040124" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040127" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040130" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040203" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040204" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 dufus/42" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-us; rv:1.6) Gecko/20040207 firefox/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 InterBank 4.32" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040211" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040215 MSIE/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040216 Debian/1.6.x.1-10" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040218" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040223" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040224" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040229" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040303" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040306" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040307" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040308" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040310" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040312 Debian/1.6-3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040314" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040318" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040321" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040324" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040325" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040326" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040329" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040330" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040401 Debian/1.6-4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040402 Debian/1.6-3.backports.org.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040403" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040411" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Debian/1.6-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040422" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040423" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040425" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040426 Debian/1.4-4 StumbleUpon/1.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040429" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040430" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040505" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040506" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040506 Powerstarfish/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040507" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040510" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040518" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040528 Debian/1.6-7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040530 Debian/1.6-6.backports.org.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6 kni-rat-sam 20041007) Gecko/20040510" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6; Using IIS? Visit www.glowingplate.com/iis ) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040123 Debian/1.6-1.he-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040413 Debian/1.6-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040528 Debian/1.6-7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-CA; rv:1.6) Gecko/20040207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6b) Gecko/20031210" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6) Gecko/20040122 Debian/1.6-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6) Gecko/20040126" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6) Gecko/20040207 AnyBrowser /1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6) Gecko/20040413 Debian/1.6-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.6) Gecko/20040429" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.6) Gecko/20040510" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; nl-NL; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.6) Gecko/20040124" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; PL; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; PL; rv:1.6) Gecko/20040122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.6) Gecko/20040528 Debian/1.6-7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.6) Gecko/20040331" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.6) Gecko/20040413 Debian/1.6-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.6) Gecko/20040115" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; zh-TW; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; zh-TW; rv:1.6) Gecko/20040122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; zh-TW; rv:1.6) Gecko/20040510" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux powerpc; en-US; rv:1.6) Gecko/20040207 FireFox/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.6) Gecko/20040414 Debian/1.6-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; eo-EO; rv:1.6) Gecko/20040414 Debian/1.6-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.6) Gecko/20040113" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.6) Gecko/20040114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.6) Gecko/20040510" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.6) Gecko/20040405" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.6) Gecko/20040408" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20040314" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20040324" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20040820" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20040902" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.6) Gecko/20040117" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6a) Gecko/20031125" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6) Gecko/20040116" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6) Gecko/20040211 Lightningyak/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; es-ES; rv:1.6) Gecko/20040116" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (BMan; U; BManOS; bg-BG; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (en-AU; rv:1.7)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; de-AT; rv:1.7a) Gecko/20040225" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7a) Gecko/20040219" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7b) Gecko/20040421 netscape7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7a) Gecko/20040219" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040320" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040321" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040323" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040401" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040404" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040614 Firefrog/0.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040626 FireFox/0.9.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040626 MSIE/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040730 Googlebot/2.1/2.1" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.7b+) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; hu-HU; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; nl-NL; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; da-DK; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7a) Gecko/20040123" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7a) Gecko/20040219" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040328" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040403" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040408" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040410" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040412" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040520 K-Meleon/0.8" + family: "K-Meleon" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Moonsnake/0.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Powersnake/0.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Powerwhale/0.8" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Pussyfag/0.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Spacebunny/0.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040616 WebWasher 3.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Moonlizard/0.9.1 (:w00t: to the world and the world :w00t:s back!)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)/0.9.1" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firepig/0.9.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Lightningspider/0.9.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Telnet/4.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Ungawa/0.9.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Waterphoenix/0.9.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Webpony/0.8 ( polymorph)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Superlizard/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Superraccoon/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 XboxStore.com" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7a) Gecko/20031129" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-AT; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; Slackware; Linux i686; en-US; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; AIX 0006FADF4C00; en-US; rv:1.7b) Gecko/20040318" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7b) Gecko/20040422" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7b) Gecko/20040429" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040612" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; ja-JP; rv:1.7) Gecko/20040705" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; de-AT; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7) Gecko/20040619" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7) Gecko/20040724" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7) Gecko/20040803 Nevermind/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-CA; rv:1.7) Gecko/20040704" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-EU; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-EU; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-EU; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-UK; rv:1.7a) Gecko/20040105" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7a) Gecko/20040218" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040312" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040316" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040322" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040405" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040408" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040421" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040514" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040608" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040612" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040615 Lightningoyster/0.9 (Mozilla/4.0 (compatible; MSIE 6.0; WinNT; ATHMWWW1.1;))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040617" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040619" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040620" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040622" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040624 Debian/1.7-2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040626" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040626 Microsoft/IE" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040626 Mozilla/4.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040702" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040703" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040704 Debian/1.7-4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040724" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040725" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040728" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040729" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040803 Lightningslimemold/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040805 Googlebot/2.1" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040808 Powertiger/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040809" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040828 Seagoat/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7rc1) Gecko/20040527" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fi-FI; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7) Gecko/20040617" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; PL; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7) Gecko/20040616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; zh-TW; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7) Gecko/20040627" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Mac OS; en-US; rv:1.7) Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OSF1 alpha; en-US; rv:1.7) Gecko/20040708" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7b) Gecko/20040319" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7c) Gecko/" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040517" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040610" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040618" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040623" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040920" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7.2 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) )" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707 Mnenhy/0.6.0.104" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fi-FI; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.1) Gecko/20040707 WebWasher 3.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.1) Gecko/20040707" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD 5.2.1 i686; en-US; rv:1.7.1+) Gecko/20020518" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.1) Gecko/20040724" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.1) Gecko/20040726" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040715" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040715 Debian/1.7.1-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040726 Debian/1.7.1-4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040730" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.1) Gecko/20040802 Debian/1.7.1-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; Athlon64; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; PL; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.2) Gecko/20040815" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.2) Gecko/20040816" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2;) Gecko/20020604 OLYMPIAKOS SFP" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040726" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040808" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040808 Debian/1.7.2-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040809" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040809 Debian/1.7.2-0woody1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040810 Debian" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040810 Debian/1.7.2-2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040815" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040816" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040819" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040819 Debian/1.7.2-3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040820 Debian/1.4-3 StumbleUpon/1.79" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040820 Debian/1.7.2-4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040825" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040906" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.2) Gecko/20040818" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; nl-NL; rv:1.7.2) Gecko/20040804" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.2) Gecko/20040829" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.2) Gecko/20040906" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.7.2) Gecko/20040823" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; de-AT; rv:1.7.2) Gecko/20040906" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.2) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.2) Gecko/20040813" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.2) Gecko/20040809" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.2) Gecko/20040810" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.2) Gecko/20040826" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; cs-CZ; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7.3) Gecko/20040910,gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040913 IE/0.10" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20040910 WebWasher 3.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.3) Gecko/20040910" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 WaterDog/0.10.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041111" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041207" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040922" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.3) Gecko/20040914" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.3) Gecko/20040919" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.3) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040914" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040916" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040918" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040919" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040922" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040922 Debian/1.7.3-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040925" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040926" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041006" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041006 Debian/1.7.3-4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041007 Debian" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041013" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041026" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041027" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041101" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041108" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.3) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.3) Gecko/20040913" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5 StumbleUpon/1.999" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; it-IT; rv:1.7.3) Gecko/20041007 Debian/1.7.3-5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.3) Gecko/20040921" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.3) Gecko/20041022" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Slackware GNU/Linux i686; pl-PL; rv:1.7.3) Gecko/20040913 --==MOZILLA RULLEZ ;)==--" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.3) Gecko/20040919" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.4) Gecko/20040926" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; ja-JP; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U; rv:1.7.5) Gecko/20041107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041107 Refrozen.com/2.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; it-IT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 MSIE/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.7.5) Gecko/20041210 MSIE/5.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; da-DK; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 google/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 IE/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 MSIE/1.0 (ax)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 TheBlacksheepbrowser/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217 Mnenhy/0.6.0.104" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; de-AT; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; ; Win98; en; rv:1.7.5) Gecko/20041107" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041220" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.5) Gecko/20041213" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041128 Windows" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041221" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041228 Fedora/1.7.5-2.home" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-AR; rv:1.7.5) Gecko/20041108 MSIE/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7rc1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a1) Gecko/20040520" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a4) Gecko/20040927" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a5) Gecko/20041122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040511" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.8a4) Gecko/20040930 Mnenhy/0.6.0.104" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8a) Gecko/20040425 `The Suite'" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.8a1) Gecko/20040520" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a1) Gecko/20040520" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040521" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040714" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a3) Gecko/20040817" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a5) Gecko/20041122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040420" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.8a2+) Gecko/20040524" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.8a2) Gecko/20040714" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.8a2) Gecko/20040714" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.8a4) Gecko/20040927" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a1) Gecko/20040520" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040607" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040704" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040713" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040714" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040812" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040817" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a4) Gecko/20040923" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a5) Gecko/20041122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041201" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041217" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040417" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040419" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040420" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040423" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040427" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040502" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040511" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.8a1) Gecko/20040520" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.8a2) Gecko/20040715" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; IRIX64 IP30; en-US; rv:1.8)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a1) Gecko/20040520" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a2) Gecko/20040627" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a2) Gecko/20040714" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a3) Gecko/20040808" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a4) Gecko/20040927" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a5) Gecko/20041117" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a5) Gecko/20041122" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a5) Gecko/20041123" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040424" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040502" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8a3) Gecko/20040822" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.8a4) Gecko/20040929" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X; MSIE Incompatible; SyNiX; es-AR; rv:1.8a2/s) Gecko/20040814" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/2.02" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 (compatible; MSIE 6.0; X11; U; Linux i686; en-US; rv:2.5 P)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/3.0 (Compatible;Viking/1.8)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01Gold (Macintosh; I; 68K)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01Gold (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-GB; rv:1.0.2) Gecko/20020924 AOL/7.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.2) Gecko/20020924 AOL/7.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20030306 Camino/0.7" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.5b) Gecko/20030917 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.6a) Gecko/20031021 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.6b) Gecko/20031205 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7a) Gecko/20040105 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7a) Gecko/20040110 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040403 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040404 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040405 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040416 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040425 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040428 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040511 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040518 Camino/0.7+" + family: "Camino" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040623 Camino/0.8" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a2) Gecko/20040602 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a2) Gecko/20040607 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a2) Gecko/20040610 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a3) Gecko/20040804 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a3) Gecko/20040811 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20041130 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20041222 Camino/0.8+" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.2) Gecko/20040825 Camino/0.8.1" + family: "Camino" + major: '0' + minor: '8' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.2) Gecko/20040827 Camino/0.8.1" + family: "Camino" + major: '0' + minor: '8' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041201 Camino/0.8.2" + family: "Camino" + major: '0' + minor: '8' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040517 Camino/0.8b" + family: "Camino" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20021220 Chimera/0.6+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030630 Epiphany/1.0" + family: "Epiphany" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030821 Epiphany/1.0" + family: "Epiphany" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030630 Epiphany/1.0.1" + family: "Epiphany" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.1) Gecko/20031114 Epiphany/1.0.4" + family: "Epiphany" + major: '1' + minor: '0' + patch: '4' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031208 Epiphany/1.0.6" + family: "Epiphany" + major: '1' + minor: '0' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Epiphany/1.0.6" + family: "Epiphany" + major: '1' + minor: '0' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031229 Epiphany/1.0.6" + family: "Epiphany" + major: '1' + minor: '0' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040223 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.6) Gecko/20040115 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040114 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.6) Gecko/20040115 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040114 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040115 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040118 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040317 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040324 Epiphany/1.0.7" + family: "Epiphany" + major: '1' + minor: '0' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040124 Epiphany/1.0.8" + family: "Epiphany" + major: '1' + minor: '0' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040312 Epiphany/1.1.12" + family: "Epiphany" + major: '1' + minor: '1' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040415 Epiphany/1.1.12" + family: "Epiphany" + major: '1' + minor: '1' + patch: '12' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040415 Epiphany/1.2.2" + family: "Epiphany" + major: '1' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040206 Epiphany/1.2.2" + family: "Epiphany" + major: '1' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040322 Epiphany/1.2.2" + family: "Epiphany" + major: '1' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040429 Epiphany/1.2.3" + family: "Epiphany" + major: '1' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040404 Epiphany/1.2.3" + family: "Epiphany" + major: '1' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040510 Epiphany/1.2.4" + family: "Epiphany" + major: '1' + minor: '2' + patch: '4' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040312 Epiphany/1.2.5" + family: "Epiphany" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040528 Epiphany/1.2.5" + family: "Epiphany" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040906 Epiphany/1.2.5" + family: "Epiphany" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040413 Epiphany/1.2.5" + family: "Epiphany" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.6) Gecko/20040414 Epiphany/1.2.5" + family: "Epiphany" + major: '1' + minor: '2' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040628 Epiphany/1.2.6" + family: "Epiphany" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Epiphany/1.2.6" + family: "Epiphany" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040624 Epiphany/1.2.6" + family: "Epiphany" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040625 Epiphany/1.2.6" + family: "Epiphany" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040803 Epiphany/1.2.6" + family: "Epiphany" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040404 Epiphany/1.2.6.90" + family: "Epiphany" + major: '1' + minor: '2' + patch: '6' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040803 Epiphany/1.2.7" + family: "Epiphany" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040810 Epiphany/1.2.7" + family: "Epiphany" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040818 Epiphany/1.2.7" + family: "Epiphany" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040819 Epiphany/1.2.7" + family: "Epiphany" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040922 Epiphany/1.2.7" + family: "Epiphany" + major: '1' + minor: '2' + patch: '7' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.2) Gecko/20040821 Epiphany/1.2.8" + family: "Epiphany" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.2) Gecko/20041016 Epiphany/1.2.8" + family: "Epiphany" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040804 Epiphany/1.2.8" + family: "Epiphany" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040807 Epiphany/1.2.8" + family: "Epiphany" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040820 Epiphany/1.2.8" + family: "Epiphany" + major: '1' + minor: '2' + patch: '8' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040510 Epiphany/1.3.0" + family: "Epiphany" + major: '1' + minor: '3' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041112 Epiphany/1.4.4" + family: "Epiphany" + major: '1' + minor: '4' + patch: '4' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020 Epiphany/1.4.4" + family: "Epiphany" + major: '1' + minor: '4' + patch: '4' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041113 Epiphany/1.4.4" + family: "Epiphany" + major: '1' + minor: '4' + patch: '4' + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.3) Gecko/20041126 Epiphany/1.4.5" + family: "Epiphany" + major: '1' + minor: '4' + patch: '5' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041116 Epiphany/1.4.6" + family: "Epiphany" + major: '1' + minor: '4' + patch: '6' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030504 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030610 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4b) Gecko/20030623 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; IRIX64 IP30; en-US; rv:1.4b) Gecko/20030618 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030722 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Solaris Sparc; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4b) Gecko/20030517 Mozilla Firebird/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Idefix hic erat!; Fenestra 50a.Chr.n.; la; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5a) Gecko/20030801 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030801 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030811 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030905 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030912 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030918 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030821 Mozilla Firebird/0.6.1+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030910 Firebird/0.6.1+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.5a) Gecko/20030908 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.5a) Gecko/20030729 Mozilla Firebird/0.6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.5) Gecko/20031026 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; cs-CZ; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6a) Gecko/20031002 Firebird/0.7+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6a) Gecko/20031105 Firebird/0.7+ (aebrahim)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6b) Gecko/20031208 Firebird/0.7+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6b) Gecko/20031216 Firebird/0.7+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040114 Firebird/0.7+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040429 Firebird/0.7+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; PL; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; fr; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031023 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031208 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20040415 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031015 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031110 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031120 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031215 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031225 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20040114 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20040120 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20040130 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20040201 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6a) Gecko/20030924 Firebird/0.7+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6a) Gecko/20031012 Firebird/0.7+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040116 Firebird/0.7+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.5) Gecko/20031007 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.5) Gecko/20031020 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.5) Gecko/20031202 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.5) Gecko/20040114 Firebird/0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7a) Gecko/20040113 Firebird/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7a) Gecko/20040210 Firebird/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7a) Gecko/20040120 Firebird/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7a) Gecko/20040129 Firebird/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040410 Firebird/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20040409 Firebird/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7a) Gecko/20040118 Firebird/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7a) Gecko/20040210 Firebird/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Firefox)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win64 (AMD64); en-US; Firefox" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040815 Lightningraccoon/0.9.1+ (All your Firefox 0.9.1+ are belong to Firesomething!)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040413 Waterdog/0.8.0+ (Firefox/#version# polymorph)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox_123/0.9.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.6) Gecko/20040210 Firesalamandre/0.8 (User Agent modifie grace a Firesomething. Telechargez Firefox en francais sur http://frenchmozilla.org/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux; en-US) Gecko/20040101 Firefox" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Firefox (Gecko)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla Dark Firefox" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla (Windows;+U;+Windows; en-GB) Gecko Firefox" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; rv:1.7.3) Gecko/20040913 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; rv:1.7.3) Gecko/20040913 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.3) Gecko/20040925 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040908 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040913 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040913 Firefox/0.10.1 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040913 Firefox/0.10.1 WebWasher 3.3" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040913 Firefox/0.10 StumbleUpon/1.999" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20040928 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10 StumbleUpon/1.996" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040911 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Firefox/0.10.1 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Firefox/0.10 Mnenhy/0.6.0.104" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Firefox/0.10 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040928 Firefox/0.10 (MOOX M2)" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; rv:1.7.3) Gecko/20040913 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; rv:1.7.3) Gecko/20040913 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; rv:1.7.3) Gecko/20040914 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041011 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1 StumbleUpon/1.999" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040911 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040913 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040914 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040919 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040923 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040924 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040928 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040929 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041001 Firefox/0.10.1 Mnenhy/0.6.0.104" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041003 Firefox/0.10" + family: "Firefox" + major: '0' + minor: '10' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; rv:1.7.3) Gecko/20040911 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; rv:1.7.3) Gecko/20040913 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (MacOS; U; Panther; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; rv:1.7.3) Gecko/20040913 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; rv:1.7.3) Gecko/20040913 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041103 Mozilla Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041109 Firefox/0.10.1 (MOOX M3)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040614 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.7) Gecko/20040803 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040913 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040913 Firefox/0.10.1 (Firefox/0.10.1 rebrand: Mozilla Firesomething)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040930 Firefox/0.10.1 (MOOX M3)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20041001 Firefox/0.10.1 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20041006 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20041001 Firefox/0.10.1 (MOOX M3)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/0.10.1 (MOOX M2)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a5) Gecko/20041031 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040910 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040911 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1 (ax)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1 StumbleUpon/1.999" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Thunderchicken/0.10.1 (All your Firefox/0.10.1 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.3) Gecko/20041027 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; rv:1.7.3) Gecko/20040913 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; rv:1.7.3) Gecko/20040913 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; Slackware; Linux i686; Slackware; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; IRIX64 6.5; rv:1.7.3) Gecko/20041020 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040911 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040913 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040914 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040916 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040921 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040928 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041001 Firefox/0.10.1 (Linux/GTK)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041001 Firefox/Slackware-0.10.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041003 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041005 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041007 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041008 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041011 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041012 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041013 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041014 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041015 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041019 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041020 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041021 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041023 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041025 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041026 Firefox/0.10.1 (Debian package 0.10.1+1.0PR-4)" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041028 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041031 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041103 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041106 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041110 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041119 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041123 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20041202 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; rv:1.7.3) Gecko/20041022 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; rv:1.7.3) Gecko/20041020 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; rv:1.7.3) Gecko/20050220 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; rv:1.7.3) Gecko/20040916 Firefox/0.10.1" + family: "Firefox" + major: '0' + minor: '10' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Linux) Firefox/0.3" + family: "Firefox" + major: '0' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20041122 Firefox/0.5.6+" + family: "Firefox" + major: '0' + minor: '5' + patch: '6' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20041122 Firefox/0.5.6+" + family: "Firefox" + major: '0' + minor: '5' + patch: '6' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.6 StumbleUpon/1.73" + family: "Firefox" + major: '0' + minor: '6' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040407 Firefox/0.6 StumbleUpon/1.66" + family: "Firefox" + major: '0' + minor: '6' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040614 Firefox/0.6.1 StumbleUpon/1.89" + family: "Firefox" + major: '0' + minor: '6' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 Firefox/0.6.1 StumbleUpon/1.87" + family: "Firefox" + major: '0' + minor: '6' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 Firefox/0.6 StumbleUpon/1.902" + family: "Firefox" + major: '0' + minor: '6' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041116 Firefox/0.6.1 StumbleUpon/1.87" + family: "Firefox" + major: '0' + minor: '6' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050110 Firefox/0.6.1 StumbleUpon/1.8 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '0' + minor: '6' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.5) Gecko/20050101 Firefox/0.6.4" + family: "Firefox" + major: '0' + minor: '6' + patch: '4' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.7 StumbleUpon/1.901" + family: "Firefox" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.7 StumbleUpon/1.902" + family: "Firefox" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.7 StumbleUpon/1.904" + family: "Firefox" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040310 Firefox/0.7 StumbleUpon/1.895" + family: "Firefox" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.7 StumbleUpon/1.9" + family: "Firefox" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040313 Firefox/0.7" + family: "Firefox" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040626 Firefox/0.7 StumbleUpon/1.9" + family: "Firefox" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040809 Firefox/0.7 StumbleUpon/1.89" + family: "Firefox" + major: '0' + minor: '7' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 Firefox/0.8 Mozilla/5.0 (compatible; Konqueror/3.2; Linux) (KHTML, like Gecko)" + family: "Konqueror" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.7b) Gecko/20040410 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.7b) Gecko/20040412 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Linux) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Firefox/0.8; Win32) Gecko/20040206" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Linux; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.903" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040308 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040311 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040314 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7b) Gecko/20040325 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040509 Firefox/0.8.0+ (MMx2000)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040519 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040531 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040608 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040608 Firefox/0.8.0+ StumbleUpon/1.99" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a2) Gecko/20040616 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040417 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040501 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040503 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040510 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040513 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a) Gecko/20040517 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; fr; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; rv:1.8a2) Gecko/20040522 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Njindonjs HR; en-US; rv:1.6) Gecko/20040206 Firefox/0.8)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.908" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7b) Gecko/20040304 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7b) Gecko/20040318 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040608 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040608 Moonbadger/0.8.0+ (All your Firefox/0.8.0+ are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040803 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8a2) Gecko/20040525 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8a) Gecko/20040504 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; it-IT; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; ja-JP; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pt-BR; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; ru-RU; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; fr; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.6) Gecko/20040206 Firefox/0.8 (Firefox/0.8)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7) Gecko/20040803 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 (All your Firefox/0.8 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 (ax)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.904" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.905" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.908" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.909" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Moonbird/0.8 (Firefox/0.8 polymorph)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Superwolf/0.8 (All your Firefox/0.8 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040210 Firefox/0.8 (www.proxomitron.de)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.8 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7a) Gecko/20040218 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040226 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040304 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040320 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040404 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040414 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040417 Firefox/0.8.0+ (MozJF)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040524 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040605 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040608 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040608 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040608 Firefox 0.8+/0.8.0+" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040613 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040614 Firefox/0.8 StumbleUpon/1.993" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.8 StumbleUpon/1.994" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a1) Gecko/20040520 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040521 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040523 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040525 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040604 Firefox/0.8.0+ (stipe) (Proxomitron Naoko 4.51)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040608 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040608 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040421 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040422 Firefox/0.8.0+ (TierMann VC++Tools)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040427 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040504 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040507 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040510 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040511 Firefox/0.8.0+ (ax)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040512 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a) Gecko/20040518 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7b) Gecko/20040412 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7b) Gecko/20040302 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.6) Gecko/20040206 Firefox/0.8 (Proud Firefox user - IE suckz)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7) Gecko/20040803 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-CA; rv:1.8a) Gecko/20040508 Firefox/0.8 Royal Oak (Mozilla)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-NZ; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firecow/0.8 (Firefox/0.8 Get over it!)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 (ax)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 - <>" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 (John Bokma, http://johnbokma.com/)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 MSIE 5" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.903" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.906" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.907 (All your Firefox/0.8 StumbleUpon/1.907 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.908" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.909" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Lightningdog/0.8 (All your Firefox/0.8 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Waterworm/0.8 (All your Firefox/0.8 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040210 Firefox/0.8 (Lohvarn)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040210 Firefox/0.8 (stipe)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.8 StumbleUpon/1.908" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050223 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7a) Gecko/20040221 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040302 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040310 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040313 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040315 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040318 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040321 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040321 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040321 Firefox/0.8.0+ (mmoy)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040322 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040323 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040324 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040326 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040327 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040329 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040330 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040331 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040331 Firefox/0.8.0+ (scragz)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040403 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040404 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040406 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040406 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040407 Firefox/0.8.0+ (djeter)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040408 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040408 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040409 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040410 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040411 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040412 Firefox/0.8.0+ (mmoy-O2-GL7-SSE2-crc32-quek01235)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040512 Firefox/0.8.0+ (MOOX)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040520 Firefox/0.8.0+ (MOOX-AV)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040521 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040521 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040523 Firefox/0.8.0+ (MOOX-AV)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040529 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040530 Firefox/0.8.0+ (Lohvarn)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040601 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040601 Firefox/0.8.0+ (MOOX-TK)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040607 Firefox/0.8.0+ (MOOX-AV)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040608 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040608 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040610 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Firefox/0.8 StumbleUpon/1.909" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Waternarwhal/0.8 (Firefox/0.8)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Firefox/0.8 StumbleUpon/1.909" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040629 Firefox/0.8 (MOOX-AV)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.8 Gumby" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.8 StumbleUpon/1.909" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.8 StumbleUpon/1.994" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.8 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a1) Gecko/20040520 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040521 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040522 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040522 Firefox/0.8.0+ (MOOX-TK)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040523 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040524 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040524 Firefox/0.8.0+ (BlueFyre)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040525 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040526 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040527 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040601 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040602 Firefox/0.8.0+ (bangbang023)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040605 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040710 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040807 Firefox/0.8 StumbleUpon/1.99" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040415 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040417 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040425 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040426 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040428 Firefox/0.8.0+ (dbright)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040430 Firefox/0.8.0+ (mmoy-O2-GL7-SSE2-crc32)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040502 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040502 Firefox/0.8.0+ (scragz)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040503 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040503 Firefox/0.8.0+ (mmoy-Pentium4a)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040504 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040505 Firefox/0.8.0+ (MOOX)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040507 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040512 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040516 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040517 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040518 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040518 Firefox/0.8.0+ (mmoy-2004-05-05-Pentium4b)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.6) Gecko/20040206 Firefox 0.8/0.8 (MSIE 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.6) Gecko/20040206 Firefox/0.8 StumbleUpon/1.906" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fi-FI; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.6) Gecko/20040209 Firefox/0.8 (Oxs G7 SSE optimized)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.8 StumbleUpon/1.99" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7) Gecko/20040608 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr-TR; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; de-DE; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040608 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040803 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040803 Firefox/0.8 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8a2) Gecko/20040601 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; cs-CZ; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040606 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; en-US; rv:1.6) Gecko/20040227 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040213 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040218 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040303 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040317 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040405 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040422 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040425 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040429 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040503 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040504 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040610 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040627 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040805 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040812 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; ja-JP; rv:1.6) Gecko/20040429 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.6) Gecko/20040212 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.6) Gecko/20040227 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.6) Gecko/20040428 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.6) Gecko/20040612 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.8a) Gecko/20040418 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.6) Gecko/20040429 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.6) Gecko/20040506 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-UK; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 Firefox/0.8 StumbleUpon/1.904" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 Firefox/0.8 StumbleUpon/1.99" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 Firefox/0.8 TGB579860FilterStats" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040208 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040209 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040211 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040212 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040216 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040220 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040221 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040222 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040223 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040224 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040226 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040227 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040228 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040229 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040301 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040301 Firefox/0.8 StumbleUpon/1.909" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040302 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040308 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040310 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040316 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040317 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040317 Firefox/0.8 - www.ubuntulinux.org" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040322 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040323 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040324 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040327 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040330 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040402 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040403 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040404 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040405 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040405 Firefox/0.8.0+ StumbleUpon/1.895" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040407 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040412 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040415 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040416 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040417 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040418 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040420 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040421 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040422 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040423 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040424 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040425 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040426 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040427 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040428 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040429 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040501 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040502 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040503 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040504 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040506 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040508 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040509 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040510 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040513 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040514 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040515 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040517 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040518 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040519 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040522 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040523 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040527 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040530 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040531 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040602 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040611 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040612 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040621 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040630 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040701 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040707 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040713 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040715 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040726 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.8 StumbleUpon/1.904" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.8 StumbleUpon/1.906" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041128 Firefox/0.8 (Debian package 1.0-4)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050110 Firefox/0.8 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7a) Gecko/20040218 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/02004032 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040313 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040326 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040328 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040403 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040411 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040608 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040626 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040630 Firefox/0.8 StumbleUpon/1.904" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040708 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a2) Gecko/20040529 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a2) Gecko/20040602 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a2) Gecko/20040605 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a2) Gecko/20040617 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a2) Gecko/20040630 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040428 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040429 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040430 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040502 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040503 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040505 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040516 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040518 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040225 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040327 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040506 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040602 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.6) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040219 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040327 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040421 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040506 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040602 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.6) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; MS-is-evil; en-US; rv:1.6) Gecko/20040405 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.6) Gecko/20040219 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sl-SI; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sl-SI; rv:1.6) Gecko/20040212 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.6) Gecko/20040602 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.6) Gecko/20040207 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.6) Gecko/20040327 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.6) Gecko/20040603 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.6) Gecko/20040615 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.6) Gecko/20040527 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.6) Gecko/20040408 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.6) Gecko/20040609 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20040324 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20040825 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20040902 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20041228 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20050204 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.6) Gecko/20050228 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD macppc; en-US; rv:1.6) Gecko/20040822 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6) Gecko/20040210 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6) Gecko/20040211 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6) Gecko/20040214 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6) Gecko/20040403 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040629 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/6.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040614 Firefox/0.8" + family: "Firefox" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040222 Firefox/0.8.0+ (mmoy)" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a2) Gecko/20040604 Firefox/0.8.0+" + family: "Firefox" + major: '0' + minor: '8' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040628 Firefox/0.9.1 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040614 Firefox/0.9 StumbleUpon/1.999" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040815 Firefox/0.9.3 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pl-PL; rv:1.7) Gecko/20040614 Firefox/0.9 Mnenhy/0.6.0.104" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.5) Gecko/20041107 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040614 Firefox/0.9 StumbleUpon/1.993" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040614 Lightningdog/0.9 (Firefox/0.9 polymorph)" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040617 Firefox/0.9.0+" + family: "Firefox" + major: '0' + minor: '9' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1 StumbleUpon/1.994" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a2) Gecko/20040711 Firefox/0.9.0+" + family: "Firefox" + major: '0' + minor: '9' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.9.3 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.9.3 StumbleUpon/1.998" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.9 StumbleUpon/1.993" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Firefox/0.9 Mnenhy/0.6.0.104" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040608 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040608 Firefox/0.9.0" + family: "Firefox" + major: '0' + minor: '9' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Firefox/0.9 StumbleUpon/1.994" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Firefox/0.9 WebWasher 3.3" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 INTERNET COMMANDER/0.9 (All your Firefox/0.9 are DEREK SMART'S BECAUSE HE HAS A PHD AND YOU DON'T)" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040623 Firefox/0.9.0+" + family: "Firefox" + major: '0' + minor: '9' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040625 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1 StumbleUpon/1.993" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1 StumbleUpon/1.994" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040703 Firefox/0.9.0+" + family: "Firefox" + major: '0' + minor: '9' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2 StumbleUpon/1.993" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.0" + family: "Firefox" + major: '0' + minor: '9' + patch: '0' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3 StumbleUpon/1.993" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3 StumbleUpon/1.999" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040808 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Firefox/0.9.3 StumbleUpon/1.995" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Firefox/0.9 StumbleUpon/1.994" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040629 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040615 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040615 Firefox/0.9 StumbleUpon/1.993" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040615 Seaant/0.9 (All your Firefox/0.9 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040616 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040617 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040619 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040620 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040624 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1 Mnenhy/0.6.0.104" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040701 Firefox/0.9.0+ (daihard: P4/SSE2)" + family: "Firefox" + major: '0' + minor: '9' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040704 Firefox/0.9.0+" + family: "Firefox" + major: '0' + minor: '9' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3 StumbleUpon/1.999" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.7) Gecko/20040616 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040615 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040616 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040614 Firefox/0.9" + family: "Firefox" + major: '0' + minor: '9' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.3) Gecko/20040831 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040628 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a3) Gecko/20040810 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a5) Gecko/20041121 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.7) Gecko/20040629 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7.2) Gecko/20040819 Firefox/0.9.1+ (ax)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040713 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.8a6) Gecko/20041127 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2) Gecko/20040811 Firefox/0.9.1+ (pigfoot)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.9.1 StumbleUpon/1.994" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040804 Firefox/0.9.1+ (bangbang023)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040808 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a3) Gecko/20040815 Firefox/0.9.1+ (MOOX-TK)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a5) Gecko/20041110 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-AR; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040810 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040811 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040812 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040814 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040814 Firefox/0.9.1+ (MOOX M3)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20040629 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.9.1 StumbleUpon/1.993" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.9.1 StumbleUpon/1.994" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040626 Spacepanda/0.9.1 (Firefox/0.9.1 serious edition)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040729 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040802 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040802 Firefox/0.9.1+ (moox)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040805 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040726 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040811 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040820 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040827 Firefox/0.9.1+ (MOOX M3)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040901 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a3) Gecko/20040904 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a5) Gecko/20041114 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040629 Firefox/0.9.1 (MOOX-AV)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; it-IT; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win NT 5.0; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040706 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040725 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040729 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040804 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040806 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7) Gecko/20040629 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; pt-BR; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040819 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040825 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040629 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040630 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040701 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040702 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040704 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040705 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040706 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040708 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040710 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040711 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040714 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040715 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040719 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040721 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040729 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040730 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040730 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040801 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040802 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.1+ (lokean SVG-enabled)" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040804 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a3) Gecko/20040730 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a3) Gecko/20040805 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a3) Gecko/20040824 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a3) Gecko/20040902 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a5) Gecko/20041027 Firefox/0.9.1+" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7) Gecko/20040712 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7) Gecko/20040719 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20040629 Firefox/0.9.1" + family: "Firefox" + major: '0' + minor: '9' + patch: '1' + - user_agent_string: "Firefox 0.9.2 (The intelligent alternative)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.7) Gecko/20040711 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pt-BR; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2 (ax)" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pt-BR; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2 (ax)" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040707 Waterbug/0.9.2 (All your Firefox/0.9.2 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040709 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040708 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040712 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040716 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040801 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040802 Firefox/0.9.2" + family: "Firefox" + major: '0' + minor: '9' + patch: '2' + - user_agent_string: "Firefox 0.9.3 (compatible;MSIE 6.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Firefox/0.9.3 (compatible;MSIE 6.1; Windows 98)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Firefox 0.9.3 (compatible MSIE is gay;Linux)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Firefox/0.9.3 [en] (All your base are belong to us)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (i686; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; de-DE; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; it-IT; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7) Gecko/20040803 Firefox/0.9.3 (#)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3 WebWasher 3.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040803 Firejackalope/0.9.3 (All your Firefox/0.9.3 are belong to Firesomething)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040805 Firefox/0.9.3 (djeter)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr-TR; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-DE; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; fr; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD amd64; en-US; rv:1.7) Gecko/20041015 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040806 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040807 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040811 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040813 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040830 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040910 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040927 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20041016 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7) Gecko/20040808 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ca-CA; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7) Gecko/20040809 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3 Mnenhy/0.6.0.104" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040804 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040805 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040806 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040807 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040808 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040809 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040810 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040813 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040814 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040818 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040819 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040823 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040824 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040825 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040827 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040830 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040831 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040901 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040904 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040914 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040917 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040920 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040926 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040928 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu) StumbleUpon/1.999" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.7) Gecko/20040803 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; uk-UA; rv:1.7) Gecko/20040809 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; de-DE; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7) Gecko/20040813 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; fr; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7) Gecko/20040902 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7) Gecko/20040817 Firefox/0.9.3" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; WinNT; es-AR; rv:1.7) Gecko/20041013 Firefox/0.9.3 (Ubuntu)" + family: "Firefox" + major: '0' + minor: '9' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20050302 Firefox/0.9.6" + family: "Firefox" + major: '0' + minor: '9' + patch: '6' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040626 Firefox/0.9.6" + family: "Firefox" + major: '0' + minor: '9' + patch: '6' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050302 Firefox/0.9.6" + family: "Firefox" + major: '0' + minor: '9' + patch: '6' + - user_agent_string: "Best website about travels.(New Zealand, Thailand, Bolivia)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "appName/appVersion (Windows; U; Windows NT 5.0; zh-CN; rv:1.7.5) Gecko/20041107 Firefox/1.0 (vendorComment)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "(Firefox/1.0; Mac OS X Panther)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Firefox/1.0 Mozilla/5.0 Netscape/7.1elezeta (Debian GNU/Linux)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.17; Mac_PowerPC) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.001 (Windows NT 5.0) [en] Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Amiga OS; U; Amiga OS 5.3; en-US; rv:5.3) Gecko/20040707 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (ca-AD; Celtric) Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; ; Apple ][) Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (en-US; rv:1.7.5) Gecko/20050110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Gameboy Color; U; Gameboy OS 2005; de-DE) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Linux; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Linux i686; nb-NO; rv:1.7.5) Gecko/20041108 Firefox/1.0 Frodo" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Linux; U; Windows NT 5.1; es-ES; rv:1.7.3) Gecko/20041027 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.3) Gecko/20041026 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.3) Gecko/20041026 Firefox/1.0RC1 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041104 Firefox/1.0RC2 (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041110 Firefox/1.0 (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041112 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041130 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20050208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20050208 Firefox/1.0 StumbleUpon/1.9991" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7) Gecko/20040628 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20041207 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20041211 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20041222 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20041225 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8a6) Gecko/20050109 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b2) Gecko/20050220 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b2) Gecko/20050224 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b2) Gecko/20050225 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050128 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050128 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050202 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050205 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050209 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050212 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050216 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050217 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050218 Firefox/1.0+ (PowerBook)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; fi-FI; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; ja-JPM; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; ja-JPM; rv:1.7.5) Gecko/20041108 Firefox/1.0,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; nl-NL; rv:1.7.5) Gecko/20041202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; zh-TW; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (; U;;; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; de-DE;SKC) Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 Windows Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; de-AT; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; ja-JP; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; cs-CZ; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; da-DK; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.7.5) Gecko/20041104 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; el-GR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-GB; rv:1.7.5) Gecko/20041113 Firefox/1.0 (MOOX M1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.3) Gecko/20041026 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (*mh*)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 SR" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8a6) Gecko/20050108 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8a6) Gecko/20050110 Firefox/1.0+ (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8b2) Gecko/20050302 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8b) Gecko/20050115 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8b) Gecko/20050218 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; es-ES; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; hu-HU; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; hu-HU; rv:1.7.5) Gecko/20041110 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; it-IT; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; ja-JP; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; nl-NL; rv:1.7.5) Gecko/20041202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pl-PL; rv:1.7.5) Gecko/20041104 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; pt-BR; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; sv-SE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; tr-TR; rv:1.7.5) Gecko/20041208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; zh-CN; rv:1.7.5) Gecko/20041124 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; zh-TW; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; nl-NL; rv:1.7.5) Gecko/20041202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; sv-SE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows 98; nl-NL; rv:1.7.5) Gecko/20041112 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ca-AD; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; cs-CZ; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; da-DK; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; da-DK; rv:1.7.5) Gecko/20041118 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.3) Gecko/20041027 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.5) Gecko/~20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0 WebWasher 3.3" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.3) Gecko/20041026 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.3) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 -awstats-exclude" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 Mnenhy/0.6.0.104" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 PR" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.998" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.9991" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041108 Firefox/1.0 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041108 Firefox/1.0 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041115 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041123 Firefox/1.0 (Community Edition FireFox P4W-X2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20050114 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5; Google-TR-1) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040812 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a6) Gecko/20041209 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a6) Gecko/20050101 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a6) Gecko/20050107 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a6; Google-TR-1) Gecko/20050101 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b2) Gecko/20050301 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050117 Firefox/1.0+ (BlueFyre)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050118 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050122 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050131 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050201 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050202 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050204 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050206 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050206 Firefox/1.0+ (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050209 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050210 Firefox/1.0+ (BlueFyre)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b) Gecko/20050215 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.7.5) Gecko/20041210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fi-FI; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fi-FI; rv:1.7.5) Gecko/20041108 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; hu-HU; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7.3) Gecko/20041027 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ko-KR; rv:1.7.5) Gecko/20041111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; nl-NL; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; nl-NL; rv:1.7.5) Gecko/20041202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.7.5) Gecko/20041104 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ru-RU; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; sl-SI; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; sv-SE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.7.3) Gecko/20041101 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.7.5) Gecko/20041124 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.7.5) Gecko/20041124 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-TW; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; bg-BG; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ca-AD; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; da-DK; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-bn; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.3) Gecko/20041027 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041104 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0 Mnenhy/0.6.0.104" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0 WebWasher/1.2.2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0 (CK-UKL)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0 StumbleUpon/1.999,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041124 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; el-GR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-AU; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-CA; rv:1.8b2) Gecko/20050226 Firefox/1.0+ (nightly)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-CA; rv:1.8b) Gecko/20050216 Firefox/1.0+ (trunk)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-EN; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-gb; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0 StumbleUpon/1.9992" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041113 Firefox/1.0 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041128 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.5) Gecko/20041129 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-NZ; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-UK; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20040903 Firefox/1.0 PR (NOT FINAL) (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20041026 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041106 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 Ad/www.yetanotherblog.de" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (All your Firefox/1.0 are belong to us)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (Arjan says HI!)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (Goobergunchian Edition)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 Mnenhy/0.6.0.104" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 Mnenhy/0.7.1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (Not Netscape 7.1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 sexyfox/0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.9991" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.9992" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 WebWasher 3.3" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 www.city.poznan.pl/1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Superjellyfish/1.0 (All your Firefox/1.0 are belong to Firesomething)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041108 Firefox/1.0 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041108 Firefox/1.0 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M3) Mnenhy/0.6.0.104" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 StumbleUpon/1.999 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 StumbleUpon/1.999 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041112 Firefox/1.0 (stipe)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041114 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041115 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050129 Firefox/1.0 (pigfoot)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050206 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050207 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050209 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050211 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20050214 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5; Google-TR-1) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5; Google-TR-1) Gecko/20041107 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5;ME) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0 StumbleUpon/1.9992" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20040103 Firefox/1.0+ (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041204 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041206 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041209 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041211 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041214 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041215 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041218 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041220 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041221 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041229 Firefox/1.0+ (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041230 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050101 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050104 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050108 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050109 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050111 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20050131 Firefox/1.0+ (Firefox CE Trunk 2004-12-23 P4W-X15)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050222 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050301 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b2) Gecko/20050305 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050113 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050115 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050116 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050117 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050118 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050123 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050124 Firefox/1.0+ (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050125 Firefox/1.0+ WebWasher 3.3" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050126 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050128 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050131 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050201 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050204 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050205 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050206 Firefox/1.0+ (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050207 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050210 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050211 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050213 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050215 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050216 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050217 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b) Gecko/20050218 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0; ortzzuwt" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.5) Gecko/20041107 xFirefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.5) Gecko/20041108 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.5) Gecko/20041208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.5) Gecko/20041210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.5) Gecko/20041210 Firefox/1.0 Internet Watcher 2000/ V1.4" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fi-FI; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fi-FI; rv:1.7.5) Gecko/20041108 Firefox/1.0 StumbleUpon/1.9991" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.3) Gecko/20041027 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.5; Google-TR-1) Gecko/20041109 Firefox/1.0 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu-HU; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.3) Gecko/20041027 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.5) Gecko/20041108 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.5) Gecko/20041108 Firefox/1.0 StumbleUpon/1.996" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.5) Gecko/20041110 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-VE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7.5) Gecko/20041108 Firefox/1.0,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.7.5) Gecko/20041111 Firefox/1.0 (JTw)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.8a6) Gecko/20050107 Firefox/1.0+ (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ko-KR; rv:1.7.5) Gecko/20041111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nb-NO; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.5) Gecko/20041104 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.5) Gecko/20041116 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.5) Gecko/20041202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.7.5) Gecko/20041110 Firefox/1.0 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.8a6) Gecko/20050109 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.8b2) Gecko/20050220 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.8b) Gecko/20050206 Firefox/1.0+ (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.8b) Gecko/20050218 Firefox/1.0+ (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ro-RO; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.3) Gecko/20041027 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sk-SK; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sl-SI; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sl-SI; rv:1.7.5) Gecko/20041113 Firefox/1.0 (largie's)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.5) Gecko/20040321 Firefox/1.0 DEBUG" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr-TR; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr-TR; rv:1.7.5) Gecko/20041208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.7.5) Gecko/20041124 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.7.5) Gecko/20041124 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.5) Gecko/20041108 Firefox/1.0 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.5) Gecko/20050208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8a6) Gecko/20050110 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8b2) Gecko/20050228 Firefox/1.0+ (MOOX M1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8b) Gecko/20050114 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; es-es; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; es-ES; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; it-IT; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; ru-RU; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-TW; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 6.0; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; es-ES; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; ; Windows NT 5.1; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Slackware - current; Linux i686; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Slackware; Linux i586; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Darwin Power Macintosh; en-US; rv:1.7.5) Gecko/20041208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD amd64; en-US; rv:1.7.3) Gecko/20041104 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD amd64; en-US; rv:1.7.5) Gecko/20050104 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-UK; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.3) Gecko/20041029 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041112 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041113 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041114 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041115 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041120 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041123 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041124 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041125 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041127 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041130 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041203 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041207 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041209 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041215 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041218 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041222 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041224 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041227 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041228 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20041229 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050102 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050104 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050105 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050106 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050112 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050115 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050117 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050120 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050123 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050124 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050125 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050127 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050204 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050205 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050207 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050212 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050215 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050225 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050226 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; ja-JP; rv:1.7.5) Gecko/20041202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i686; es; rv:1.7.5) Gecko/20041128 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux) Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0 (Debian package 1.0-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20050103 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.5) Gecko/20050210 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; chrome://navigator/locale/navigator.properties; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20041119 Firefox/1.0 (Debian package 1.0-3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20050206 Firefox/1.0 (Debian package 1.0+dfsg.1-5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-CH; rv:1.7.5) Gecko/20040107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041111 Firefox/1.0 (Debian package 1.0-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041112 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041128 Firefox/1.0 (Debian package 1.0-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041207 Firefox/1.0 (Debian package 1.0-5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20041211 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20050202 Firefox/1.0 (Debian package 1.0+dfsg.1-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.5) Gecko/20050210 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.7.5) Gecko/20041209 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0-2ubuntu4-warty99)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.8) Gecko/20050101 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040907 Firefox/1.0 PR (NOT FINAL)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041026 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041029 Firefox/1.0RC1 (Debian package 0.99+1.0RC1-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041030 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041030 Firefox/1.0RC1 (Debian package 0.99+1.0RC1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041102 Firefox/1.0RC1 (Debian package 0.99+1.0RC1-3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041105 Firefox/1.0RC1 (Debian package 0.99+1.0RC1-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041112 Firefox/1.0RC1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041009 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041106 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0 (Debian package 1.0-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0 SPELLSHIDO!" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041112 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041113 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041114 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041115 Firefox/1.0 StumbleUpon/1.998" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041116 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041116 Firefox/1.0 (Ubuntu) StumbleUpon/1.999 (Ubuntu package 1.0-2ubuntu3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041116 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0-2ubuntu3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041117 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041117 Firefox/1.0 (Debian package 1.0-2.0.0.45.linspire0.4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041119 Firefox/1.0 (Debian package 1.0-3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041120 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041120 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0-2ubuntu3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041121 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041123 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041124 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041125 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041126 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041127 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041128 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041128 Firefox/1.0 (Debian package 0.99+1.0RC1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041128 Firefox/1.0 (Debian package 1.0-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041129 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041129 Firefox/1.0 (Debian package 1.0-3.backports.org.1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041130 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041201 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041203 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041204 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041204 Firefox/1.0 (Debian package 1.0.x.2-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041205 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041206 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041207 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041207 Firefox/1.0 (Debian package 1.0-5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041207 Firefox/1.0 StumbleUpon/1.999 (Debian package 1.0-5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041208 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041209 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041209 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0-2ubuntu4-warty99)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041211 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041212 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041213 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041214 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041214 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041215 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041215 Firefox/1.0 Red Hat/1.0-12.EL4" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041216 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041218 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041219 Firebunny/1.0 (Firefox/1.0)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041219 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041219 Firefox/1.0 (Debian package 1.0+dfsg.1-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041219 Firefox/1.0 (Debian package 1.0+dfsg.1-1) Mnenhy/0.7.1" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041220 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041222 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041223 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041223 Firefox/1.0 Yoper/FIREFOX_RPM_AM" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041224 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041225 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041226 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041227 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041228 Firefox/1.0 Fedora/1.0-7" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041228 Firefox/1.0 Fedora/1.0-8" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041230 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041231 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050103 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050104 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050105 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050106 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050109 Firefox/1.0 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050112 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050113 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050115 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050116 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050120 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050120 Firefox/1.0 (Debian package 1.0+dfsg.1-3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050121 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050121 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-2ubuntu2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050123 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050123 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-2ubuntu3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050125 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050126 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050127 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050128 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050128 Firefox/1.0 (Debian package 1.0.x.2-13)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050128 Firefox/1.0 (Ubuntu)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050128 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-2ubuntu5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050129 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050130 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050131 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050201 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050202 Firefox/1.0 (Debian package 1.0+dfsg.1-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050203 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050203 Firefox/1.0 (Debian)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050203 Firefox/1.0 (Debian package 1.0.x.2-15)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050205 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050206 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050206 Firefox/1.0 (Debian package 1.0+dfsg.1-5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050207 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050209 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050210 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050210 Firefox/1.0 StumbleUpon/1.999 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050215 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050218 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050221 Firefox/1.0 (Ubuntu)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050221 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-6ubuntu1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050222 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050223 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050225 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20050228 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20041013 Firefox/1.0.0" + family: "Firefox" + major: '1' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a6) Gecko/20041204 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050117 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050201 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050207 Firefox/1.0+ (daihard: P4/SSE2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050212 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050218 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-AR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20041128 Firefox/1.0 (Debian package 1.0-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20041210 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.7.5) Gecko/20050128 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-2ubuntu5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; es-MX; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fi-FI; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.5) Gecko/20041108 Firefox/1.0 Mnenhy/0.7" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20041115 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0-2ubuntu2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20041116 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0-2ubuntu3)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20041119 Firefox/1.0 (Debian package 1.0-3 Moostik.net)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20041128 Firefox/1.0 (Debian package 1.0-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20050110 Firefox/1.0 StumbleUpon/1.998 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20050202 Firefox/1.0 (Debian package 1.0+dfsg.1-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20050206 Firefox/1.0 (Debian package 1.0+dfsg.1-5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.5) Gecko/20050210 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; he-IL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; hr-HR; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; hu-HU; rv:1.7.3) Gecko/20041101 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; hu-HU; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.7.5) Gecko/20050210 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.7.5) Gecko/20041128 Firefox/1.0 (Debian package 1.0-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; nl-NL; rv:1.7.5) Gecko/20041202 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; nl-NL; rv:1.7.5) Gecko/20050210 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; nl-NL; rv:1.7.5) Gecko/20050221 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-6ubuntu1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.5) Gecko/20041108 Slackware Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.5) Gecko/20050110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ru-RU; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.7.5) Gecko/20050110 Firefox/1.0 StumbleUpon/1.999 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.7.5) Gecko/20050128 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-2ubuntu5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.7.5) Gecko/20050210 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; tr-TR; rv:1.7.5) Gecko/20041208 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; us; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; zh-TW; rv:1.7.5) Gecko/20041119 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i786; en-US; rv:1.8b2) Gecko/20050225 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i786; en-US; rv:1.8b) Gecko/20050212 Firefox/1.0+" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20041116 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20041125 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20041209 Firefox/1.0 (Debian package 1.0-5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20041220 Firefox/1.0 (Debian package 1.0+dfsg.1-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20050110 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20050123 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.7.5) Gecko/20050128 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-2ubuntu5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux ppc; es-US; rv:1.7.5) Gecko/20041220 Firefox/1.0 (1.0)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux; sl-SI; rv:1.7.5) Gecko/20041112 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; da-DK; rv:1.7.5) Gecko/20041118 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; de-DE; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041112 Firefox/1.0 (Debian package 1.0-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041116 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041117 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041130 Firefox/1.0 (Debian package 1.0-4)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041204 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041214 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041218 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20041226 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050104 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050106 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050111 Firefox/1.0 (Debian package 1.0+dfsg.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050114 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050124 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050128 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-2ubuntu5)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050211 Firefox/1.0 (Debian package 1.0+dfsg.1-6)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.5) Gecko/20050221 Firefox/1.0 (Ubuntu) (Ubuntu package 1.0+dfsg.1-6ubuntu1)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; MSIE 6.0; Linux i686; en-US; rv:1.7.5; IDF-BCC;) Gecko/20041111 Firefox/1.0 (Debian package 1.0-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.5) Gecko/20041114 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.5) Gecko/20050103 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.5) Gecko/20050126 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; NetBSD i386; en-US; rv:1.7.5) Gecko/20050128 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD amd64; en-US; rv:1.7.5) Gecko/20050122 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.7.5) Gecko/20041128 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.7.5) Gecko/20050101 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Slackware; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Slackware; Linux i686; pl-PL; rv:1.7.5) Gecko/20041108 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.7.5) Gecko/20041111 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.7.5) Gecko/20041213 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.7.5) Gecko/20050101 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.5) Gecko/20041109 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.5) Gecko/20041110 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.5) Gecko/20041130 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.5) Gecko/20041207 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7.5) Gecko/20050213 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "WhoreNuts/2.0 (Windows; U; Win98; en-US; rv:1.7.5) ScabCount/123883 Firefox/1.0" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Gecko/20041108 Firefox/1.0; Mac_PowerPC)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Gecko/20050225 Firefox/1.0.1 Antares; U; Antares 5.5" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Gecko/20050228 Firefox/1.0.1 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; de-DE; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1 StumbleUpon/1.9991" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.6) Gecko/20050227 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; hu-HU; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:1.7.6) Gecko/20050223 Firefox/1.0.1,gzip(gfe) (via translate.google.com)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; nl-NL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-GB; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050222 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050224 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 robert" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 StumbleUpon/1.9991" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 StumbleUpon/1.9992" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050228 Firefox/1.0.1 (MOOX M1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050228 Firefox/1.0.1 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; it-IT; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ca-AD; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; el-GR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1 StumbleUpon/1.9992" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050224 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050224 Firefox/1.0.1 (pigfoot)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050228 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050228 Firefox/1.0.1 (MOOX M2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050228 Firefox/1.0.1 (MOOX M3)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6; Google-TR-1) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-AR; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-AR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.7.6) Gecko/20050303 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.6) Gecko/20050223 Firefox/1.0.1 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; hu-HU; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT; rv:1.7.6) Gecko/20050226 Firefox/1.0.1 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.6) Gecko/20050301 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.6) Gecko/20050303 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.7.6) Gecko/20050301 Firefox/1.0.1 Fedora/1.0.1-1.3.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050224 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050224 Firefox/1.0.1 Fedora/1.0.1-1.3.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 Red Hat/1.0.1-1.4.3" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050226 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050227 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050228 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050301 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050301 Firefox/1.0.1 (Debian package 1.0.1-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050302 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050302 Firefox/1.0.1 Fedora/1.0.1-1.3.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050303 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050305 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050306 Firefox/1.0.1 (Debian package 1.0.1-2)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.7.6) Gecko/20050301 Firefox/1.0.1 (Debian package 1.0.1-1)" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.7.6) Gecko/20050224 Firefox/1.0.1 Fedora/1.0.1-1.3.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.6) Gecko/20050223 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.6) Gecko/20050302 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.6) Gecko/20050308 Firefox/1.0.1" + family: "Firefox" + major: '1' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.6) Gecko/20050225 Firefox/1.0.2" + family: "Firefox" + major: '1' + minor: '0' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.3) Gecko/20041101 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2 StumbleUpon/1.999" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20041030 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20041031 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20041101 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041102 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2 (ax)" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041104 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.5) Gecko/20041104 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041103 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041105 Firefox/1.0RC2" + family: "Firefox" + major: '1' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Linux Slackware; U;Linux Slackware 10.1; en-US; rv:1.8.0) Gecko/20050616 Firefox/1.1" + family: "Firefox" + major: '1' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0) Gecko/20050304 Firefox/1.1" + family: "Firefox" + major: '1' + minor: '1' + patch: + - user_agent_string: "Mozilla Firefox/5.0" + family: "Firefox" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/7.1" + family: "Firefox" + major: '7' + minor: '1' + patch: + - user_agent_string: "Firefox 7.1.3(compatible MSIE is gay;Linugz)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Linux Slackware x86_64 BlackBox; de_AT; Intel@Xeon) Firefox/Gecko" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.2b) Gecko/20021016 K-Meleon 0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2b) Gecko/20021016 K-Meleon 0.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8" + family: "K-Meleon" + major: '0' + minor: '8' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.1" + family: "K-Meleon" + major: '0' + minor: '8' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2" + family: "K-Meleon" + major: '0' + minor: '8' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040608 MultiZilla/ StumbleUpon/1.995" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040613 MultiZilla/1.5.0.4h" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.2) Gecko/20040803 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.7) Gecko/20040617 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (OS/2; U; Warp 4.5; en-US; rv:1.8a3) Gecko/20040819 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.3.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.2) Gecko/20040803 MultiZilla/1.6.3.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.2) Gecko/20040804 MultiZilla/1.6.4.0b (ax)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.3) Gecko/20040910 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.6) Gecko/20040113 MultiZilla/1.6.2.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-AT; rv:1.7.3) Gecko/20040910 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.3.1; MultiZilla v1.4.0.3J) Gecko/20031007 MultiZilla/1.6.0.0d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6a) Gecko/20031030 MultiZilla/1.6.0.0a" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.2.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2) Gecko/20040803 MultiZilla/1.6.0.0e" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.3) Gecko/20040910 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040316 MultiZilla/1.6.2.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040316 MultiZilla/1.6.3.1c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7b) Gecko/20040318 MultiZilla/1.6.1.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040514 MultiZilla/1.6.4.0a" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040616 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.6) Gecko/20040113 MultiZilla/1.6.2.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7.2) Gecko/20040803 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-AT; rv:1.7) Gecko/20040616 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031007 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.0.0e" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.2.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.3.0d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.3.1c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.3.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.1) Gecko/20040707 MultiZilla/1.6.3.2c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.1) Gecko/20040707 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040803 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 MultiZilla/1.6.2.0c (ax)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 MultiZilla/1.6.4.0b (ax)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.3) Gecko/20040910 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041217 MultiZilla/1.6.0.0e" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040421 MultiZilla/1.6.3.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040514 MultiZilla/1.6.3.2f" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040514 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040608 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040616 MultiZilla/1.6.2.1a" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040616 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a1) Gecko/20040520 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a2) Gecko/20040714 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a4) Gecko/20040927 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a) Gecko/20040429 MultiZilla/1.6.3.2c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.4) Gecko/20030624 MultiZilla/1.6.1.0b (ax)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Debian GNU/Linux - only dead fish go with the flow - i686; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.2.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040301 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.2.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040115 MultiZilla/1.6.2.1a" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040115 MultiZilla/1.6.3.0e" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 MultiZilla/1.6.3.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040510 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040528 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040804 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040913 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041014 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040316 MultiZilla/1.6.3.0e" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040421 MultiZilla/1.6.2.0c" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7b) Gecko/20040425 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040608 MultiZilla/1.6.2.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040618 MultiZilla/1.6.2.1d" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a3) Gecko/20040805 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8a) Gecko/20040501 MultiZilla/1.6.4.0b" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 MultiZilla/v1.1.20" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2b) Gecko/20021007 Phoenix/0.3" + family: "Phoenix" + major: '0' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5" + family: "Phoenix" + major: '0' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5" + family: "Phoenix" + major: '0' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5" + family: "Phoenix" + major: '0' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MS FrontPage 6.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MSFrontPage/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.0; Windows 3.1)" + family: "IE" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.0; Windows 3.1; Sculptor; Rules)" + family: "IE" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.0; Windows 95)" + family: "IE" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.0; Windows 95) via HTTP/1.0 coder.internet-elite.com/" + family: "IE" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/3.0 (compatible; MSIE 3.0; Windows NT 5.0)" + family: "IE" + major: '3' + minor: '0' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.01; Windows 3.1)" + family: "IE" + major: '3' + minor: '01' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.01; Windows 95)" + family: "IE" + major: '3' + minor: '01' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.02; Windows 95)" + family: "IE" + major: '3' + minor: '02' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.02; WindowsCE" + family: "IE" + major: '3' + minor: '02' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.02; Windows CE; PIEPlus 1.2; 240x320; PPC)" + family: "IE" + major: '3' + minor: '02' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.02; Windows CE; PPC; 240x320)" + family: "IE" + major: '3' + minor: '02' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; MSIE 3.02; Windows CE; Smartphone; 176x220)" + family: "IE" + major: '3' + minor: '02' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; MSN 2.5; Windows 95)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Windows 95)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Windows 95; FunWebProducts-MyWay)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Windows 95; .NET CLR 1.1.4322)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Windows NT)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Windows NT 4.0)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Windows NT 5.0)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Windows NT 5.1)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; Windows XP)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; AOL 4.0; Mac_PPC)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; AOL 4.0; Windows 95; Toshiba Corporation)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; AOL 5.0; Mac_PPC)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Mac_PowerPC)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; MSN 2.5; AOL 3.0; Windows 98; Compaq; wGoVols)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; MSN 2.5; MSN 2.5; AOL 4.0; Windows 98)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; MSN 2.5; Windows 98)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 2000)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 95; FREESERVE_IE4)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 95; iOpus-I-M)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 95; QXW0300f)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 95; TriStar Enterprises)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 98;CP=MS)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 98; DigExt)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 98; DT)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 98; Messages.co.uk)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows 98; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; 240x320)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; MSN Companion 2.0; 800x600; Compaq)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; Smartphone; 176x220)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.01; Windows; U; 32bit)" + family: "IE" + major: '4' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.5; Mac_PowerPC)" + family: "IE" + major: '4' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.5; Windows 98; )" + family: "IE" + major: '4' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.5; Windows NT 5.0)" + family: "IE" + major: '4' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5; Windows NT 5.1; Windows XP SP2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.00; Windows 98" + family: "IE" + major: '5' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 4.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 5.0; Windows 95; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 5.0; Windows 95; DigExt; DT)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 5.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 5.0; Windows 98; DigExt; DT)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 6.0; Windows 98; Compaq; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 6.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 7.0;TargetAOL7.0; Windows 95; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 7.0;TargetAOL7.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 7.0; Windows 95; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 7.0; Windows 98)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 7.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 7.0; Windows 98; DigExt; FunWebProducts)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 7.0; Windows 98; Hotbar 4.3.2.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; AOL 8.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0b1; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; CS 2000 6.0; Wal-Mart Connect 6.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC; AtHome021)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC; e412357VZ_IE50M)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC; p412360OptusCabl)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC; s412454BPH6mac)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC; s412514Mac/m/4.5)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC; S425166QXM03307)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC) (via translate.google.com)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC; X111923v13b.08)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; MSN 2.0; AOL 7.0; Windows 95; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; MSN 2.5; AOL 5.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; MSN 2.5; AOL 5.0; Windows 98; DT; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; MSN 2.5; MSN 2.5; Windows 98)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; MSN 2.5; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; MSN 2.5; Windows 98; DigExt; CindyKlett 1)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; MSNIA; AOL 7.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; AT&T WNS5.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; BTinternet V8.4; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; 1.21.2 )" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; AtHome0107)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; btclick.com Build BTCFSOHOQ2)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; DT)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; freenet 4.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; Hotbar 2.0; AT&T CSM6.0; FunWebProducts)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; JUNO)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; LILLY-EMA-EN)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; QXW0330q)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; QXW03314)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; sureseeker.com)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; tco2)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt; YComp 5.0.2.4)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DT)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DT; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; OZEMR1999V01)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) VoilaBot BETA 1.2 (http://www.voila.com/)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; ZDNetSL)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; {10708F41-46D9-11D9-9941-0008A127FF36})" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; {251744E0-8FEE-11D8-8ED7-00045A9E19B3})" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; {BD767A21-2BDF-11D9-B494-0050BAFA5FC2})" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; Compaq; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; Compaq; DigExt; FunWebProducts)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0(compatible; MSIE 5.0; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; A084)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; AIRF)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Arcor 2.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; AtHome033; FunWebProducts)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; AT&T CSM6.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Creative)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; */E-Plus-002)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; freenet200)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; freenet 4.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; FreeSurf myweb.nl v1.0.1)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; FunWebProducts)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; FunWebProducts; Creative)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; FunWebProducts; FunWebProducts-MyWay)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; FunWebProducts-MyWay)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Hotbar 2.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Hotbar 4.3.2.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Hotbar 4.3.5.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; iebar)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt);JTB:15:88fba442-193e-11d9-bb86-0050fc8126b1" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; KITL27; (R1 1.3))" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; LanguageForce)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Mannesmann Arcor)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Matrix Y2K - Preview Browser)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; MAX1.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; MCNON1.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; MindSpring Internet Services)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc21; v5m)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; MSN 6.1; MSNbMSFT; MSNmen-us; MSNczz; v5m)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; MSNIA)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; pbc4.0.0.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; pi 3.0.0.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; QXW0331m)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; QXW0331w)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; (R1 1.3))" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; SC/5.07/1.00/Compaq)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; searchengine2000.com; sureseeker.com)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; StudentenNet)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; sureseeker.com)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; TencentTraveler )" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; TiscaliFreeNet)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; tn3.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; V1.0Tomorrow1000)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt) via Avirt Gateway Server v4.2" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Virgilio3pc)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; VNIE5 RefIE5)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; vtown v1.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; www.ASPSimply.com)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; YComp 5.0.0.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; YComp 5.0.2.4)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; YComp 5.0.2.5)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; YComp 5.0.2.6)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; yplus 1.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; formatpb; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; FunWebProducts)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; FunWebProducts; Hotbar 4.4.5.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; NETACT; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; provided by VSNL)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; Q321120)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; QXW03301; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; QXW03301; DigExt; sunrise4)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; Software Trading Edition)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; WebHopper)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; YComp 5.0.0.0; Cox High Speed Internet Customer; sbcydsl 3.12" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows ME)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT;)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; Bob)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; Adam's Mark Hotels)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; AT&T WNS5.0; AT&T CSM6.0; AT&T WNS5.0 IE5.0.01)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; DT)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; DTS Agent" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; (R1 1.3))" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; TBIT)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; Yahoo-1.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; YComp 5.0.0.0)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DT; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; QXW0330d; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 [fi] (compatible; MSIE 5.0; Windows 98)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 [fr] (compatible; MSIE 5.0; Windows 98)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.0; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.0; Windows 98;)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.0; Windows NT/95/98))" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "MSIE 5.0" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "MSIE 5.0 (compatible; noyb; Windows5.1)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; AOL 4.0; Windows 98)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; AOL 4.0; Windows 98; QXW0332b)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; AOL 5.0; Windows 95; QXW0332b)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; AOL 7.0; Windows 98)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; AOL 7.0; Windows 98; YPC 3.0.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; AOL 8.0; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; CS 2000; Windows 95; AT&T WNS5.0; DigExt)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; MSN 2.5; Windows 98)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; MSNIA; Windows 95; MSNIA)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; BCD2000; FunWebProducts)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; DT)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; Microplex 1.0.1.5; OptusIE501-018)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; Microplex 2.0; OptusIE501-018)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; MSNIA)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; QXW0332b)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; QXW0332i)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; QXW03336)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; QXW0333a)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; SEARCHALOT.COM IE5; iOpus-I-M)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; USA On-Site)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; Xtra)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; 1012SurfnetVersion2.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; 1&1 Puretec)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; 981)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; AO1.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; AskBar 2.01; Hotbar 4.4.5.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; AT&T CSM6.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; BCD2000)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; BPH32_57a)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; BT Internet)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Config C)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; DT)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; F-5.0.1SP1-20000718; F-5.0.1-20000221)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; FDM)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Feat Ext 19)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; FREE)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; FunWebProducts)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; FunWebProducts; FunWebProducts-MyWay)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; GTE_IE5)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Hotbar 2.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Hotbar 3.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Hotbar 4.4.2.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Hotbar 4.4.7.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Hotbar 4.5.1.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Hotbar4.5.3.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; KSC)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Linux 2.4.2-mvista_01) [Netgem; 4.0.6; InterDigital-T]" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Linux 2.4.2-mvista_01) [Netgem; 4.4.2; i-Player; netbox; NetgemUK]" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Linux 2.4.2-mvista_01) [Netgem; 4.4.3b1; i-Player; netbox; NetgemUK]" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Linux 2.4.2-mvista_01) [Netgem; 4.5.2a; i-Player; netbox; btdigitaltv]" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Linux 2.4.2-mvista_01) [Netgem; 4.5.2a; i-Player; netbox; NetgemUK]" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Linux 2.4.2-mvista_01) [Netgem; 4.5.2b; i-Player; netbox; NetgemUK]" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; MRA 2.5 (build 00387))" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; MSNIA)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; MSOCD; AtHome020)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; OptusIE501-018)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; pi 3.0.0.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; QXC03304)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; QXW03335)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; QXW03336)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; (R1 1.3))" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; SEARCHALOT.COM IE5)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; SPINWAY.COM)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; SQSW)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; sureseeker.com)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; surfEU DE S1)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Teleos)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; TNET5.0NL)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; {World Online})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; YComp 5.0.2.6)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 4.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {2BBC0D6A-BD8E-43C8-9CA1-81673682EF32})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {31BF9C41-DE4C-49B8-B050-19E27C86DC76})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {59C0EB25-1B95-4B4C-AF0B-C247D74597B0})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {87CA9FD1-DEE6-4CB5-98FE-62BA2CA583DE})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {944D8EEF-056A-4073-B8F3-C317B94BA3C0})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {A68BF0C3-9B5E-4F63-A05B-0ADCAF21F0C8})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {ABF22706-058D-48D2-B032-BC3A65229618})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Admiral Group Limited -)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; AHP)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Alexa Toolbar)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Assistant 1.0.2.4)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; AtHome021SI)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Bitscape Solutions, India)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Boeing Kit)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {CDC8EB20-F4B7-4407-BD64-40AB1B97D85C})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Coles Myer Ltd.)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Creative)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; DigExt)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; DigExt; iebar; (R1 1.5))" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; DigExt; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; DigExt; YComp 5.0.0.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; digit_may2002)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; DT)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {E73D9CB8-6F87-458B-9943-F0284A59F969}; FDM)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; {EEC83506-405F-4B48-BA4F-047A5AA92F3E})" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; */E-Plus-002)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; F-5.0.1-20021031)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FDM)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FPC 014)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FunWebProducts)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FunWebProducts),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FunWebProducts-MyTotalSearch)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FunWebProducts-MyWay)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FunWebProducts; .NET CLR 2.0.40607)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FW1)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; H010818)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)Host: www.pgts.com.au" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar 3.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar 3.0) via NetCache version 3.1.2c-Solaris" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar 4.2.4.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar 4.3.1.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar 4.4.2.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar 4.4.5.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar 4.4.5.0; FunWebProducts)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar 4.4.6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Hotbar4.5.3.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; i-NavFourF)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; iOpus-I-M)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Launceston Church Grammar School)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Mohammad Ali Jinnah University)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MRA 4.0 (build 00768))" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MSOCD; AtHome020)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; .NET CLR 1.0.2914)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; .NET CLR 2.0.40607)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Netcom_BA_DD)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; OptusIE55-31)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; PCUser)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; PhaseOut-www.phaseout.net; PhaseOut-www.phaseout.net)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Q312461)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Q321120)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Q321120; Feat Ext 20)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; (R1 1.1))" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; (R1 1.3))" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; (R1 1.5))" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Sgrunt|V106|671|S-1000478620)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; Smart Explorer 6.1)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; surfEU DE M2)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; T312461)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; TencentTraveler )" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; TNT Australia Pty Ltd)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; T-Online Internatinal AG; MSIECrawler)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; WebTap)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; YComp 5.0.0.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; YComp 5.0.2.5)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; YComp 5.0.2.6; FunWebProducts)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.1)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; Aztec)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; BWB 09032000; BWB 07032000)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; DT)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; freenet 4.0)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; FunWebProducts)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; IE4SUPER; IE4COPLEY; proxyho; proxyinternet)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; IE501NTAb)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; OIZ - Switzerland)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; QXW0332s)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; QXW03336)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; [R1 1.3])" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; SBC)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; Sears Roebuck and Co. 2001)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; S.N.O.W Workstation)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; v1.0 C1; v2.0 C3; v4.0 C3; v2.0 C1)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; v1.0 C1; v4.0 C3)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; www.k2pdf.com)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; YComp 5.0.2.4)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "MSIE 5.01" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "MSIE 5.01 (Windows 98)" + family: "IE" + major: '5' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.05; Windows NT 4.0)" + family: "IE" + major: '5' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.05; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.12; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.13; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '13' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.14; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '14' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.15; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '15' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.16; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '16' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.17; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '17' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.17; Mac_PowerPC),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '17' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.2; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '2' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.2; Mac_PowerPC) - Internet Explorer 5.2, Mac" + family: "IE" + major: '5' + minor: '2' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.21; Mac_PowerPC" + family: "IE" + major: '5' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.21; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.22; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC)" + family: "IE" + major: '5' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 95)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 95; Arcor 2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 95; EWE TEL)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 95; FDM)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 98; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 98; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 98; VV50110)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows 98; Win 9x 4.90; Q312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 6.0;TargetAOL6.0; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 6.0; Windows 95)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 6.0; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 6.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 95)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; {326AFFA0-90D0-11D8-9D83-444553540000})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; DT; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; Hotbar 4.2.1.1362)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; Q312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; QXW03371)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; Win 9x 4.90; AN10HaendlerWelcomeletter1200; AO1.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; Win 9x 4.90; Creative; (R1 1.3))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; Win 9x 4.90; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows 98; Win 9x 4.90; (R1 1.5))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 7.0; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 8.0; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 8.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 8.0; Windows 98; Win 9x 4.90; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 8.0; Windows 98; Win 9x 4.90; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 8.0; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 8.0; Windows NT 5.0; BTT V3.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 9.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 9.0; Windows 98; Win 9x 4.90; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; AOL 9.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; CS 2000 6.0; Wal-Mart Connect 6.0; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; CS 2000 6.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; CS 2000 6.0; Windows 98; YComp 5.0.2.6)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; CS 2000; Windows 98; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; CS 2000; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSN 2.5; AOL 6.0; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSN 2.5; AOL 7.0; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSN 2.5; Windows 95; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSN 2.5; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSN 2.5; Windows 98; {476BCB60-A826-11D8-9866-444553540000})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSN 2.5; Windows 98; AT&T CSM6.0; YComp 5.0.2.5)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSN 2.5; Windows 98; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSNIA; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSNIA; Windows 98; AT&T CSM6.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSNIA; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; MSNIA; Windows 98; Win 9x 4.90; MSNIA)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 3.11)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; AN10HaendlerWelcomeletter1200; AO1.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; A&R Internet; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; BCD2000)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; BPB32_v2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; CSO 3.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; DigExt)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; indo.net IE40 users)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; iOpus-I-M)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; iPrimus)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; IT-Office)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; OptusIE501-018)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; OptusIE55-31)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; OptusIE55-31; BPH03)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; PC Games Hardware)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; QXW0333s)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; QXW0333x)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; QXW0334j)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; qxw03377)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; QXW03395)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; StumbleUpon.com 1.758)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; surfEU DE S3)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; SYMPA)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; T312461; Alexa Toolbar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; T312461; UDWXQ08154711; Praise and Worship to the Lamb of God!)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; TBP_6.1_AC)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; TBP_7.0_GS)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; Tucows)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; wave internet services-LAN)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; WSIE)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 95; YComp 5.0.0.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; )" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98;)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)." + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible;MSIE 5.5; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible;MSIE 5.5; Windows 98);" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0(compatible; MSIE 5.5; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; 1 & 1 Internet AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; {25FDDD80-7A10-11D9-B0EA-00055D3406F7})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; 3301; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; {88CC0240-7784-11D9-B0EA-00055D3406F7})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; AIRF)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Alexa Toolbar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; AT&T CSM6.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; AT&T WNS5.0; AT&T WNS5.2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; AT&T WNS5.2; AT&T CSM6.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; AUTOSIGN W95 WNT VER01)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Avant Browser [avantbrowser.com])" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; AWWCD; OptusIE501-018)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; {B0727E40-7BFF-11D8-BF96-00028A14743D})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; {B85C43C0-6408-11D8-890A-005004AD1452})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; BPH32_59)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; brip1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; BTopenworld)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Chariot; Hotbar 4.3.2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; CNE-Internet 02252000)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; COM+ 1.0.2204)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Compaq)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Compaq; PeoplePC 2.3.0; ISP)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Config C; Config D)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Config D; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Creative)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; CSO 3.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; CWMIE55WDU)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DAC)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DIL0001021)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; distributed by ish)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DT; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DT; Hotbar 3.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DT; http://www.Abolimba.de)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DT; MSIECrawler)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DT; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; */E-Plus-002)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; ESB{1B6DEFA6-3A18-4B9B-9022-99348A8910CF})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; {FE627F21-305D-11D9-A75F-00055D2D4DD4})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; freenet 4.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; FunWebProducts-MyWay)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; FunWebProducts-MyWay; DVD Owner)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; GlobtelNet)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; HanseNet ADSL v1.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Hotbar 4.3.1.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Hotbar 4.3.2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Hotbar 4.5.1.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; HTMLAB)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; HTMLAB; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Installed by Symantec Package)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Jet2Web Internet Service GmbH)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; KITV4.7 Wanadoo)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; KSK sp. z o.o.)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; L1 IE5.5 301100)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; MRA 3.0 (build 00614))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; MSN 6.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; MSOCD; AtHomeNL191)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; NetCaptor 6.2.1A)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; .NET CLR 1.1.4322);JTB:15:82cffcc4-8761-4b59-9ba1-c2cba02980a7" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; N_o_k_i_a)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; OptusIE55-31)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; OptusIE55-31; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; OptusIE55-32)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; OTCDv1.4)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; PeoplePC 1.0; ISP)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Q312461; T312461; i-NavFourF; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0300Z)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0333s)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW03346)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW03347)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW03349)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0334h)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0334j)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW03354)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW03356)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0335n)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0335o)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0335v)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0336b)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW03373)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; qxw03376b)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0337i)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0337t)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0338o)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0338t)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0338t; MSIECrawler)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; QXW0530g)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; (R1 1.1))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; (R1 1.3))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; (R1 1.5))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Royal Perth Hospital)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; salzburg-online)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; SiteCoach 1.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; sureseeker.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; surfEU DE M2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; surfEU DE S1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; surfEU DE S3)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; T312461; Cox High Speed Internet Customer)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; T312461; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; T312461; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; T312461; V-5.5SP2-20011022)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; TBP_6.1_AC)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; TBP_7.0_GS)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; TBP_7.0_GS; DefensiveSurfing.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Teleos)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Teleos; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Terminal)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; tn3.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; tn4.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Turk Nokta Net; AIRF)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; version55)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; VNIE55)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Wanadoo 6.0; Feedreader)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98) WebWasher 3.3" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Wegener Arcade)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; A084)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; AIRF; FunWebProducts; Alexa Toolbar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Alexa Toolbar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; AN10HaendlerWelcomeletter1200)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; AN10HaendlerWelcomeletter1200; AO1.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Arcor 2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; AtHome021SI; (R1 1.5))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; AT&T CSM6.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; AVPersonalSerial 728479f8326c352757535b791d2e62b027776bc6)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Circle0701)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; CNE-Internet 02252000)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Creative)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; {D7B0F19C-92C9-4506-96FC-7357186B5914})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; DT-AT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; DT; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; DVD Owner)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; EDISINETD02)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; FDM)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Feat Ext 19)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; freenet 4.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; FunWebProducts; FunWebProducts-MyWay)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; FunWebProducts; MSIECrawler)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; H010818; BTT V3.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; H010818; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; H010818; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; HEP AS; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Hotbar 3.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Hotbar 4.1.8.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Hotbar 4.3.2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Hotbar 4.4.2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; IDL Internet)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; iebar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; iOpus-I-M)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Kit Terra Premium; FunWebProducts),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; libero)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; MSIECrawler)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; MSN 6.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; MSN 6.1; MSNbBBYZ; MSNmen-us; MSNc21; v5m)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; MSOCD)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; MyIE2; FunWebProducts; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; .NET CLR 1.0.3705; Hotbar 4.6.1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; .NET CLR 1.0.3705; Hotbar 4.6.1),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; ntlworld v2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; ONDOWN3.2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; OptusIE55-31)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; pbc4.0.0.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; PeoplePal 3.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Q312461; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; QXW0335v)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; (R1 1.3))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; (R1 1.5))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; sbcydsl 3.12; YComp 5.0.8.6; AT&T CSM6.0; AT&T CSM7.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; ScreenSurfer.de)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; SNET OLR v5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; SPINWAY.COM)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; StarBand Version 4.0.0.2; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; StumbleUpon.com 1.760; Alexa Toolbar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Supplied by blueyonder)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; surfEU DE M2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; T312461; (R1 1.3))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; TBP_7.0_GS)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; tele.ring Version 4.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; TUCOWS)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; V1.0Tomorrow1000)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; V1.0Tomorrow1000; Q312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90) (via translate.google.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; Wanadoo 5.4; Wanadoo 5.5; Wanadoo 6.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; YComp 5.0.0.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; www.vancouver-bc-canada-guide.com; NetCaptor 7.2.2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; YComp 5.0.2.5)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; YComp 5.0.2.6)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; ZDNetIndia)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; ZDNetIndia.com browser)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; ZDNetIndia; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; ZDNetSL)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Zon CD-rom versie 2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows CE)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; 1 & 1 Internet AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; 1&1 Internet AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; AIRF)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; by IndiaTimes)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; c_commcd1; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; CHIP Explorer :-)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; DekaBank; DGZ-DekaBank; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; DERA IE 4.01 Install 1.0.0.6-CD)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; DEV4012; SP4012)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; DigExt)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; DigExt; QXW03346)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; ENR 2.0 emb)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; F-5.0.0-19990720)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; FR 09/05/2000)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; FunWebProducts; Hotbar 4.4.5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; GDMS_98A_BRAZIL)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Gothaer Versicherung Mobil)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; H010818; DoJ-SOE-4.0.0.0-build-20000213)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; H010818; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; H010818; HEWLETT-PACKARD -- IE 5.5 SP1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Housenet Full 1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Humana1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; HVB 2/2001; T312461; HVB)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; ICN - 000407; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; IE55232Ab)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; i-NavFourF)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Installed by Symantec Package)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; IT-Office)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; L1 IE5.5 December 2000)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Logica 5.01.1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; LycosDE1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; MATAV_IE_55_HUN)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; MI Brandenburg; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; MSIE-5.5-DZBANK)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; .NET CLR 1.0.3705; Googlebot; .NET CLR 1.1.4322; .NET CLR 1.0.3705; Googlebot)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; N_O_K_I_A)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; norisbank; iOpus-I-M)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; P20314IEAK1; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Provided by UAL)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; QXW03002)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; QXW0330d)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; QXW0333v)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; QXW03346)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; QXW0334h; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; QXW03356)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; QXW03371)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; (R1 1.3))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; (R1 1.5))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; RBPD2711)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Sema UK Telecoms upgrade)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; SQSW)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Suncorp Metway Ltd)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461; FunWebProducts-MyWay)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461; IK)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461; (R1 1.1))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; T312461; Unilever Research)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; TIN ie4a32bit rel.1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Tucows)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; USHO-111203)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; v4.0 C3; v5 C5)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; Version 2/5.5 Customised)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; YComp 5.0.0.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT5)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5;Windows NT 5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; 1 & 1 Internet AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {2F8067D2-867C-4351-A289-786E8307965E})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; 3304)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; 3305)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; 360networks)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {4D391717-5781-46B1-9B5E-82D8014C43B0}; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {54ACD89C-CE9B-4CD3-9617-E30DE3DA8738})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {5A4938A5-F50D-46DE-80AA-C659EC68625D}; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {5C8D4EB8-815B-42DD-BF83-63A5F7F7377D}; Hotbar 4.4.6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {63AE5C75-6D69-4DC2-B8E2-F8E204D31206})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; 828750)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {A4E04F4A-3C7A-484D-B1E0-DE64E78EB309})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) Active Cache Request" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {AF9A0710-ED4B-4DEE-884C-E0BB887C2E44})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Agilent Technologies IE5.5 SP2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Agilent Technologies IE5.5 SP2; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Airservices Australia)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Alexa Toolbar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; AspTear 1.5)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; AT&T CSM6.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; AT&T CSM7.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; AWWCD)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; bkbrel07)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; BOCSIE55SP2; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; BTopenworld)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) But of course, that's a fake. I'm really running Mozilla on a non-Microsoft OS, and I've only set these headers to get around the restrictions of people who are ignorant enough to exclude the browser that " + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {C89A4139-160D-4323-B132-B58019B2AF1A})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; CBC/SRC)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; CHEP Australia; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; CHMC)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Coles Myer Ltd.)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; compaq)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; compaq; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Config D)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Config D; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Connex 13/02/2001; Connect 25/07/2002)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Creative)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; CSC)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; CWMIE55WODU)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; CWMIE55WODU; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; DAF)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Dept. of Primary Industries)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; DEUBA)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; DGD (AutoProxy4))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; DPU; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; DT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; DT; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; [eburo v1.3])" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; [eburo v1.3]; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; [eburo v1.3]; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; {EE17FE27-30FE-41A1-992C-71356B0262D1})" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; ESB{FC3DA1FF-49D4-4235-B656-6358FBC0D57B}; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; FDM)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Fisher-Price)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; FREE; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; FunWebProducts; maxweb)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; GameBar)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; GEP IE 5.5 SP2 Standard; GEP IE 5.5 SP1 Standard)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Groupe DANONE)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; 828750)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; Navstd27juin2001en)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; Q316059)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; H010818; UB1800; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Hotbar 2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Hotbar 4.1.8.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Hotbar 4.2.8.0; H010818)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Hotbar 4.4.5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; HTMLAB)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; ICT)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Installed by Symantec Package)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Installed by Symantec Package; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; iOpus-I-M)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0);JTB:104:a95eef30-9f35-4ec0-bc43-66a16a703faf" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; KSK sp. z o.o.)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; LCPL)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; LILLY-US-EN)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; LLY-EMA-EN)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Logica 5.5 SP2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Merrill IE 5.5 SP2 Install Kit; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; mhs)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; MSOCD; AtHomeEN191)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Nambour State High School (Queensland Australia); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2914)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; N_o_k_i_a)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; N_O_K_I_A)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Nokia 7650; 240*320)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; N_O_K_I_A; (R1 1.5))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; NSW.net)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; nwb)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; OptusIE55-31)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; OptusIE55-31; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Oregano2 )" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Patriot V5.5.1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; PRU_IE55SP1; PRU_IE55)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Q312461; iOpus-I-M)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Q312461; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; QXW0336o)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; qxw0337d)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; QXW0338d)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; (R1 1.1))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; (R1 1.3))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; (R1 1.5))" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; RA; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; RA; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; RC7.4 release)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; RC7.4 release; i-NavFourF)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; SCF - Mean & Nasty; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; SDS IE5.5 SP2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; S.N.O.W.2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; S.N.O.W.2; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; surfEU DE M1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; SWS)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; CAT-COE)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; DOJ3jx7bf)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; F-5.5SP2-20011022)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; F-5.5SP2-20011022; F-5.0.1-20000221)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; FunWebProducts)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; Guidant IE5 09302001 Win2000 Distribution; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; istb 702; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; ITS 2.0.2)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; MSIECrawler)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; .NET CLR 1.0.3705)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; PC SRP 2.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; POIE4SP2; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; TBPH_601; Feat Ext 19)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; TheFreeDictionary.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Thiess Pty Ltd)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T-Online Internatinal AG)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; U)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; Unknown)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) (via translate.google.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; www.ASPSimply.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; www.bfsel.com)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; WYETH)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; YComp 5.0.0.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; YComp 5.0.8.6)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; ZDNetIE55)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.1)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.7 [en] (compatible; MSIE 5.5; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.8 [en] (compatible; MSIE 5.5; Windows NT 5.1; U)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.0 (compatible;MSIE 5.5; Windows 3.11)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.0 (compatible;MSIE 5.5; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.5; Windows NT 5.0)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.5; Windows XP);" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.1 (compatible;MSIE 5.5; Windows 98)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/7.2 (compatible; MSIE 5.5; Windows 98; DigExt)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "MSIE 5.5" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5.1; Windows NT 4.0; T312461; spw500; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "MSIE 6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 (compatible; MSIE 6.0; Windows 98; 240X320; PPC; Default)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.00; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 5.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 5.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 5.0; Windows 98; Win 9x 4.90; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 6.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 6.0; Windows 98; Creative)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 6.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 6.0; Windows 98; Win 9x 4.90; Q321120)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 6.0; Windows NT 5.1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows 98; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows 98; Win 9x 4.90; freenet 4.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; FunWebProducts; SV1; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; Hotbar 4.3.2.0; BCD2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; Hotbar 4.4.7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; PCUser; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; Q321120; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; Q321120; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 7.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; {5F4036E0-6271-11D8-8929-000AE67C2897})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; AT&T CSM6.0; FunWebProducts; Hotbar 4.2.9.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; Compaq)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; GA55sp2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98);JTB:2:825c2721-bc07-11d8-bdea-444553540000" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; Win 9x 4.90; AT&T CSM6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; Win 9x 4.90; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; Win 9x 4.90; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows 98; Win 9x 4.90; OUBrowser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; {1EB73F69-5BFB-4D8C-9BA8-72A428DA75D3}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; {3B4748F2-EE14-4317-B069-7AB6F7AEFE69})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; BTOW V9.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; CDSource=storecd_01_03; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; CDSource=v9e.05)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; DigExt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; FunWebProducts; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; generic_01_01; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; Hotbar 4.4.6.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; SaveWealth)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; StumbleUpon.com 1.751)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; SV1; FunWebProducts; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; YComp 5.0.0.0; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; YComp 5.0.0.0; SYMPA; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; Win 9x 4.90; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; Win 9x 4.90; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; Win 9x 4.90; YPC 3.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows 98; YComp 5.0.0.0; AT&T CSM6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.0; Hotbar 4.3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.0; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {07D8E8DA-0530-4B69-A0A4-7EB7CB54C821}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {2E4B39C0-67F6-4E50-BD40-FAD19B5CAA8A})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; 3305)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {7197B170-E810-4522-9DC0-088AAD5AD6E9}; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {723EBBEB-CBB8-4A00-AD75-0A0B1A0517ED})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {8B658E16-E35C-4C43-A913-307AA2BADC55}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {9CCDF57C-A828-47C1-9431-3670BDEC44B6}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {9D60457B-6A0F-4CAF-8C22-B463BC201CBB})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; BCD2000; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; CDSource=storecd_01_03; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; CDv5.1.1_1099)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {D2F65954-6A14-43B5-86BE-42556275B763})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; dial)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; DigExt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; ESB{67E15522-64F5-4326-B157-10FF147CA5E9}; ESB{EF27D6C9-1D19-4ED9-B494-FA921D24CCB0}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; {FD960C72-0B96-40FA-BFF5-6B1CE3F64B60}; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; SV1; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; FunWebProducts; YPC 3.0.2; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; generic_01_01; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Hotbar 4.2.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Hotbar 4.3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; iOpus-I-M; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Preload_01_07)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Q312461; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Q312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Q312461; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; (R1 1.5); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Roadrunner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Roadrunner; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; SV1; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; Creative; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; FunWebProducts; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; Grip Toolbar 2.07a; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; Hotbar4.5.3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; Media Center PC 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Media Center PC 3.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; v8c.01; Hotbar 4.2.11.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; Wanadoo 5.5; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; YPC 3.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; YPC 3.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.9; Beta 0.9.4201.270; Browser Control 0.9.0.4; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; {DB0219C0-5374-11D9-81F0-00010292A080})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; GTelnet1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98) OmniWeb/v496" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; Win 9x 4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; Win 9x 4.90; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 4.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 4.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 4.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; iOpus-I-M; SEARCHALOT.COM IE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; CS 2000 6.0; Wal-Mart Connect 6.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; CS 2000 6.0; Wal-Mart Connect 6.0; Windows 98; Compaq)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; CS 2000 6.0; Wal-Mart Connect 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; CS 2000 6.0; Wal-Mart Connect 6.0; Windows NT 5.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; CS 2000 6.0; Wal-Mart Connect 6.0; Windows NT 5.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; CS 2000 6.0; Wal-Mart Connect 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; CS 2000 6.0; Wal-Mart Connect 6.0; Windows NT 5.1; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; AOL 8.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; AOL 8.0; Windows 98; {99AEF9F6-AD65-4E28-B512-F173232EBD29})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; AOL 9.0; Windows 98; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla /4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; AT&T WNS5.0; AT&T CSM6.0; AT&T CSM8.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; FunWebProducts; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; iPrimus; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; PCUser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; sureseeker.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; sureseeker.com; searchengine2000.com; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; Win 9x 4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98; YPC 3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows NT 5.1; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.6; Windows 98; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.6; Windows 98; T312461; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.6; Windows 98; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98; Creative)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98; Hotbar 4.3.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98; MSOCD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98; T312461; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98; Win 9x 4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSNIA; Windows 98; Win 9x 4.90; AT&T CSM6.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 3.1; Wanadoo 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 95)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 95; PalmSource; Blazer 3.0) 16;160x160" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/ 4.0 (compatible; MSIE 6.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98);" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible;MSIE 6.0;Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; 100)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; 1&1 Internet AG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; 1&1 Puretec)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; 1&1 Puretec; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {12Move})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; 1.57.1 )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {1A030500-6279-11D8-91F9-00055D306537}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {29C5C4C0-87CA-11D8-94C0-00E07DE10B20})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {3171E4C0-49BB-11D9-8CA9-D07E76ABD032})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; 3304; MSN 8.0; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; 3305)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {57F5F0C1-E226-11D8-A9B2-00C04F5BBF26})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {62FF51C0-7B8B-11D8-AD78-004F4905E079})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {6C917480-655F-11D8-8622-444553540000})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {728C4D40-8C75-11D9-86F6-D73001167134}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {7E8AF401-1A03-11D9-BF45-444553540000})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {7EC49A61-187E-11D9-824D-0008A15DF7A2}; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {8F9DB3A0-A757-11D8-A1FE-444553540000}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {9C20C200-1109-11D8-8F74-444553540000})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AAPT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AIRF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AIT; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; alice01; DP1000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; alice01; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; alice01; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Alitalia Custom)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; APC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; APCMAG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; APCMAG; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AskBar 3.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AskBar 3.00; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AskBar 3.00; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AtHome0107)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AtHome0107; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AtHome033)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AtHomeI0107)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AtHomeI0107; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AT&T CSM6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AT&T CSM6.0; AT&T CSM7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AT&T CSM6.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AT&T CSM6.0; Q312461; AT&T CSM7.0; AT&T CSM8.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AT&T CSM7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AT&T WNS5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AT&T WNS5.0; MSOCD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; austarnet_2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; AUTOSIGN W2000 WNT VER03)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Avant Browser [avantbrowser.com]; OptusNetDSL6)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {B3EB8D41-DE48-11D8-BBF4-00804815CB32})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BB1.0 IE5.5.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {BBA839A0-7F6C-11D9-8278-0080C8E10726})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BCD2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BCD2000; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {BDBAC461-139C-11D9-B962-00A0CCD11F28})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BIGPOND_ADSL_42)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BIGPOND_ADSL_42; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BPB32_v2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; bpc; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BPH03)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BPH32_55a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BPH32_59; OptusIE501-018)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BTO E1.07; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BTOW)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BTOW V9.0; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BTOW V9.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; BTOW V9.5; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {CA066580-6E9C-11D8-97BC-0060088DA696}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; CDSource=cannonst)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; CDSource=v2.15e.04)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; CDSource=vBB1c.00; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Centrum.cz Turbo2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Compaq)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Computer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Cox High Speed Internet Customer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Cox High Speed Internet Customer; NetCaptor 7.5.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Cox High Speed Internet Customer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; cPanelGui 6.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Creative)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Creative; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; CSOLVE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; DCSI)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Deepnet Explorer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; DigExt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; DigExt; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; digit_may2002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; DIL0001021; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; DP1000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; DT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; DVD Owner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; DVD Owner; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {E39750C0-6F5B-40B4-9D70-0681DB8795DA})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; eBook)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)::ELNSB50::0000411003200258031c016c000000000506000800000000" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)::ELNSB50::0000411003200258032001df000000000507000900000000" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)::ELNSB50::000041100400030003de0208000000000502000800000000" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)::ELNSB50::000081900320025803140197000000000502000800000000" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; ESB{13B30CE0-EC80-11D8-83BE-0001031746AB})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; ESB{BBA298E0-3889-11D8-9F02-0010B5525635})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; ESB{F0B8BB20-643F-11D0-9C90-00C0F0741766}; yie6_SBC; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; ezn73ie5-1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; EZN/PC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; EZN/PC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {F361FD20-F590-11D7-AFAF-0050FC225B60})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; F-5.0.0-19990720; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; {FD464440-B8BD-11D8-9957-00010273BF2C}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; formatpb)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FREE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; freenet DSL 1.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; freeonline)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; fs_ie5_04_2000i)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; fs_pb_ie5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; Feat Ext 21)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; FunWebProducts-MyTotalSearch)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; Hotbar 4.4.2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts-MyWay; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; NN5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; FunWebProducts; SEARCHALOT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; GFR)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; APCMAG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; Hotbar 4.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; i-MailBook)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; MathPlayer 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; VZ_IE6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; H010818; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hellas On Line; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.1.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.1.8.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.3.1.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.3.2.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.3.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.4.5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.5.1.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.5.1.0; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; HTMLAB; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; ICONZ IE5CD; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; IDG.pl)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; IE5.x/Winxx/EZN/xx)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; IESYM6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iiNet CD1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; i-Nav 3.0.1.0F)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Installed by Symantec Package)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; InterNetia 0002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iOpus-I-M; ISP40; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iOpus-I-M; MyIE2; FunWebProducts-MyWay)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iOpus-I-M; NetCaptor 7.5.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iP-BLD03)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iPrimus)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; iPrimus; OptusIE501-018)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98);JTB:140:1255fb21-285b-11d9-bc23-444553540000" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98);JTB:15:344477a2-2c6d-11d9-a611-000854034fa2" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; JUNO)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; JyxoToolbar1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; KB0:176933)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; KPN)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MADE BY WEBO)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MathPlayer 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MathPlayer 2.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MathPlayer 2.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MindSpring Internet Services)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSN 8.0; MSN 8.5; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSN 8.0; MSN 8.5; MSNbQ001; MSNmen-us; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSN 9.0;MSN 9.1; MSNbQ001; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSN 9.0; MSNbBBYZ; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSOCD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSOCD; AtHome021SI; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSOCD; AtHomeEN191)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSOCD; Cox High Speed Internet Customer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MSOCD; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MyIE2; iOpus-I-M; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MyIE2; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; MyIE2; Q312461; Maxthon)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Neostrada Plus 5.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Neostrada TP 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Neostrada TP 6.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; NetCaptor 7.5.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; NetCaptor 7.5.3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; .NET CLR 1.1.4322),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; .NET CLR 1.1.4322; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; NN4.2.0.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusIE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusIE501-018; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusIE501-018; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusIE55-27)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusIE55-28)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusIE55-31)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusIE55-31; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusNetCable-02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusNetDSL6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OptusNetDUI6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OZHARLIT6.0_1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OZHARLIT6.0_1_PP3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; OZHARLIT6.0_1_PP3; Hotbar 4.1.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Panoramic IT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PCM_04; DVD Owner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PCM_06a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PCPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PCQuest)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PCQuest; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PCUser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PCUser; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PCUser; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PeoplePC 1.0; hpford)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PeoplePC 2.4.5; ISP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PeoplePC 2.4.5; ISP; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Pioneer Internet - www.pldi.net)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PKBL008; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PN)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PowerUp IE5 1.01.02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; pro)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; provided by blueyonder)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; AT&T CSM6.0; AT&T CSM7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; DF23Fav/2.5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; H010818; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; H010818; yie6_SBCDSL; sbcydsl 3.12; YPC 3.0.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; TUCOWS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q312461; YComp 5.0.0.0; NN5.0.3.3; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q321017)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Q321120; Feat Ext 1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW03398)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW03399)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW0339a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW0339b; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW0339c)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW0339d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW0339m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW03404)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW0340e; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW0340k)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; QXW03416)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; (R1 1.1); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; (R1 1.3); (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Roadrunner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Roadrunner; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Rogers Hi-Speed Internet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Rogers Hi-Speed Internet; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; sbcydsl 3.12)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; sbcydsl 3.12; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SEARCHALOT.COM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Sgrunt|V108|867|S538318592|dial; snprtz|S03066638220053; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SIK1.02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SIK30)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SIK30; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SIS; {SIS})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SiteKiosk 5.5 Build 36; HBBKLP01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Skyline Displays, Inc.; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SL102000; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SpamBlockerUtility 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Spartipps.Com PS Edition; iOpus-I-M; MyIE2; DX-Browser (V4.0.0.0; http://www.dxbrowser.de))" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SPINWAY.COM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Strato DSL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; StumbleUpon.com 1.735)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; StumbleUpon.com 1.758)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; StumbleUpon.com 1.760; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Superonline)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Supplied by Cloudnet, Inc.)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; supplied by tiscali)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; sureseeker.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SYMPA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; SYMPA; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; Hotbar 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; Newman College)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; Q312461; Hotbar 4.0; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; Q312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T312461; V-5.5SP2-20011022)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; TBP_6.1_AC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; tco2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; telus.net_v5.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; telus.net_v5.0.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; TencentTraveler )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; TeomaBar 2.01; Wysigot 5.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; tiscali)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; TNET5.0NL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; T-Online Internatinal AG; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Total Internet; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; TUCOWS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; TUCOWS; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; TUCOWS; Q312461; FunWebProducts; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Ubbi)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; V1.0Tomorrow1000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; v11b.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; V-5.5SP2-20011022)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; VNIE5; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; VNIE5 RefIE5; SCREAMING_IE5_V2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; VNIE60)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; VZ_IE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; VZ_IE6; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; W3C standards are important. Stop fucking obsessing over user-agent already.)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Wanadoo 5.6),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Wanadoo 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Wanadoo 6.0),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Wanadoo cable; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; WC/qrDwCOdiRzNfl)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Web Link Validator 3.5" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) WebWasher 2.2.1" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; WestNet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x4.90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; 1&1 Internet AG by USt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; {2A23FA2A-F9FD-484E-801D-DF232F7C64BA}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; {74787047-5497-4FC4-8302-D08B74E01B4B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; APCMAG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; AskBar 3.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; AT&T CSM6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; AT&T CSM6.0; AT&T CSM8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; AT&T CSM6.0; VZ_IE6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; AT&T ELC5.5; T312461; {Cablevision Optimum Online})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; AT&T WNS5.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Avant Browser [avantbrowser.com])" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Avant Browser [avantbrowser.com]; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Avant Browser [avantbrowser.com]; YPC 3.1.0; iOpus-I-M; .NET CLR 1.1.4322)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; BIGPOND_ADSL_42)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; BIGPOND_ADSL_42; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; brip1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; BT Business Broadband)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; BT Openworld BB; YPC 3.0.2; FunWebProducts; yplus 4.3.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; BTopenworld; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; {C954D864-F84E-7490-1E6D-7AF74AE2E175})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; CDSource=ALLIED_01_01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Charter B1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Cox High Speed Internet Customer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Creative)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; c't)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; DT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; DT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; DT; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; DT; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; {E895B1EF-805F-4965-88D8-54AF2D5541F7})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; EnterNet; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; ESB{6BC1B80D-8E38-4080-99B0-2440E59328A1})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; {F77382BC-AB24-49B4-8059-71D9365FEEB2})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Feat Ext 19)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Feedreader)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FREE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; freenet 4.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FREESERVE_IE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FunWebProducts; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FunWebProducts; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FunWebProducts; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FunWebProducts-MyTotalSearch; FunWebProducts; Hotbar 4.4.6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; FunWebProducts; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; generic_01_01; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; H010818; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; H010818; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Hotbar 4.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Hotbar 4.1.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Hotbar 4.2.11.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Hotbar 4.2.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Hotbar4.5.3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; HWE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; iebar; MSN 9.0;MSN 9.1; MSNbQ002; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; JJ)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Mailinfo [1999999999999999])" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MSN 9.0;MSN 9.1; MSNbQ002; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MSN 9.0;MSN 9.1; MSNbQ002; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MSN 9.0; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MSOCD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MSOCD; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; MyIE2; Free Download Manager)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; ONDOWN3.2; AtHome021SI)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; OptusIE55-31)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; OptusIE55-31; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; OptusIE55-31; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; OptusNetCable-02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; OptusNetDUI6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; OUBrowser; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; PC ACTUAL (VNU Business Publications España)),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; PCUser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; PCUser; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; PCUser; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Provided by Alphalink (Australia) Pty Ltd; H010818; FunWebProducts);JTB:15:d16f74f8-64d6-4024-a74d-b8724a1c548c" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; FtSoJ 666)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; Hotbar 4.1.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; Hotbar 4.5.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; LDE0308a; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; SEARCHALOT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461) WebWasher 3.3" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q312461; YPC 3.0.1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Q321120; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Queens-ITS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; QXW0337s)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Roadrunner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Rogers Hi-Speed Internet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Rough Cutz)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; sbcydsl 3.12; FunWebProducts; yplus 3.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; sbcydsl 3.12; YPC 3.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; SIK1.02; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; SIK30)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; SIK30; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; son0302CD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Sunet v2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Supplied by blueyonder)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Supplied by blueyonder; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Supplied by blueyonder; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; SYMPA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; T312461; Headline-Reader; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; T312461; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; T312461; Wanadoo 5.3; Wanadoo 5.5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; T312461; Wanadoo 5.5; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; TeomaBar 2.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; T-Online Internatinal AG; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; TUCOWS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Virgin 3.00; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; VZ_IE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; VZ_IE6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; Xtra)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; YComp 5.0.2.5; SIK30)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; yie5.5_SBCDSL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; yie6_SBC; YPC 3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; YPC 3.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; YPC 3.0.1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90; YPC 3.0.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; WRV)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; www.ASPSimply.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; www.k2pdf.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; www.spambully.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Xtra)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Xtra; Hotbar 4.3.5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.0.0; Cox High Speed Internet Customer; sbcydsl 3.12" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.0.0; OptusIE55-31)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.2.4; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.2.5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YComp 5.0.2.6; IESYM6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6; iebar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBCDial; YPC 3.0.0; FunWebProducts; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBCDSL; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBCDSL; sbcydsl 3.11; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBCDSL; sbcydsl 3.12)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBCDSL; sbcydsl 3.12; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBCDSL; sbcydsl 3.12; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBCDSL; sbcydsl 3.12; yplus 3.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6_SBC; YPC 3.0.1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; yie6; YComp 5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.0.0; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.0.0; BT Openworld BB; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.0.1; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.0.2; BT Openworld BB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.0.2; BT Openworld BB; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; YPC 3.1.0; yplus 4.5.03b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; MyIE2; PPC; 240x320; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows compatible LesnikBot)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; 11-12-2002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; 3COM U.S. Robotics)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; ABN AMRO)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; AIRF; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; APC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; APCMAG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Aztec)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Bank of New Zealand)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; BVG InfoNet V5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; CLS4; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; CNETHomeBuild03171999; DigExt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; COLLAB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0; Config A V1.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0; Config A V1.3; Config C V1.3; v5 C5; Config D V1.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0; Config A V1.3; Config D V1.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0; Config A V1.3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0; Config A V1.3; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0; Config A V1.3; v4.0 C3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0; Config A V1.3; v5 C5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Config A V1.0; Config D V1.3; Config A V1.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; CT2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Deepnet Explorer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; digit_may2002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; digit_may2002; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; eircom/june2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Girafabot; girafabot at girafa dot com; http://www.girafa.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; H010818; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; H010818; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Hays Personnel Services)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Hotbar 4.1.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Hotbar 4.1.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Hotbar 4.4.5.0; Config A V1.0; Config A V1.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; HVB 2/2001; HVB-GROUP, 0001_CIT; spunt-ois-intranet; ois-intranet; HVB: NT-OIS; HVB; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; HVB 2/2001; HVB; NT-Zentrale; HVB-GROUP, 0001_Zentrale; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; IE55CX1; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; JPMC_CDI)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; MCS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; MRA 2.55 (build 00423); MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; MSIE5.0; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; MyIE2; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; NAB PC IE6SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; NetServ; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; P20314IEAK1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; PCQuest; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; PCUser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; po; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Q312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Q312461; QXW0339m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Q342532)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Qwest - 11122003-a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; QXW0339c)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; QXW0339m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; RBC; 9LA; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; RZNT2000.010)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; SDE 2/12/02 1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; SEARCHALOT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; STIE5-000710)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; supplied by tiscali)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; DI60SP1001; DOJ3jx7bf; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; Hotbar 4.1.8.0; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; Q312461; (R1 1.1); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; Q312461; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; SI; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; T312461; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; terranet.pl; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; TESIEAK6a; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; TTC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; TUCOWS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Union Pacific Corporate Image)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; v1.0 C1; v4.0 C3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; v1.0 C1; v4.0 C3; iOpus-I-M; v2.0 C1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; v1.0 C1; v4.0 C3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; www.ASPSimply.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Yahoo-1.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; YComp 5.0.0.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0;)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible;MSIE 6.0; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {01B9B056-41CF-4C49-9F15-FBFD356FACB9}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {06123460-5191-47D8-9801-E64CEE8E7D7C}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {061F9742-FB3A-4B13-8D81-F1DBCFA49E24})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {06537897-63B2-495D-BD75-97D5F17AEF61}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {0D43CA9A-9A2A-4AD3-9FB3-D11ED856701C})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ¾ÜÆÄÀÏ (atfile.com); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {109E9252-FC9D-4712-9D79-AC1C6061FD02}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 1&1 Internet AG by USt; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 123-Reg The Cheapest & Easiest Way to Get a Domain Name)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {12AB035D-BD79-4DED-B042-E95ED524B435}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {143F7CDC-2BEF-45ED-9CA0-9B2076F467D4}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {144098F2-DE3D-4A0E-AA56-C97DABCBEC15})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 1.57.1 )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {19449247-55EC-4B9A-A99C-A1FD75AB322A})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {1AAA4471-A825-4D94-9F91-18DF18D97101}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {1B07E273-0A6C-440D-8E04-CBB9F30106AD})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 2.5.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {282E02E6-44BF-4FF6-9C84-59755CC87202}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {298A087F-0FE1-40C9-A893-97A76A73F88E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {2C0881E9-B6B7-45DB-BFDF-F70BB47FA680}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {2DABB6D9-031A-4174-9C59-D87776C152AC}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {2E487848-058A-4532-83EE-AFF12A987739}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {305B1A70-D1DC-45EF-AA35-F707BBEE85EC}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 3303; iebar; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {338C77F9-6668-40F2-B9AA-7B8B3AACAADA}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {3504DB01-C872-40F5-90A1-A76E8C7BA7F8})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {359046E3-C000-44A8-90B3-BA1FA146D3ED}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {3FD9CEF8-894A-4FFE-BD59-6B3A28A6967A}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 3M/MSIE 6.0;; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 3M/MSIE 6.0;; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {4E075391-5B06-46A7-872B-70EB64C44294})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {4EC4D46A-2224-42E4-B20E-263A00146AD5}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {4F1675AF-7549-42E8-A055-6E4554DDB2B6})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {53D150F0-3948-40FB-AED0-BC12A07D16CB}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {57B317DC-AF18-477D-B26C-D635B7BC0C6C}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {59290DD6-57E1-419C-A050-BC983EB72656})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {5C6515F0-765B-4AD8-A168-3761FB537EBB}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {5DB0254E-3F8C-4DDA-A3D4-6C543537187B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {607C5361-86F7-42A1-8BC4-E3BB7EF36E49}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {62BA8785-A517-4CF6-8456-56716A6D1158}; iebar; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {649E2463-3332-4F08-A0B1-8CCC13C2A5B6}; CLX-IE-5.5sp2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {665CA5DF-6149-4382-9952-7B39C4A56AD1})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {68B11FD1-3CDB-4433-8D4B-FAC8D8352E6E}; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {6B81900A-D6AA-461E-8FC6-1620330AC921}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {6B9216F6-4521-47B0-B084-2A8E511A0B9F}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {6D3765E4-9B4F-43FA-A724-82E2F0EF0D1F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {6E0F184F-9748-4A0E-8B0C-F812273A1D33})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {6E678899-843C-496E-9B27-A35206C3E26B}; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {6EFA4147-88FB-4570-8DA4-EE21FA159006}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {70E73558-8F52-4A75-9312-C8E68DEDAB57})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {7144A0D4-D427-4095-B265-D15A8756742F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {79AF7E55-D81C-44D9-8636-94129DF9DF37}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {79CEA9FC-BE53-45A3-B81D-B66479A78C7D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {7A9D705C-6447-43AF-9CBD-F3EBBC64467D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {8036F106-4980-4D9C-8E40-BC990D1C5340}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {81629412-DDAE-4320-9573-1909044055F5})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {86464A58-0461-4217-8D58-67F6F1813A02}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {89CD3E7F-86F4-4766-8A15-773ED2B1ECDA}; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 90)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {90333DAB-0FE6-4FE7-9F0A-37211DA1DD26})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {90A67E22-1FA8-46DB-913D-5BFAB83B9187}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {9444DFA5-F00A-4C9C-A481-D228454293AC})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {96C6F6D2-27AB-4CE8-A693-5FB34DED41C9})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {9C8127EF-235E-4DB5-A132-FB67DCB6DB9E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; 9L5.5; 9LA; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {A253E2A3-43A6-4F7C-ACE5-7ACE750E8496}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {A26143E3-E395-4A08-906C-2094F96F9992}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {A39C4CA3-D28E-48DF-A362-5D0862045D4B}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {A45DB481-08E3-4625-85C0-18D272EFA672})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {A5E3D903-A7D5-493D-8319-D7A126A43C4E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {A64C95F3-2891-4793-8163-A6165CF588EC})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {A6B5140D-D366-4853-A784-224D481F964A})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {A6E2595A-77BF-4A90-BDD6-581660B19BAF}; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AAL; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AAPT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ABACUS LABS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Abbey National PLC; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Abiliti Solutions; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ABN AMRO)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ABN AMRO; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ABN AMRO; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Agilent Technologies IE5.5 SP2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Agilent Technologies IE5.5 SP2; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Agilent Technologies IE5.5 SP2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AGIS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AIRF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AIRF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AIRF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AJA; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alcatel Portugal IE6 SP1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alexa Toolbar; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; alice01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ANZ Banking Group)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ANZ Banking Group; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AOL 9.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APC; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APCMAG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APCMAG; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APCMAG; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APCMAG; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APCMAG; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APC; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; APC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AQL - Groupe Silicomp; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AskBar 3.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AskBar 3.00; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AskBar 3.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AskBar 3.00; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM6.0; AT&T CSM 6; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM6.0; AT&T CSM7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM6.0; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM6.0; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM6.0; www.ASPSimply.com; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM7.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM7.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T CSM8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; AT&T WNS5.1; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser 6.5.1.3 [avantbrowser.com]; .NET CLR 1.1.4322)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser 7.0.0.8 [avantbrowser.com]; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]; Feedreader)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]; i-NavFourF; NetCaptor 7.2.2)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]; MyIE2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]; .NET CLR 1.1.4322)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avi 1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {B0B866F5-5095-4A87-AD12-D436006DEE38}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; b2c01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {B42D1284-FDB2-4F37-A1DF-857CBBCA89B2})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {B75CE5DB-567A-44D7-920D-1228B51B3B3E}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Bank of New Zealand)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BAssF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BB1.0 IE5.5.2; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BB1.0 IE5.5.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BB&T Standard Load (IE 6 sp1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BCD2000; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BCIE6SP1; .NET CLR 1.0.3705; Working 081103 Rev 6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BCUC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; bfz Aschaffenburg)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; bgflie; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BIGPOND_ADSL_42)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BIGPOND_ADSL_42; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Boeing kit)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Boeing Kit)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Boeing kit; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Boeing Kit; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Boeing kit; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BOTW)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BOUK)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; brip1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; brip1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BSS; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BT [build 60A])" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; btclick.com Build BTCFMFQ3; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BT Openworld BB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BTopenworld; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; bull ;-) ; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Business 1st; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; BWL 5.5 IEAK; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; by Hi-HO)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; c20010830)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {C545DFFA-2A55-4A99-AC19-EB846E5457EA})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {C5C1AC35-93B1-48C0-BAD1-FD616C71A118}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {C6A15346-4AC9-4272-8CF7-151480C6A9D4})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {C7132536-FBAC-4135-9D87-C6DEC6B0AFE0}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {C8EA929F-150F-4C5F-81E2-A258BEDBF712})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {Cablevision Systems Corporation})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {CB1C5177-05C4-4DFE-B687-AD6AF39ACD3E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {CB46BCEF-212D-452A-9341-734FBBA61540}; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CBC/SRC; Hotbar 4.4.9.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CCSU; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {CD8D3547-6274-46D5-947D-12B00C362FD5}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CDSource=ALLIED_01_01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CDSource=ALLIED_01_01; ESB{1A596234-D5AD-49CF-A3D5-B814562D9F84})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CDSource=ALLIED_01_01; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CDSource=BP1b.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CDSource=BP1b.00; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CDSource=v2.15e.03; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CDSource=v2.15e.04)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CDSource=vBB1c.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {CF867BA5-3DE3-4197-A46B-0C7BBF5C2285}; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {CF8E2F64-C6B1-4DAE-BFDE-0D69737FAA8A})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Chemopetrol)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CHOP_IE55_V2; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CHWIE_SE60)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CIBA SC Standard Setup)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CIBA SC Standard Setup; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; City of Mesa, Mesa, AZ, USA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CL_P2K_1_1_2_1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CNGTRUST)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CO770; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Coles Myer Ltd.)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Coles Myer Ltd.; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Coles Myer Ltd.; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; COM+ 1.0.2204)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Combellga; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; compaq)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Compaq; DigExt; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; compaq; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; compaq; T312461; Hotbar 4.1.8.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Compatible; Version; Platform; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Computer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Computer) WebWasher 3.3" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Config D; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Conman 2.5; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Cox High Speed Internet Customer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Cox High Speed Internet Customer; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Cox High Speed Internet Customer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CoxIE55)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CoxIE55; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CPT-IE401SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CPWR)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Creative)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Creative; iebar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CSMMWebClient1001; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CSUF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; cust 2.01 r7; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Customized by Adrian Connor; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; CyberZilla; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {D208973F-8755-4E82-A102-0AAA11511D7B}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {D4183739-BB5C-46AB-B754-64727133F2A5}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {D48C8B2F-108A-48C8-9F5F-058A0125BFB9})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {D86494B1-7D5D-4748-838D-529552349E2B}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {DA7D9C31-C746-405E-A35A-6798A9DD3842})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Data center)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Datavend Internet Services)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DCC=6.SP1-E)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {DD52EB3A-6F72-4BDC-8490-161016E9E39C})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Debian Linux; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Deepnet Explorer 1.3.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Deepnet Explorer 1.3.2; Lunascape 1.4.1)" + family: "Lunascape" + major: '1' + minor: '4' + patch: '1' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Deepnet Explorer 1.3.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Deepnet Explorer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Deepnet Explorer; .NET CLR 1.1.4322; .NET CLR 2.0.40607; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Deptartment of Premier & Cabinet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Dept. of Primary Industries)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DeptoMtz/237)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DET_ITD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DHSI60SP1001)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DHSI60SP1001; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DHSI60SP1001; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; dial)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Dialer/1.10/ADSL; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; dial; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; Hotbar 4.2.11.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; MyIE2; FDM)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; OZHARLIT6.0_1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; Q312461; NetCaptor 7.0 Beta 3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; Q312461; NetCaptor 7.0 Beta 5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; ScreenSurfer.de; http://www.ScreenSurfer.de; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; Tucows)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DigExt; YPC 3.0.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; digit_may2002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; digit_may2002; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; digit_may2002; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; digit_may2002; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DIL0001021)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DOF-IE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DOJ3jx7bf; T312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; drebaIE-ZE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DrKW=IEAK; DrKW; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DrKW; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DT-AT; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DT; i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; DVD Owner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {E39E04A9-A873-4BEB-8AC9-8AAE2C5F4B36}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {E4CBDA2C-2AD6-4963-934B-78AA66873B09})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; E5; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {E6BC9F59-0BE1-42F0-B30B-28E630FC426C})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; [eburo v1.3])" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {EDEBBC92-1A23-4CCF-A287-E7C446EE184E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; EDS; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; eircom/june2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; EMC IS 55; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Endeavour Sports High School)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Era)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ERACON AG; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{18990B24-B930-4963-9F4A-61EC73B586A7})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{262D05ED-F4C4-41AA-9DF8-72398CBAFD6B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{3B40AD5C-7E2F-46D4-9A6A-7C43322AC378}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{3E1AFDF1-14A8-422C-AE93-58363EDEAF96})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{5CEA4270-4309-43DE-913E-4A34AC4DDAC0})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{5D6E1D2C-9FB8-4423-8E9D-9AD635CED031}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{6000F0D1-9B3D-429E-9991-2DA84AB29E7A}; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{69A214B6-5A7B-43E5-89D8-E8F4A9946F3E}; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{97B6FDFD-F75F-4CB4-8F1D-FA16B707E202})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{9FFE22ED-496B-4730-B4EA-CFCDCAF1FCAE})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{A6A5FEED-9585-4F90-8424-38ED6FD61D32}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{CDD58A96-417A-4783-B196-B39BD35B879E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{E8E61902-FB81-4DDA-8BD2-1CE907F88866}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{F512E5D9-AF79-49FE-A3A6-83693239F5C0})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ESB{F7D303AF-E887-4662-945C-FF4B3413A379}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; EV20020426A; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; EXPRESS_004; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ezn)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {F1EA689F-1B1F-474B-8E21-C2122AD49CE8})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {F30610B3-0195-4745-BFEF-D07509032CA2})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; F-5.0.1SP1-20000718; F-5.0.1-20000221; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {F60857FB-3034-40CF-9E34-A28D3EF30C9F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; F-6.0SP1-20030218)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; F-6.0SP1-20030218; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {FABA9F34-879A-44F2-84B8-83E37CC31579})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FastWeb)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FastWeb; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FCP Intranet Browser; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {FD5A89C5-E2DA-4278-BBCB-B19DA07185AB}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {FD604FB4-DBBF-481F-A46F-543390363E21})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; {FDD074C3-CFD3-4CD5-B6FA-1A4AE8C0852D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FDM; COM+ 1.0.2204)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FDM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Feat Ext 19)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Feat Ext 21)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Feedreader)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Feedreader; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Feedreader; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Feedreader; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Feedreader; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Flow Systems)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; formsPlayer 1.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; formsPlayer 1.3; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FORSCOM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Franciscans Australia; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FREE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FREETELECOM; Wanadoo 6.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FREE; Wanadoo 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Fujitsu Services GmbH, Germany; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; bkbrel07)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; FunWebProducts-MyTotalSearch; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; GameBar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; Hotbar4.5.3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyTotalSearch)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyTotalSearch; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyWay; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyWay; MSIE 6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyWay; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyWay; .NET CLR 1.0.3705; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyWay; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts-MyWay; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.0.3705; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.1.4322; Google-TR-1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 1.1.4322; .NET CLR 2.0.40301)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; (R1 1.5); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FunWebProducts; Telia; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; FUSAIE55SP2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GENA SDV2.1; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GEP IE 5.5 SP1 Standard)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GEP IE 5.5 SP2 Standard; GEP IE 5.5 SP1 Standard; GESM IE 5.5 SP2 Standard)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GEP IE 5.5 SP2 Standard; GEP IE 5.5 SP1 Standard; T312461; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GEP IE 5.5 SP2 Standard; GEP IE 5.5 SP1 Standard; T312461; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GIS IE6.0 Build 20020920)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GIS IE6.0 Build 20031007)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GIS IE6.0 Build 20031007; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GIS IE6.0 Build 20031007; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GMX AG by USt; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Google)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Googlebot)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; GPM - MSIE 6.0 SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Gulfstream Aerospace)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; 3M/MSIE 6.0;; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; 824145)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; 824145; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; 824145; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; 828750; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; 828750; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; ANZ Banking Group)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; AT&T CSM7.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; BASA Standard)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; BB55; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; BCIE6SP1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; brip1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Client Engineering 20010828; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; FunWebProducts-MyWay; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; HEWLETT-PACKARD -- IE 5.5 SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Hewlett-Packard; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Hotbar 4.3.1.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Inovant)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Inovant; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; iOpus-I-M; YComp 5.0.8.6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Q316059)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; Roadrunner; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; RVQhNDHN5fHE9Vytg36u/rdyxKj6LSKTLgkNEyABZ==)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; SILSOE; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; T312461; Hewlett-Packard; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; T312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; UB1.4_IE6.0_SP1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; UB1.4_IE6.0_SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; UB1.4_IE6.0_SP1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; H010818; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; HCJME)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Heath Park High School; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Het Net 3.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Het Net 4.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hewlett-Packard)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hewlett-Packard IE5.5-SP2; Hotbar 4.1.8.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hewlett-Packard IE5.5-SP2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hewlett-Packard; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; HMEUK)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; HO32600; HO32501; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; HomePage)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 3.0; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.1.7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.1.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.1.8.0; Hewlett-Packard IE5.5-SP2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.1.8.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.1.8.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.1.8.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.2.14.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.2.4.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.2.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.3.2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.3.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.6.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.4.6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.5.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar4.5.3.0; MyIE2; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hot Lingo 2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hot Lingo 2.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; HTMLAB; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; http://InternetSupervision.com/UrlMonitor)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; http://www.pregnancycrawler.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; HWT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IBP; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IBP; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ICT 20021217; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; &id;)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IDG.pl)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IE5.5_ SP2_wOLE; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ie6dist)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IE6IEAK; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IE6/SEF; IE6/FO)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IE6 SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IE6SP1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IE6SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iebar; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iebar; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iebar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iebar; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IE_EFY)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IESFYINTL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IESFYINTL; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IESYM6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IESYM6; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IESYM6; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IE UACh; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Illinois State University; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Illinois State University; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-MailBook; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-NavFourF; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-NavFourF; FeedEater; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-NavFourF; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-NavFourF; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; i-NavFourF; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoCommons)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; infor INTRANET; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Installed by Symantec Package)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Installed by Symantec Package; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Internet Cafe 324)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Internet Cafe 324; ICafe 324)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; internetsupervision.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; INTRANETUSER)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; INTRANETUSER; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; Alexa Toolbar; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; PRU_IE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iOpus-I-M; (R1 1.5); .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; iPrimus)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Issued by ACC Web Services; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; istb 644; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; istb 702)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; istb 702; AskBar 3.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; istb 702; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ISU; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; IWSS:PC-8684-ayrale; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; KC135ATS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; kiev.xvand.net; i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322; hunter)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; kinglothar; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; KITV4.7 Wanadoo)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; KITV4.7 Wanadoo; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; KKman2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; KKman3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; KKman3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Kvaerner ASA; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; L1 IE5.5 301100; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ; labs.giannone.unisannio.it; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LCAP-CB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LCPL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LDE0308a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LDE0308a),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; @lee-road.co.uk)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LendingTree.com; AIRF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LLY-EMA-EN)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LM-MS; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LM-MS; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LN)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Lockheed Martin TSS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Logica 5.5 SP2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Logica 5.5 SP2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Loyal 4arcade.com User II)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LU)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; LWC-dev)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maersk Data AS, Denmark; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Magistrat Wien)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Magistrat Wien; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Manufacturing and Customization)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Marineamt Rostock; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MathPlayer 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MathPlayer 2.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MathPlayer 2.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MathPlayer 2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MathPlayer 2.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MathPlayer 2.0; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; Alexa Toolbar)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; MyIE2)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; MyIE2; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Maxthon; (R1 1.3))" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Mazillo)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MBsdk0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MenloIE; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MISCS 1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MMS Standard)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Monash University (Customised IE 5.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Mozilla/4.0 (compatiable; MSIE 6.0; Windows NT; Anexsys LLC))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Mozilla/4.0 (compatible; MSIE 5.0; Debian GNU/Linux; Windows NT); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Mozilla/4.0 (compatible; MSIE 5.0; Win9x/NT; JUNO))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; HDR.05.01.00.06; .NET CLR 1.0.3705; .NET CLR 1.1.4322); .NET CLR 1.1.4322))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MRA 2.5 (build 00387))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MRA 4.0 (build 00768))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; msie 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSN 6.1; MSNbMSFT; MSNmen-ca; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSN 6.1; MSNbMSFT; MSNmen-ca; MSNc0z)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSN 6.1; MSNbMSFT; MSNmen-ca; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSOCD; AtHome020; Vj2qqm9YVSwdmA06; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSOCD; AtHome021SI; YPC 3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSOCD; AtHomeEN191)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSOCD; Hewlett-Packard)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MSP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MTK; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; Alexa Toolbar)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; FunWebProducts)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; FunWebProducts; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; FunWebProducts; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; iebar; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; i-NavFourF)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; i-NavFourF; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; Maxthon)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; MRA 4.0 (build 00768); .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; NRTE; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; Poco 0.31)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; Poco 0.31; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; (R1 1.3))" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; (R1 1.5))" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; (R1 1.5); .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; MyIE2; Websearch4u 2; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NAB PC IE6SP1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NetCaptor 6.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NetCaptor 7.0.2 Final)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NetCaptor 7.0 Beta 2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NetCaptor 7.5.0 Gold)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NetCaptor 7.5.0 Gold; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NetCaptor 7.5.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NetCaptor 7.5.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NetCaptor 7.5.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; Feat Ext 19)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 2.0.40426)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322;)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; Alexa Toolbar; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; Free Download Manager)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.40301)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.40607; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.40903)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322) NS8/0.9.6" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322) via Avirt Gateway Server v4.2" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322) WebWasher 3.3" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322) (www.proxomitron.de)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 2.0.40607; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 2.0.40607; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 2.0.40903)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Net M@nager V4.00 - www.vinn.com.au)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Nevada DOT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NIX)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NN5.0.4.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; N_O_K_I_A)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; N_O_K_I_A; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; N_O_K_I_A; TheFreeDictionary.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Nomad)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Nordstrom; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Nordstrom; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NoSpiesHere)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Novo Nordisk Engineering A/S)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NSWFB SOEWKS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NSW.net)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ntlworld v2.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NTSSVCCORP04022001-ELSAUG2001; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; NZCity 6.0; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ODP links test; http://tuezilla.de/test-odp-links-agent.html)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Office of State Courts Administrator)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; OptusIE55-27; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; OptusIE55-31)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; OptusIE55-31; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; OptusNetCable-02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; OptusNetCable-02; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; OptusNetDSL6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; OptusNetDSL6; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Orange Development Dinges)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PAS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCM_06a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCM_06a; Hotbar 4.4.1.1381; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCM_06a; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCnet Version January 2002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCQuest)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PC SRP 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCUser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCUser; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PCUser; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PHS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PhysEd)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PIB99A)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Pierce County WA v1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Planet Internet PIM 2; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PN)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PNCStd; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PneuDraulics Inc - Rancho Cucamonga - CA; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PowerGeekz Rulez; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PPI 05022002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Private information. DO NOT SHARE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Progressive Insurance; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Progressive Insurance; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Provided by Alphalink (Australia) Pty Ltd)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; provided by CRC North Keilor)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PRU_IE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PsyStudentDesktop)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PVH; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; PwCIE6v01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q123456)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; ADP Micro 6.0 SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Amgen.v1b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Amgen.v1b; YPC 3.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Amgen-v1c)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; APCMAG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; AT&T CSM 6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; compaq; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; ESB{586E8C53-5BFC-491B-928B-AA1E0EDEC154})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; ESB{E6216221-1B63-48B0-B352-CF03FD47282F}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Feedreader)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; FunWebProducts-MyWay; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; HD 6.1 Custom; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Hotbar 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Hotbar 4.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; i-NavFourF; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; ir.ie6.v1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Marshfield Clinic)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Mind Your Own Damn Business!!!!!!)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; MSIE 5; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; MTK; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; MyIE2; i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; MyIE2; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.0.2728; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322; ByteMe_6969)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; ONDOWN3.2; Cox High Speed Internet Customer; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; OptusIE55-31; OptusIE501-018)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; QXW0339r; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; sbcydsl 3.12; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; SEARCHALOT.COM IE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; SWFPAC NSB IE6sp1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; Walsrode Online http://www.walsrode-net.de)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; YComp 5.0.0.0; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; YComp 5.0.0.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; YComp 5.0.2.6; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; YComp 5.0.2.6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461; YPC 3.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q321064)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q321120)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q342532)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QPC MegaBrowser 1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QPC MegaBrowser 1.0; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QS 4.1.1.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QS 4.1.2.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QS 4.1.2.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW0333r; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW03399; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW0339a; MyIE2; Maxthon; i-NavFourF; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW0339d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW0339d; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW0339h)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW03411; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW03413)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW03416)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW03416; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; QXW03417; Gruss von BURGSMUE; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.1); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.1); (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3); Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3); .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3); .NET CLR 1.1.4322; SiteKiosk 5.5 Build 45; ALAMOANA2; SiteCoach 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3); (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.3); (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.5); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.5); .NET CLR 1.1.4322; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; RA_APAU)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; RayDen)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; RBC; 9LA; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; RC75 Release)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; RC75 Release; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Reuters Global Desktop)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; RHIE6SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; RIS GmbH - 1.1 - A)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Roadrunner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Roadrunner; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Rogers Hi-Speed Internet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Rogers Hi-Speed Internet; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) RPT-HTTPClient/0.3-3" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SAA; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SailBrowser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SALT 1.0.4223.1 0111 Developer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SALT 1.0.4223.4223 0111; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SALT 1.0.4613.0 0111 Developer; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SALT 1.0.4613.0 0111 Developer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SALT 1.0.4613.0 0111 Developer; Search Box Toolbar 1.0b2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SBC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SBC; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SBC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.11; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; FunWebProducts; yie6_SBCDSL; yplus 3.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YComp 5.0.0.0; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YComp 5.0.0.0; UB1.4_IE6.0_SP1; iebar; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YComp 5.0.0.0; yie6_SBCDSL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YPC 3.0.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YPC 3.0.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sbcydsl 3.12; YPC 3.0.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SBC; YPC 3.0.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SCB; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SDS IE6 SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SDS IE6 SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SDS IE6 SP1; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SEARCHALOT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SEARCHALOT 102303)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SEARCHALOT.COM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SEARCHALOT.COM IE5; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SEARCHALOT.COM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Siemens Testmanager; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SIK1.02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SIK30)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SIK30; FunWebProducts; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SIK30; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SiteKiosk 5.5 Build 45; SiteCoach 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SKM v1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SlimBrowser [flashpeak.com]; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SLM; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Smart Explorer 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Smart Explorer v6.0 ( Evaluation Period ); Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SMSHome (http://www.aggsoft.com); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; snft internet; SEARCHALOT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; S.N.O.W.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; S.N.O.W.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; snprtz|dialno; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SOEBUILD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SPEED; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SQSW)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SRA-60-05032003; RC-60-040226)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StarBand Version 1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StarBand Version 4.0.0.2; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Steria102002; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Steria Browser - MKG; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; STIE55-010209; STIE5-000710; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; STJUDE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; student.vuw.ac.nz)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StumbleUpon.com 1.733; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StumbleUpon.com 1.733; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StumbleUpon.com 1.736; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StumbleUpon.com 1.737; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StumbleUpon.com 1.755)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StumbleUpon.com 1.760)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StumbleUpon.com 1.917)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; StumbleUpon.com 1.917; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; stumbleupon.com 1.924)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Supplied by blueyonder)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Supplied by Tesco.net; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; sureseeker.com; iebar; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; surfEU DE M2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SURFkit V5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SWSIT; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SYMPA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SYMPA; ESB{F8AB14A0-3270-47A7-9717-22047C6C04E7}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SYMPA; FunWebProducts; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SYMPA; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SYMPA; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; SYMPA; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Systems Management Server (4-28-03))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; t20010828; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; AIRF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; BTOW V9.5; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461;DI60SP1001; {1D9923A3-DFFD-4703-95E9-DB38D1421256}; DI60SP1001; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461;DI60SP1001; {1D9923A3-DFFD-4703-95E9-DB38D1421256}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Digipub,Grape; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; DonRocks; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; DSCC/DLA; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; EK60SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Emf!sysUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; F-6.0SP1-20030218)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; FunWebProducts; Hotbar 4.4.5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; FunWebProducts-MyWay; drebaIE-ZE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; FunWebProducts-MyWay; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; FunWebProducts-MyWay; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; General Mills, Inc -6SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; General Mills, Inc -6SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Hewlett-Packard IE5.5-SP2; YComp 5.0.0.0; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Hotbar 4.2.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; iebar; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; IE_DT2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; image_azv)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Infowalker v1.01; Feedreader; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; iOpus-I-M; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; istb 641; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; istb 702)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; MRA 4.0 (build 00768); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; MyIE2; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; .NET CLR 1.0.3705; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; .NET CLR 1.0.3705; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; PC SRP 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; PC SRP 2.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; PC SRP 2.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; PC SRP 2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; PGE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; PGE; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; POIE4SP1; POIE4SP2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; POIE4SP2; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; PPG; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Q312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Q312461; (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; (R1 1.5); .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; sbcydsl 3.12; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; SBS V1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; SBS V1.1; SBS V1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; SLM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; TeomaBar 2.01; .NET CLR 1.1.4322; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; TTUHSC; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; Tyco Electronics 01/2003)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; YComp 5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461; YComp 5.0.2.6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Taunton School; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TBP_7.0_GS; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TBP_7.0_GS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TBP_7.0_GS; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TDSNET73INS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Teacher; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TELEFONICA DE ARGENTINA; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Telia; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TencentTraveler )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TencentTraveler ; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TencentTraveler ; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TencentTraveler ; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TeomaBar 2.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TeomaBar 2.01; formsPlayer 1.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TESIEAK6a; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Texas Instruments)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TheFreeDictionary.com; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; The Scots College)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TIDK)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TIETOS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T-Online Internatinal AG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TOYOTA CANADA INC.; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; T-SYSTEMS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TUCOWS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Tucows; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TUCOWS; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TUCOWS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TUCOWS; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TUCOWS; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; TYCHO)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Tyco Electronics 01/2003)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Tyco Electronics 01/2003; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UB1.2_IE6.0_SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UB1.4_IE6.0_SP1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UB1.4_IE6.0_SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UB1.4_IE6.0_SP1; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; University of Leicester; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; University of Limerick, Ireland; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; University of Limerick, Ireland; T312461; .NET CLR 1.1.4322) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Updated-1-22-2004)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UPS-Corporate)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UPS-Corporate; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UQconnect)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UQL Public Workstation; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UrlMonitor)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; urSQL; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; user@ch.eu.csc.com; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; %username%)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; utvi160403)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; UWE Bristol; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; VB_ITS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; VBN; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; VDOT IE6 sp1 - Landesk Package 8-2003; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Verizon Wireless 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Verizon Wireless 2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; VEU)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Virgilio6pc)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Vodafone España)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Vodafone España; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Vodafone; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Volkswagen of America; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; VSAT500)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; V-TV Browser7.0.0.0 (Build 700))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; VZ_IE6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; W2K/KW; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Wanadoo 6.1),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Wanadoo 6.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) WebWasher 3.3" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; wg16)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; WHCC/0.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; WHCC/0.6; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; WHCC/0.6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; WODC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; WRV)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.acction.com.au)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.amorosi4u.de.vu)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.amorosi4u.de.vu) (www.proxomitron.de)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.ASPSimply.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.ASPSimply.com; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.ASPSimply.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.bfsel.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.k2pdf.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.k2pdf.com; .NET CLR 2.0.40607; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; www.VanessaAmorosi.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; WYETH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Wysigot 5.22; Iconico-WebTools-Pro-v1-0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.0.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.0.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.0.0; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.0.0; SBC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.4; Hotbar 4.4.2.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.4; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.4; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.4; Supplied by Tesco.net)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.5; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.5; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.6; Hotbar 4.4.2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YComp 5.0.2.6; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBCDSL; sbcydsl 3.12)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBCDSL; sbcydsl 3.12; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBCDSL; sbcydsl 3.12; YPC 3.0.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBCDSL; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBC; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBC; YPC 3.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBC; YPC 3.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBC; YPC 3.0.1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; yie6_SBC; YPC 3.0.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.0; yplus 4.0.00d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.1; IBP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.1; yie6_SBC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.3; sbcydsl 3.12; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; YPC 3.0.3; sbcydsl 3.12; FunWebProducts; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ZDNetIndia; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; ZI Imaging Corporation; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {00E372B7-BEAF-4DE2-8656-D9E207B7A868}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {00FC4ECE-55C0-4CC0-B927-A257C53EEA9B}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {010372B4-6664-4F0F-9F72-69CDEAAEF34C}; SV1; sensis; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {01CCA09B-D5C0-494F-9AB2-C6A542FB3229}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {02E74E79-2624-4118-ACC0-B2B5E3303175}; SV1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {04C71239-93BC-463E-8049-E98C6347C7B6}; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {05292C4C-2C29-4A29-A4A3-07773831343F}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {059455F9-7AF0-4213-B2BF-552E61CC057A}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {0840790C-3719-4A4D-95C6-1C8D668C09FB}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {096DD935-8F09-400D-862E-BAB1224F8D8B}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {0A4A867A-C305-4125-BDE0-9596EAE3F231}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {0A6E773D-A7D9-4536-BA0E-85BC13B3537F}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {0A9BDEB0-929E-4F14-B6C5-EEF41B896043})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {0AB53206-6DD9-450D-B4AA-685C7E5148B6}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {0AB63054-8A7C-42DB-BFD8-DCBDA1D57B67}; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {0DC2355B-02C9-42D8-9358-7CC385381704})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {0F233567-886D-460E-BCD2-88171D6F8C04}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {10D39F67-2519-4768-A71A-9F7915E2CABE}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {11C208DD-B1E1-49F3-A67C-2E8F81A0450E}; SV1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 1&1 Internet AG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 1.21.2 ; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {1272B23E-8FD1-4BBE-A149-41B4E94621EA})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 1.41.1 ; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {150A8501-CEA4-4B5F-A7C9-55616EDF8F6C}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {154813CD-3783-458E-B7E0-3294360CA69E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 1.56.1 )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 1.57.1 )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {1639F6BF-2F23-4A84-AB07-B2FC5A94935A}; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {1681F45C-A0AD-4298-922C-5469DF1CB2EB}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {16A0E5E0-30C1-4ACA-AB32-0719A8E952AA})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {17156865-D8E3-4E6C-B430-78B89BA7C978}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {177ECE14-992D-4AA3-894B-5071AFBC00D5}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {18154988-E91C-4941-B5B6-4FD487BC0525}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {18C2BD69-EEEF-4151-BBA4-23B98B4B6B03}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {1903CC58-2135-4245-A3C4-C539A1B2F880}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {1907B553-57F7-4A6E-870A-C4744E1B6316}; iebar; CustomExchangeBrowser; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {1A29EBB4-B546-4452-A5BE-BECD78E4775F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 1C)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {1DD69613-6D5A-4E27-862B-7CD98B580F7A}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {1E96F9A7-2DD2-4386-8EB8-7D4B33840A98}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 1ngo!)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 20040404; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {2085FE1A-3A52-4263-9403-CB8938637154}; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {22311735-7766-4562-8318-CFBA42C160AD}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {22827DFF-8DEE-4B06-A2D8-42D90E0D53CA})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {23320F0D-2CA6-4BB2-B889-E23EDE240004}; AskBar 3.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {23521C6A-ECC2-4461-B2D4-9D9C390B90F0})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {24886906-C12D-4D24-8A85-046283E20B25}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {26335003-5381-431D-85FC-5FBAE901B682}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {28267C2F-1F37-4133-A363-3AE7FE96A5ED}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {284FBE28-A81E-404D-AF29-EDD0384E1E1F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 2919; 21231; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {2C003D7B-598B-0DEA-1120-FD31003AE559})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {2C283092-4E93-4C58-ABE1-07EC5031F0D5}; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {2D23B066-4320-4A33-97E2-37D1E986227E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {2D25856C-B035-4C44-A548-A4A90CFF8355}; ESB{0F85F697-7BE6-4024-9936-09124BD6C11D}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {2EC67C21-DA69-496A-A8A2-C518BF746B76}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {2F11EBA2-D79D-47CE-8038-E25C5C60CA50})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {2FD51919-0611-4405-A0C0-2B0757909879}; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 2XP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3043E601-196A-4FD7-89B3-30B82C26D3D1}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {32097A18-1D85-423C-913C-A7BFACBE9070}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3277AD62-7541-4E08-85FC-9058C62AFB67}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {328DDFC1-1867-4044-B118-01E6C8878FA6})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 3301)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 3304)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 3305)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 3305; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3328C095-323C-45D5-8C47-94D927422276})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {341A244C-4429-403A-953F-332E6B717C94}; FunWebProducts; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3463A193-AB0F-48A2-A40F-314E277D4FA8}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {35466D8B-0733-4318-9C15-90D01F7D18B4}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {35A6C8BC-4D10-464E-9059-0786612B0949}; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {35DE4964-76A5-4C61-A6C1-12ADF40CF932})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {360D7714-1669-40B4-8A79-8DC66280E427}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {364EDA13-8707-497D-8D19-043EC47F06E9}; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {366089E4-4B15-4161-81BD-0BE380E6C054}; urSQL; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {387DAA29-45E7-4360-9D07-3C17CEF67768}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3A536119-BE87-47FE-A2CA-00EC28725F68}; SV1; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3A584A4D-518C-4D0E-BC6B-541B7D69A3FE})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3CB6D22A-827A-4D5B-95D1-C25042B282C6}; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3D309697-A650-4F70-9E8B-3E5BBD8136D4}; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3F766A6E-FF5A-419A-8E0D-B410CC976848}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {3FD99CE8-4876-42EB-A98E-C3240840E16F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 3M/MSIE 5.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 3M/MSIE 5.5; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {40BEA18B-3AD4-4A88-87CB-9F3E34B672C5})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {41D06DE4-3B47-4AFE-8586-A2A0BC21128B}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {42662884-5207-488E-88DD-22D1EE5876E4})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {438A4A73-BC8A-4815-81F7-E684646FE3BB}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {4489F513-F2F4-428D-862D-E328E98846C1})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {474A61B2-06FD-4AC4-BD58-15A5EE8D135A}; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {48B30A43-F85C-421C-B89F-5D8DCE6F0C33})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {48BC54DC-03AC-43C8-98C3-6C74FAFA4CBF})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {4907EF1F-C744-4C7A-BD93-DB6598A4124F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {4910F99D-049A-4B1E-AA4C-6254837DE90E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {497D41FB-CBB2-4214-A8FA-2C8339E15215}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {4D0F642B-7758-4DD7-806D-22F5C327491B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {4DAD8D3C-DBF0-48FF-81D9-D8B6056B250A}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {4F0AA017-AB3E-4B63-94AC-3554E6E79E2B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {505431EF-B36F-4113-AD87-A9F319C9A9A7})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {505F1043-8A30-492E-A1F4-6D76A19DAFDC}; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {51B5AE33-C14D-49E0-B977-C367563556E8})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {52370F31-7911-CA01-5788-3A30A77F2822})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {53810FCF-D003-454B-BE56-53B2FCF44FD9}; www.kpas.net; IBP; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {55173041-4495-432A-B14A-DC8C4904669C}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {55173041-4495-432A-B14A-DC8C4904669C}; .NET CLR 1.0.3705; .NET CLR 1.1.4322; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {5677AA33-67A1-4270-B68D-B5D5A4E95FA0}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {56B378DE-DAA6-4681-9973-9BEF2D4DDC6F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {56CD5059-BD0C-4315-9677-6D1C92EAF5A8}; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {56FA8E7E-12AB-4911-A191-21C37C311D65}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {581A1CD1-357D-4B8D-8953-C522246CC007}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {581CB45E-7FDC-4B9A-B71C-28266E860749})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {59632201-F778-4CBA-B1F4-C4CCD491D964}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {5B643202-DEAC-4D35-BC57-FE4279576E94})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {5C2F722D-C130-4AD3-8A07-5D3C659A6926}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {5C405188-4130-4F5D-801B-92844913257D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {5CD38EE8-DD84-47A1-9FD8-61C91D812942}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {5D6BCA52-DC20-46F7-B828-2B34BB4618F9}; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {5DF11A3C-26FC-451E-9C44-151B22E63F64}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 601-24)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6240A551-23EB-402C-8A79-008063B05AC2}; Alexa Toolbar; Feat Ext 18)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {625B82F8-3C54-4C68-B502-9EDAD5E5A2B0}; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {654B0711-4A85-42E7-983F-7C17305D0E48}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {66830790-BB7A-4162-B58C-8A914A9DFF5C}; SV1; 1.57.1 ; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {671249BD-E4C8-4962-8F4C-B5116D567611}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {67198D79-41B9-4775-88C5-FF11BF28DF6E}; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {676CA98F-335D-4002-AE68-06EC0FCD863E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {68070A19-8A16-4631-9EC8-4A06D22F83A6}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6A5F8282-BD7B-4C03-AA47-D5EA5EE6CC2C})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6A7ABDFC-3C88-42D6-8E5C-464935051D13})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6B03FCEC-E168-4CD2-946B-4E7C3171D66C})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6BC3FAAA-4F70-42A4-A3D9-5D6E7D38B6E6}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6BD7D868-97D7-4021-A0D1-AFAFDE7AED4A}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6BE32F1D-C93D-4A7A-AB49-C6C28663C805}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6C4A00C9-0682-4A2B-A5C5-7C066461D41A})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6C54EE4C-5F00-4EEB-AABA-A35C734E2654})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6D2550C2-E7EC-4A02-84F9-AE5DA7671170}; SV1; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6D733935-1BA5-402C-81CD-EFFD0A66928B}; SV1; OptusNetDSL6; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {6FC0CBD9-8501-A7A3-BC23-9E828B1739DD})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7029D658-033C-4F21-9334-3028D54A9C46}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {70A105A4-3B56-40B8-ACB3-0B9567712A0C}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7166AA8D-9F2D-45AF-BC84-3A13C84AB68C}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {716A884C-2833-41B9-B4A2-7CFF5CC19774}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {725986B4-361D-4262-888A-1DEF1D40A677}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7275A900-6883-4F2C-9D7B-9D7E6F1B1CAD}; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {73031379-6EF6-48A2-8182-5E04CA2B100D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {73CA2DB1-3D3A-4AA3-BE60-1AB52BBA5DC7})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {73FC897C-EB65-481A-9DFE-D5E6BA3549EF}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {746BDD15-B60E-45F9-8D9B-0DDBC59E6A16}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7564D434-679A-406F-BB78-7277EA46547A}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7609500E-F1F7-4395-AD02-DA8F288385DB}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {76558216-F653-405A-BD95-00857C519BFB})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {76CBD2B2-30E1-4D85-BD1B-D854AEB6FC5B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {76D1A158-5E58-4876-B3B5-09A18AF2D3AB}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {773D9899-3378-495E-AC5D-D9489250EB13})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {776316A7-FEC1-44A8-9DB5-8469FF21105D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {77820B37-7295-47CD-8842-0AA10651F383}; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {79D3BB58-8001-4C11-BB86-ADE061CEAF25})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7A834B30-AA9D-4D2B-AC38-919CE48D56E2})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7AAD7328-EFD7-4E69-8B69-7E9E6D5F4B2F}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7DABAE32-5850-47DE-A886-7BF64850D96D}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7DCFFE58-FF03-4A2A-B3E6-8149BB0EF19F}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7F82049C-378B-4A5A-98D6-E1D43E43CFA0})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {7FB10817-27B8-4D7C-86DD-C61DFD37585B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {80351674-652B-4DDA-8432-41F8E61AB1E7})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {82EFCD46-30E8-45E3-99B6-AD90BEBDAD6B}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {835E8FC0-7916-4D1F-AA80-DD7F553053C6}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {8421A6E1-44C8-4B7D-A950-5EDE1F3181F0}; SV1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {85192DB1-086A-4E53-A59F-BDB83377709A}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {858921CC-D456-4230-95D4-B968432409B3})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {8590B1C5-F4E9-41B0-A990-A8C325015392}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {8621CC8A-4F10-45B1-9C16-A289C29FB98E}; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {865C266F-BCAE-421B-BF88-F1B120A4F943}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {88516849-FDAF-4A0A-956F-FA2CF2F6D7F9}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {888CC72D-0C51-4514-9AA7-507E9D2D6A9E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {89E40FF4-BD77-4586-B092-EB6957FFEEC0}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {8F1D0313-7282-4B1C-B38B-E33B59B2B5B8}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {8F8DADE0-9F1C-406B-8D45-A3686358668D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {906090F7-10E4-4B25-B2D9-D258E722AFC4}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {913B3453-254F-4FC2-AB37-B3CB009590D0}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9520EB69-95A9-4B9E-B576-F9453174C6F8}; ESB{C8AD18A8-BC88-40E8-97D9-31784C41F582}; ESB{50D170B2-6884-4234-96B4-22273E912859})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {965166C4-481A-4D30-8597-0A4319911257}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 97828)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {97D5F745-44A2-4093-B7E1-E8235862D1CA}; SV1; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {996DA28F-748C-4439-ABC3-4546531ED0FC})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9AA7FFB2-7E7D-4B92-86AE-835F7B135CB9}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9AFC0F21-2679-4207-98D7-E2DB9CDC0E89})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9B8F54EC-CC98-489C-9050-D61EF01E6D45})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9C3408B0-029E-479E-93AD-AA8492C083CE})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9CD98633-D53A-4916-B25D-BBF0EC6299A5}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9CD98633-D53A-4916-B25D-BBF0EC6299A5}; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9CE63974-BFE2-4797-BEB8-B8C133A401B9}; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9E70E38E-EEFE-48E4-9B4C-BF0FEE5E94CD}; .NET CLR 1.0.3705; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {9FE37218-F0B4-43AA-8528-2B052E647F3C}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A159BA28-48C0-4189-BEE6-D59494BCDD76})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A27C75DF-D29F-4B21-834D-66C1B23297E5})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A2841CE9-E06C-4BB2-AF6B-14C4EAA0F0CF}; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A333877C-5AE7-4532-969B-A6004713EF80}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A4E5458B-4CE1-4552-9D0E-8C01D102C7FA}; FunWebProducts; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A5891798-8194-4EC2-BB31-8C33151147C0}; ESB{9E677553-0D9B-4A40-B6E7-8AD691A3065F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A61CE854-3B32-4B71-B3BD-60DCE467E30E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A88CFFCD-C389-47D6-8AEC-52C1DB0371C4})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A97D2399-C6DD-47F7-A9E3-4C2842744510}; SV1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {A9D3BF59-505F-4316-AA7F-ABC49BF4B03E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AAPT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AAPT; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AAPT; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {ABC49948-9942-404D-B4FE-574FCA90475D}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ACSWorld; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; actually Firefox - assholes, support Mozilla/5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ADP Plaza - Build 64; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {AE17F330-EBBA-4B78-B5DF-3288211BACB4})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {AE480139-C1AA-4168-9BA2-24E090FBB8C7}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WILDdesigns; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AIRF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AIRF; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AIRF; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AIRF; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AIRF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AIRF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AIRF; Q312461; SV1; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AIRF; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AKH Wien; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Al Asad/Hunter Site, LSA Anaconda; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Alexa Toolbar; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Alexa Toolbar; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Alexa Toolbar; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Alisys_ONO; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ALPHA/06)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ALPHA; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; anna mielec tani seks dziwka; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ANONYMOUS; Huntingtower [INTRANET ONLY]; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AOL7; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APCMAG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APCMAG; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APCMAG; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APCMAG; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APCMAG; OptusIE501-018; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APCMAG; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APCMAG; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APC; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; APU-XP; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Arcor 2.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Arcor 2.0; SV1; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Arcor Online 3.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 2.11; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 3.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 3.00; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 3.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 3.00; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 3.00; .NET CLR 1.1.4322; Fluffi Bot+)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 3.00; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 3.00; SV1; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskBar 3.00; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskJPBar 3.00; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AskJPBar 3.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AtHome021SI; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AtHome021SI; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AtHome033)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AtHome033; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AtHome033; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AtHome033; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AtHome033; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AtHomeEN191)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ATOM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; AT&T CSM 6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; AT&T CSM 6.0; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; AT&T CSM 6.0; YComp 5.0.2.6; FunWebProducts; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; AT&T CSM 6; SV1; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; AT&T CSM 6; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; AT&T CSM8.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc11; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; Q312461; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; Q312461; SV1; .NET CLR 1.1.4322; MSN 9.0; MSNbQ001; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; Roadrunner; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM6.0; YComp 5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM 6; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM 6; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; Feedreader; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; FunWebProducts; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; MyIE2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; .NET CLR 1.1.4322; Feat Ext 13)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM7.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM8.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T CSM8.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T WNS5.2; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; AT&T WNS5.2; Q312461; AT&T CSM6.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; austarnet_2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; Alexa Toolbar)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; FunWebProducts-MyWay)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; MyIE2; Feedreader; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; MyIE2; SV1; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; .NET CLR 1.1.4322)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; SV1)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Avant Browser [avantbrowser.com]; SV1; .NET CLR 1.0.3705)" + family: "Avant" + major: '1' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Awe¤6 - Adonay Web Explorer; Mozilla/4.0 (compatible; Awe¤6 - Adonay Web Explorer); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {B0832C32-9DEE-429D-9138-56DD764E4C9E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {B2570479-25DA-7559-C478-C0A0855A6BD5}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {B3215A47-A5E1-4B6A-9BB4-3DF0A424B6A1}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {B473E576-6FFF-4F71-9FE5-29224CE32692})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {B8106019-1D23-4C8E-808C-AE28616B449A}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {B9554770-CEA1-4514-BC49-A30D9169404D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {B98C23CE-0A06-492A-A248-BF4336DE4EDD})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BB B500 U2.02; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {BBD40907-B7C9-4947-9B8F-A62A288A98F9}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BB-INTRA-MAI2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BBT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000; MathPlayer 2.0; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000; Q312461; SV1; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000; SV1; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000; SV1; iebar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCD2000; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BCIE6SP1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {BD0F71D8-0AC0-49F7-BD87-81F5C24E60E3})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {BF2D4BA4-80A1-46E5-AC3F-B62AED59596C}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {BF8B323E-06A3-459F-BAB5-ABE8401D417A}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; bgft)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BIGPOND_ADSL_42; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BIGPOND_ADSL_42; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BizLink; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; bmi ecommerce; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; bpc; SV1; (R1 1.3); (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BP E1.06; SV1; Smart Explorer 6.1; 1.41.1 ; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BPH32_56; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BRA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Brew_Browser_6.0_SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; brip1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; brip1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; brip1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; brip1; SV1; Sidewinder 1.0; formsPlayer 2.0; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .: BritishHeaven.de :.; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT [build 60A]; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Business Broadband; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTinternet V8.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTinternet V8.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTinternet V8.4; YComp 5.0.2.6; MSN 6.1; MSNbMSFT; MSNmen-gb; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTinternet V8.4; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTopenworld; AIRF; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTopenworld; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld BB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld BB; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld BB; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld BB; SV1; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld BB; YPC 3.0.0; yplus 4.3.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld BB; YPC 3.0.2; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld Broadband)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld Broadband; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld Broadband; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BT Openworld Broadband; YPC 3.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTopenworld; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTopenworld; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTopenworld; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTopenworld; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTopenworld; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTOW)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTOW; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTOW V9.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTOW V9.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BTT V3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; BWCH30; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {C122D12A-1212-49C3-89B0-CD9F3ED9F7BD}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {C1B43645-698E-4524-9042-76FC08FDE51A})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {C2EED8D4-0E69-4BC2-8F34-3B246690F6DE}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {C389C776-89D8-4251-A003-AC55DE5E6821}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {C429A6DA-4192-4DD9-85EA-B5EC7CB4DA25}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {C5D1D9A9-F1A0-4C62-8162-8BA0DD8C3BA4})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {C67ED323-27F6-4127-B7F2-56691D7AC32F})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {C713E123-6F1C-41FC-84B3-880D9608E8D7}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {Cablevision Optimum Online}; (R1 1.3); Feat Ext 19)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CASPERXP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CASPERXP; MyIE2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CASPERXP; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {CD23D801-AD49-4451-BCEE-0E1BBFC3E71A})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=ALLIED_01_01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=ALLIED_01_01; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=ALLIED_01_01; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=ALLIED_01_01; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=BP1b.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=BP1b.00; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=BP1b.00; SV1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=storecd_01_03; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v11c.01; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v12a.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v13b.06; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDsource=v2.15e.03)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v3.12a.00; SV1; YPC 3.0.2; yplus 4.3.02b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v9e.01; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v9e.03; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v9e.05)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v9e.05; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v9e.05; NN5.0.2.12; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v9e.05; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=v9e.07)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CDSource=vBB1c.00; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {CE4189CF-B7E9-4F85-B301-6CC3C11A0196}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {CEDA55FF-C15E-4879-88A3-A83B90CAFEC5}; MCI Windows Corporate Image; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; :certegy Corporate; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Charlestown; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Charter B1; FunWebProducts; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Charter B1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Charter B1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CHWIE_NL70; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CHWIE_NO60; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CHWIE_NO70; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CHWIE_SE70; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CITGO09302002; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Cng)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CNnet Internet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; COE June 03, 2002; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; COE June 03, 2002; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; College of Business Administration Lab; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; COM+ 1.0.2204)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; compaq; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; compaq; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; compaq; YPC 3.0.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Compatible; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; @; Compatible; Version; Platform)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Compatible; Version; Platform)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Connect 1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Consorzio Operativo Gruppo MPS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; consumer; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Corporate Image; MCI Windows Corporate Image; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Cox High Speed Internet Customer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Cox High Speed Internet Customer; Hotbar 4.2.8.0; Hotbar 4.3.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Cox High Speed Internet Customer; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Cox High Speed Internet Customer; Q312461; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Cox High Speed Internet Customer; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CP; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CP; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CPT-IE401SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CPT-IE401SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CPT-IE401SP1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CPWR)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CPWR; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative; ESB{AE9445A2-0ED0-4AC0-BDE4-3EA933008624}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative; Hotbar 4.4.5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative; Q342532)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Creative; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Crick Enhanced; Q312461; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {CSC})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {CSC}; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CSIE60SP01; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CS.v0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CursorZone 1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CustomExchangeBrowser; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Customized by Computer West; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CVnet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; CWCRDAY; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {D009E04F-7285-4277-BAF6-77797A8417CF})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {D03E5946-02C5-4FFB-BDF7-A2D658A27777})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {D15E0797-FD3B-413C-B67B-63D937268BE0}; Feat Ext 21)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {D1F76FF8-EE02-4E7F-BB77-5D6682CC4F46}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {D2C0EFBA-26D7-48B4-8500-1F2483B6044C}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {D379CF0A-4B77-463F-B99C-6E854BEACF65}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {D546DB1D-E98F-468A-8876-49573C986A27}; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {D72714F6-A809-4DE6-B422-2B2ADCEBF152}; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DAgroupPLC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DATASIEL; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {DB056177-05D3-45EF-A868-F029A67735C0}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {DBF8B407-FE31-4D86-8C6E-2F831D79AB5B}; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {DC6A17BE-3A95-4B92-8292-A8EE80FB04CB})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {DCAEF9CE-8251-422E-ADD0-AD2B56DEFED3})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dcdev001; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DCSI; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {DD7B8EB4-6D8A-46BB-B262-45CEC0C799E8})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DDnDD; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.3.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer 1.3.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Deepnet Explorer; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DesignLinks; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {DFD18BB5-E42B-42DE-9F12-A936648D0AF1})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DFO-MPO Internet Explorer 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DGD (AutoProxy4); .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; -D-H1-MS318089; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; -D-H1-MS318089; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DI60SP1001; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dial)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Dialer/1.10/ADSL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Dialer/1.10/ADSL; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Dialer/2.08/Frisurf; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dial; NetCaptor 7.0 Beta 2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dial; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dial; SV1; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dial; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dial; SV1; www.ASPSimply.com; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; AAPT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; Assistant 1.0.2.4; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; digit_may2002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; FunWebProducts; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; KITV4.7 Wanadoo)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; MSN 6.1; MSNbMSFT; MSNmen-gb; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; NN4.2.0.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; OptusNetCable-02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; OptusNetDSL6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; Q312461; iOpus-I-M; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; Q312461; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; Rogers Hi-Speed Internet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; SV1; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; VNIE60; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; VNIE MESH_PC; YPC 3.0.2; yplus 4.4.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DigExt; YPC 3.0.2; yplus 4.3.02b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; digit_may2002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; digit_may2002; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; digit_may2002; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Distance Learning, Inc.)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; D-M1-MSSP1; D-M1-200309AC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dna Internet; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DOJ3jx7bf; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DOJ3jx7bf; .NET CLR 2.0.40607; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DownloadSpeed; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DP1000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; dpx; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; drebaIE-ZE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DrKW; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DRS_E)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DRS_E; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DRS;Techcom Software Solutions Inc.;KDDS1277;IE6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; d:tnt7_ForumBrowser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; d:tnt7_ForumBrowser; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DVD Owner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; DVD Owner; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {E2B5FAFC-1899-497E-BACC-EEEA7F24A5D2}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {E2E07F6D-A6E7-1684-82DA-8DE003B9C217})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {E422A9F3-43BA-41E7-AF5D-838A15EBE348}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {E4BBB50E-5B1B-4D8C-A819-AD524233897E}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {E5E08788-0480-4269-BC71-A7797C5D3C62}; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {E69CE46B-FC60-6F41-B5CD-7789712032EA}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {E85C6A09-3F78-4078-B300-293C2CD8FD03})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {E875708F-E195-B824-10FE-6BB954D80082})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {EA1C7663-ACC4-45B1-8A90-221B12478AF0})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {ED79526B-0CE1-4925-AAFF-F8C063DE0161})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {EE8C6E6D-7C14-493D-96D8-96189CDB443C})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {EEF090D2-AD10-4793-AA02-7C5F2B8F099F}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {EFACCBB9-0BDC-4B3A-A7B9-051398D9E119})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; eircom/june2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; EJGVNET; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; EK60SP1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; EMC IS 55; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Emiliano ti vede ....)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) [en]" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ENGINE; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; EROLS040199)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{02508E72-8688-4F8C-BF9C-73C3D029563C}; SV1; iebar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{101D66DC-5446-428D-A6EA-ED273C9FC84B}; Hotbar 4.4.7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{10ED3712-AD0D-4BB1-8D3C-0B0E15A671C4}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{1234D1DF-0277-4F9A-A0EB-0FAF5D432EE2}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{133E6249-80BF-4741-9A39-10C8D7C998AC}; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{136B3929-78D3-4728-A726-73ECC4B983CF})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{180F232C-E374-4B08-A664-FA09F726DBE4})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{1C38363F-253A-4424-B102-4495048AF33E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{28878E88-F98C-4A17-878A-E36A996D5072}; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{2F39423D-9DBB-48B9-B343-20ACBF9CFDC2}; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{30E3976E-D14C-4C93-B9B7-9AFECD8F306F}; MyIE2; Maxthon)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{31889988-FC07-40BA-7F3E-AEBEA15391D6}; ESB{E2E93F3B-0BE5-472F-2ABB-1C9AEFB49813}; ESB{CC56F89D-FD35-4E39-6074-F0B433D7D482}; ESB{225AAA31-E92C-4034-89D0-14B9F20BE982}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{34824601-AC35-488E-B249-BCD4AAF8A1C6})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{35404506-8A98-49E1-9E17-D61E2C1BAC18})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{3D72EE78-2FEB-4C75-B8DC-3BF40C60D3C5})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{45F63CFC-FA29-4C6E-A6D6-B947491001C8}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{472D70C9-7893-4D2B-B119-BB44221294EC}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{4779B872-DBEE-40A8-8442-E0FF5DA484D7}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{484F9004-564C-4B12-AC4E-1418ECDE928A}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{4B268CB2-51FA-4C84-B624-6DE3F0D887DA}; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{4D3EA7A9-3801-4A63-91E9-5CCC71E6868C}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{4E071CF0-5E40-4332-8E3D-AF6371997B08}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{58553345-1609-429A-8ED6-D9F1B9A77DC2}; ESB{65E1A955-DCEC-465A-821C-54F40FF8B34A}; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{5D811861-EA95-45EE-B290-38265CDC5E35}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{62965017-4DF0-4965-87E8-BA0D8449C3DE})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{688258C8-E4A8-482F-9667-C29B4CABFA9A}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{68DE235B-522D-4012-A9D9-E5F196997BC0}; ESB{D7EC4F6C-EFE4-4DBB-A0BD-FFCA2CEF6E60})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{6AF1F99B-2A01-4167-B3EE-BC497D63F9D4}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{6EFB5336-7A45-448B-843F-9AC66EF6FBD1})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{73AE67D7-E15F-4325-B51F-124AB9646A23}; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{75618962-1051-4901-83E3-FA45F0DE1ADD})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{75E350B6-0105-4218-971A-A1CB090DC683}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{77A48D0F-61AF-44B4-BEFD-42E758642C6D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{7D07736D-DE37-4F7F-AC8E-C68237EBF022}; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{7F8B060C-274D-4956-B4B4-46DEFBCBF28A}; ESB{4B5E3CE7-C53E-4C53-A2EE-6D064498DF1F}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{82EA8C84-7DC3-489C-B779-A3469BE4708E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{83E1DA4B-9DEF-4AFB-883B-D347E5A6107D}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{87F2D8B2-4248-4885-A012-C7B7FA26F488})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{8C127829-44A0-4BB8-9D28-E81994F66EE0}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{8C9138AB-F2ED-4BB7-A14E-2A3D3D977E0B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{91E7C142-4F0C-49FA-81C3-1E8A6C52A2F3}; ESB{C50C0A96-9BEB-46E8-B245-4EC5EC3830E5}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{9981848E-AAB6-4A05-B8A4-3A0A5F328952}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{9B524756-DEC6-4F01-8E9F-5922E7097A74}; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{9C041F81-CD5B-4241-9C74-CD4FE075546E}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{A1F633C5-98D0-4F80-A38A-7A216501394C}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{A5C6ECFC-8673-444F-B7E7-DE0C5B59D622}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{ABA66D21-29BE-4BAF-BAD4-ED6812C1E033}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{ADA09EE9-2082-4E60-A551-973A98214068})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{B485C8BD-00D2-42A3-A424-90D47ECB16EA}; ESB{51D3AFB9-B34E-42EB-8AD7-D60D7CEF84E2}; ESB{B901E2E3-3130-4FD3-A611-F671E4D7D235}; ESB{F8ED9EF0-B332-437D-AF6F-E4D7929AAE51}; ESB{145C6EA3-68A6-4840-8583-FDE74" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{BC8D007D-0F64-48DF-9841-D9A5F8184B58}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{C48545AB-77DE-4E4E-AC5B-183794002D5B})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{C809320D-9E35-41B8-B589-1857D6C6B121}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{C9452703-6C32-4564-9A1C-E11A31A69CD4}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{CD23C4DA-697C-4A7E-B50B-884DD2A1A8E2}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{D65EE013-85EB-431B-A47F-633C4457E9BE})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{D6E592CA-A859-4145-A375-64AC4DFC291D}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{D8F6BF12-200C-466E-85E5-06BBD005995E}; YPC 3.0.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{E3E1E7D6-9A2C-4F39-843E-362AB50F6088}; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{E63A7B5D-0538-4B3D-BBAB-915D834B1FE3})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{E6DD635D-0921-4491-B013-17AF67B2E602}; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{EA155034-249E-47E4-988B-5576EA36F928}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{EA67BD1B-D57E-4131-BCEC-E5C35BD6A0CE}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{F0F896A7-E6EA-4914-B1DE-C16BBB4A67E1})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{F40811EE-DF17-4BC9-8785-B362ABF34098}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{F7A8BDDE-BB37-40C8-AA1D-4B57BD78EFBA}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{FE364DB1-9712-443D-8511-83A85984644A}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ESB{FF0BE471-F8FA-4219-8FFC-07515C5FCB9C}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Eurobell Internet; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; exNetPanel:1059240)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F1ECC819-455A-46BC-A405-EFB52BF85707}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F2024F27-DA75-4D6A-B590-2AD23305F9F7}; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F27B2FF4-5121-47B1-8A63-CE5BD1021640})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F29D822D-EED0-4E29-8B61-8B038CEC1C0A}; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F35D706E-FD32-451F-9A2F-DFD96F9F0DA6})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F3A9F2D1-57F6-4A32-8E00-5AA391FC89A2})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F467C9A2-D4AF-4B0F-890E-8F8923BAE9C2}; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F4E70CE0-6237-4227-906E-788A750F9FB4}; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; F-6.0SP1-20030218)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; F-6.0SP1-20030218; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F70A8590-C5BA-483C-BE5F-8589C20E9B38})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F7BF8B53-70AB-4EA6-915C-C70769C62210})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F8498490-1D66-4D29-9FCC-BB35327A6257}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {F8FE05B9-FCEF-4302-AC51-C4B61FFBF4B9})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FA63D7BD-846C-43EE-9287-0FB9150B1111}; SV1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FB15F932-A469-4646-BCB4-8EB15AECFF9F}; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FC1AC744-B5CC-4237-96AA-E63B9FE6FE44})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FD749AFA-79D4-49DF-9348-6228D25835C8})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FDM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FE8FFD49-3EE4-412F-B700-175757E8EA1B}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Feat Ext 19)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Feat Ext 20)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Feat Ext 21)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FEB_2004-TPG; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Feedreader)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Feedreader; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Feedreader; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Feedreader; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FF25C218-3C07-491B-BFCA-D6C5557A414F}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FF360BD3-4648-4D2D-94C7-F95404BDC9BB})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FF8CB3A2-81BE-4550-B98C-CC9DFAF7A452}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FF8CB3A2-81BE-4550-B98C-CC9DFAF7A452}; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {FFBF6A73-2389-4D4F-A470-862760ED16CD}; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FGL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FIDUCIA IT AG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FIPID-{6/j.Ss94W0oM{6KchRpCsLmMQ222656249)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; fisg IE 6.0 SP1 (FID r2.0); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FMRCo cfg. 6.01.3.1b1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FMRCo cfg. 6.01.3.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FORSCOM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Free Download Manager)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; Feat Ext 19)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; FunWebProducts) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; SV1),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FREE; Wanadoo 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FreeWeb Explorer 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FS_COMPAQ_IE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; fs_ie5_04_2000_preload)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; fuck you; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; AskBar 3.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; BCD2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; dial; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; ESB{27845BE7-0EC6-473C-8064-3C4A063AB585}; ESB{5CEF3C99-0C80-47FB-B591-9EA0568D728D})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; FIPID-{8ORj5ZKEvfbg{8r02nwzw7eKE181427001)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; FunWebProducts-MyWay; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; FunWebProducts-MyWay; Wanadoo 6.1; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Grip Toolbar 2.07)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.3.5.0; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.1.0; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.2.0; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.5.0; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.5.0; MSN 8.0; MSN 8.5; MSNbBBYZ; MSNmen-us; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.5.0; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.7.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.4.9.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.5.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.5.1.0; MSN 6.1; MSNbMSFT; MSNmen-nz; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.5.1.0; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar4.5.2.0; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar4.5.3.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar4.5.3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; HTMLAB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; IBP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; iebar; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; iebar; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; KKman2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Maxthon; FREE)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MSN 6.1; MSNbMSFT; MSNmsv-se; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MSN 8.0; MSN 8.5; MSNbVZ02; MSNmen-us; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyTotalSearch)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyTotalSearch; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyTotalSearch; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; ESB{285EDB64-F0D5-40CE-9E80-0424E454F7A4}; ESB{82D87D6A-A9EA-4A92-A8E0-46F5501A1E54}; ESB{53A21F9E-0210-412D-A05D-A8145EBD094A}; ESB{B709ECE9-AE61-48D0-8788-FBBAD5FECB3E}; ESB{829700D" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; Grip Toolbar 2.07a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; JyxoToolbar1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; NetCaptor 6.5.0B6; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; .NET CLR 1.0.3705; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1; OptusNetDSL6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts-MyWay; SV1; www.kpas.net; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.1.4322" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.1.4322),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.1.4322; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; OptusNetCable-02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; OptusNetDSL6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; OZHARLIT5.5_1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; PP; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Preload_01_07; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Primus-AOL; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SIK30)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; AAPT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; ESB{793F2EFD-3EE8-4B36-AB38-1853C6EC257E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; Hotbar4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; Maxthon; MediaPilot; MediaPilotAd; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; Maxthon; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; MSN 6.1; MSNbDELL; MSNmen-us; MSNc22; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-gb; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; snprtz|T04114572010350)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; son-OEM-1101; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; SV1; YPC 3.2.0; .NET CLR 1.1.4322; PeoplePal 3.0; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; YPC 3.0.1; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FVSD#52)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; [Gecko])" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; generic_01_01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; generic_01_01; FunWebProducts; (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; generic_01_01; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; generic_01_01; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GIS IE5.5 SP1 4-20-2001 DMG Build)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GIS IE6.0 Build 20030604; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GIS IE6.0 Build 20031007; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GIS IE6.0 Build 20031008; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GIS IE6.0 Build 20031008; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GIS IE6.0 Build 20031111; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GIS IE 6.0 Build 20040714; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Global Visioneers, LLC - www.GlobalVisioneers.com -; Globcal Visioneers, LLC - www.GlobalVisioneers.com -)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GMX AG by USt; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; GoldenWeb.it)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Googlebot)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Googlebot/2.1 (+http://www.googlebot.com/bot.html))" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Googlebot/2.1 (+http://www.googlebot.com/bot.html); Maxthon; FDM)" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Google-TR-1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; H010818)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; H010818; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; H010818; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; H010818; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; H010818; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HCI0430; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HCI0441; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Headline-Reader; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Het Net 3.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hewlett-Packard; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hewlett-Packard; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HinBox 0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HJS.NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; hlink5.5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.1.7.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.1.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.1.8.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.1.8.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.1.8.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.1.8.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.1.8.0; SV1; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.1.8.0; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.10.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.11.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.1.1281; MSN 6.1; MSNbMSFT; MSNmfr-fr; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.1.1367; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.1.1367; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.13.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.13.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.14.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.14.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.8.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.2.8.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.3.1.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.3.2.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.3.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.3.5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.3.5.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.1.1394)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.1.1394; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.1.1406; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar4.4.1.1415)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar4.4.1.1415; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; FunWebProducts; MSN 6.1; MSNbDELL; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.2.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.5.0; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.5.0; FunWebProducts-MyWay; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.5.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.5.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.5.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.5.0; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.5.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.6.0),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.6.0; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.6.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.6.0; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.6.0; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.7.0; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.7.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.8.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.4.9.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.0.0; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.0.0; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc0z; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.0.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.1.0; .NET CLR 1.1.4322; FDM; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.1.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.5.1.0; SV1; MSN 6.1; MSNbMSFT; MSNmen-ca; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar4.5.3.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar4.5.3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar4.5.3.0; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hotbar Unknown; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Hot Lingo 2.0; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HPC Factor; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HTMLAB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HTMLAB; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; hubbabubba)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HW-IE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IBP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IBP; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IBP; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IBP; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Ibrowse/3.2(Ibrowse3.2;AmigaOS4.0); SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Icewtr Network services (jen); SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ICLP; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ICM60)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ICM60; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ICSLabs - USC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ICT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ICT; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IDG.pl)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE5.x/Winxx/EZN/xx; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE 6.05; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE60BRMM by STASM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE 6.0 (FID r1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE 6.0 SP1 (FID r2.0))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE 6.0 SP1 (FID r2.0); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE 6.0 SP1 (FID r3.0); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE 6.0 SP1 (FID r3.0); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE 6.0 SP1 (FID r3.0); (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE 6.0 SP1 Unrestricted; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE6CFG32a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE6CFG32a; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE6SP1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; DP Oslo; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-in; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iebar; SV1; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IE; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IESYM6; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IgwanaBrowser; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; Feedreader; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; Feedreader; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; .NET CLR 1.1.4322; FB-Solutions)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; i-NavFourF; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IncoNet Starter Kit ver 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; INFINOLOGY CORP; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; INFOAVE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; INFOAVE5; Q312461; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; INFOAVE5; Q312461; SV1; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Infowalker v1.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Infowalker v1.01; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; INTDUN; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; brip1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; Free Download Manager)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; Maxthon; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; MyIE2; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; IBP; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; MathPlayer 2.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; MyIE2; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iOpus-I-M; SV1; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iP-BLD03-PRE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iP-BLD03-PRE; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iP-BLD03; SV1; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iP-CMPQ-2003; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iP-CMPQ-HDD; FunWebProducts; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iP-CMPQ-HDD; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ip_internal_request; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iPrimus)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; iRider 2.07.0018; SV1; Feedreader; .NET CLR 1.1.4322)" + family: "iRider" + major: '2' + minor: '07' + patch: '0018' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; isp1057; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; istb 702)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; istb 702; i-NavFourF; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ITS-Ver1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IWSS:MSC01048/00096b3da0d3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IWSS:SPH-XP-SACH02/0008a1091f37; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; IWSS:WXP4390/00904b631249; IWSS:WXP4390/000d567960f4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JackGTestLocalMachineValue; someFunkyString; .NET CLR 1.1.4322; .NET CLR 1.0.3705; Others)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JAS; SV1; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JLC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JMV)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JMV; SV1; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1);JTB:15:817d2be2-fc1c-4568-8f4e-cc5f9a982e3b" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Juni)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JUNO; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JyxoToolbar1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JyxoToolbar1.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JyxoToolbar1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; JyxoToolbar1.0; SV1; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Katiesoft 7; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KITXP40NL; MSN 6.1; MSNbMSFT; MSNmnl-nl; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KKman2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KKman2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KKman3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Kmart; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Kmart; Q312461; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KPMG; InstantAlbert; XBOXToolbar; CustomToobar.com; Eduardo A. Morcillo; Custom Browser Inc.; SavantMedia; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KPMG; InstantAlbert; XBOXToolbar; CustomToobar.com; Eduardo A. Morcillo; Custom Browser Inc.; SavantMedia; SinglesToolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; KPSWorkstation; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; LDS Church)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; LIB Staff; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Link Checker Pro 3.1.72, http://www.Link-Checker-Pro.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; LN; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; LTH Browser 3.02a; FDM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Lunascape 1.3.1)" + family: "Lunascape" + major: '1' + minor: '3' + patch: '1' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; luv u; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; lvw)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; LW0815)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Lycos-Online; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MADE BY WEBO; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MassCops Browser; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MathPlayer 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MathPlayer 2.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MathPlayer 2.0; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MathPlayer 2.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MathPlayer 2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MathPlayer 2.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MathPlayer 2.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Matrix Y2K - Preview Browser; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; Alexa Toolbar)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; FDM)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; iRider 2.20.0002)" + family: "iRider" + major: '2' + minor: '20' + patch: '0002' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; MyIE2; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; MyIE2; SV1)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; MyIE2; SV1; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; (R1 1.5))" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; SailBrowser 2005; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; Stardock Blog Navigator 1.0; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; SV1)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; SV1; Alexa Toolbar)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; SV1; Feedreader; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; SV1; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; SV1; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; McInternetBrasil_MCAAE_3112; NusaQuiosque; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MCI Windows Corporate Image; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MCI Windows Corporate Image; QS 4.1.1.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MCI Windows Corporate Image; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MCI Windows XP Corporate Image; MCI Windows Corporate Image; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MediaPilot; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Megara Web; IE 6.05; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mercer Human Resource Consulting; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Metro C&C, Croatia)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MidBC001; Q312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Miele & Cie. Explorer Version 6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MiniJv2 3.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; mip.sdu.dk)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mon_AutoConfig_v1.02_STL; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mountainside; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .Mozilla)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Menara); SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (Compatible; MSIE 6.0; Windows 2000; MCK); Mozilla/4.0 (Compatible; MSIE 6.0; Win; MCK); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; -D-H1-MS318089))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; HDR.05.01.00.06; .NET CLR 1.0.3705; .NET CLR 1.1.4322); .NET CLR 1.1.4322); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (compatible,MSIE 6.0; Windows NT; Brite Way Publishing; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0(compatible; MSIE 6; Win32; Mck))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0(compatible; MSIE 6; Win32; Mck); Mozilla/4.0 (Compatible; MSIE 6.0; Win; MCK))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Mozilla/4.0 (zgodny z ISO 900087635.5); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MPD JV v1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MRA 2.5 (build 00387))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MRA 3.0 (build 00614))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MRA 4.0 (build 00768))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MS Custom IE; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSIE6XPV1; KB824145; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; msie6xpv1; LM_POSTPLATFORM; MSIE6ENV6; MS04-004; CU_POSTPLATFORM; .NET CLR 1.0.3705; .NET CLR 1.1.4322; LM_50_POSTPLATFORM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; msie6xpv1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; msie6xpv1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmbr-br; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc0z; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmen-sg; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc21)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmit-it; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 6.1; MSNbMSFT; MSNmtc-tw; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 8.0; MSN 8.5; MSNbBBYZ; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 8.0; MSN 8.5; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-gb; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 9.0; MSNbBBYZ; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 9.0; MSNbDELL; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSN 9.0; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; AtHome0200; T312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; AtHome021SI; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; AtHomeEN191; Hotbar 4.3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; AtHomeEN191; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; Q312461; Hotbar 4.0; SEARCHALOT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MSOCD; T312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MTI; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MTI; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Multikabel)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyHealthyVet; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2 0.3)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Alexa Toolbar)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Deepnet Explorer; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; ESB{9D28903E-AE01-4815-A52A-AE2885F86845}; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; ESB{E225A099-D057-4FEF-BAC6-3BEC123804CC}; NN5.0.2.23)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Feedreader)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Feedreader; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; FunWebProducts)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Hotbar 4.5.0.0; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; i-NavFourF; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; iOpus-I-M; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; iRider 2.10.0008)" + family: "iRider" + major: '2' + minor: '10' + patch: '0008' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; JyxoToolbar1.0; iolbar-3.0.0.XXXX; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Matrix Y2K - Preview Browser; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; AIRF; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; iOpus-I-M; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; .NET CLR 1.1.4322; FDM)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; SV1)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; SV1; Deepnet Explorer; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; SV1; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; Maxthon; SV1; .NET CLR 1.1.4322; Tablet PC 1.7; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; NetCaptor 7.0.1)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; NetCaptor 7.5.3; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.0.2914; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; (R1 1.1); FDM)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; (R1 1.1); .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; (R1 1.3))" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; (R1 1.5))" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; (R1 1.5); .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; Alexa Toolbar)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; CustomToolbar.com; Maxthon)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; Mailinfo [102065]; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; Maxthon)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; Maxthon; Feedreader; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; .NET CLR 1.1.4322; FDM)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; TheFreeDictionary.com)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Nahrain)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NARA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NaturaMediterraneoEEmare; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Neostrada Plus 5.6; FIPID-{2N8gA8m2Ta32{2nYX0EkruYpg585052490; i-MailBook)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Neostrada TP 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.0.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.0.2 Final; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.0.2 Final; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.1.0 Beta 2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.2.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.2.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.2.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.0 Gold)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.0 Gold; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.0 Gold; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.2; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.2; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.3; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NetCaptor 7.5.4; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3621)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .BGDID000017489A1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; Dave)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; Feat Ext 19)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; Feat Ext 21)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; Googlebot; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; &id;)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; MSN 8.0; MSN 8.5; MSNbDELL; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; MSN 8.0; MSN 8.5; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.0.3621; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 3.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Tablet PC 1.7)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; XMPP TipicIM v.RC6 1.6.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; NetNearU)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; Tablet PC 1.7; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Alexa Toolbar; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Donut RAPT #51 Sugi)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322-dtb)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Feat Ext 18)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Feat Ext 19)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Feat Ext 21)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Free Download Manager)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Lunascape 1.4.1)" + family: "Lunascape" + major: '1' + minor: '4' + patch: '1' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmde-de; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-gb; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc11; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmnl-be; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 8.0; MSN 8.5; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 8.0; MSN 8.5; MSNbVZ02; MSNmen-us; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 9.0; MSNbBBYZ; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 9.0; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; MSN 9.0; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40301)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40426)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.31113)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.40301)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.40426)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.40607; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.40607; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Netibar 1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; SpamBlockerUtility 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Tobbes surfing board)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322) WebWasher 3.3" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; XMPP TipicIM v.RC5 1.6.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.40607; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.40607; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.40607; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 2.0.40903)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Netpenny)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Netvitamine Toolbar (+http://www.netvitamine.com); i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; New Value #1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NISSC; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NISSC; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NN4.2.0.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NN5.0.2.23; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NN5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NN5.0.3.3; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NN5.0.3.3; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; NN5.0.600.15)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Nordstrom; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ntlworld v2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ntlworld v2.0; Hotbar 4.5.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ntlworld v2.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; nxforms/1.00; formsPlayer 1.1; formsPlayer 1.3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ONET; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Ongame E-Solutions AB; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ONLINE 5.5; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OnlyInternet.Net; Personal Computer Doctors)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ONS Internet Explorer 6.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OPT-OUT; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OPT-OUT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OPT-OUT; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE501-018)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE501-018; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE501-018; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-27)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-27; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-27; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-31; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE55-32)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusIE5; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; SV1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetCable-02; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetDSL6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetDSL6; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetDSL6; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetDSL6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetDSL6; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetDSL6; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetDSL6; SV1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OptusNetDSL6; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Origin Energy Limited - SOE 3.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OZEHAR01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OZHARLIT6.0_1_PP3; FunWebProducts; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OZHARLIT6.0_1_PP3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OZHARLIT6.0_1_PP3; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; OZHARLIT6.0_HN)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Paros/3.2.0" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PASSCALL; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PCAdvisor032002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PCPLUS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PCUser; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PeoplePal 3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Performance Technologies S.A.; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PGE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PhaseOut [www.phaseout.net]; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PKBL008; fs_ie5_04_2000i)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Plus a few changes)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PNCStd)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Poco 0.31; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Polkomtel S.A.; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PottsNet; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PowerBase6; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Preload_01_07)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Preload_01_07; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Prepaidonline.com.au setup; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Primus-AOL)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PrimusCAlanEN; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PrimusDSLEN)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PrimusPCEN)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PROGRATECH; MSIE6.0XP OpenBrowser CPOP5.2; DyGO.NET MailSRV; MyIE2; SV1; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Provided by Alphalink (Australia) Pty Ltd)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PRU_IE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PwCIE6v01; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; PwCIE6v01; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q-06062002-K2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q-06062002-K2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312460)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; 1.21.2 ; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; AAPT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; AIRF; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Amgen.v1b; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; APCMAG; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; AT&T CSM6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; AT&T CSM6.0; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; BCD2000; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; BrowserBob; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; BTopenworld; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; CDSource=ALLIED_01_01; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; CDSource=storecd_01_03; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; COM+ 1.0.2204; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Cox High Speed Internet Customer; 1.41.1 )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Cox High Speed Internet Customer; i-NavFourF; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Cox High Speed Internet Customer; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Cox High Speed Internet Customer; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; DVD Owner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; ESB{6C1AEBB4-8C44-41AE-866F-707D5E75B0E9}; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; ESB{A44A754F-952B-4E88-802A-5725DBA66F0E})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; F-6.0-20020225)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Feedreader)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Feedreader; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; FunWebProducts-MyWay; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; FunWebProducts; NetCaptor 7.5.2; WebCloner 2.3; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; FunWebProducts; ntlworld v2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; GIL 2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hewlett-Packard; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 3.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 4.1.5.0; MyIE2; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 4.1.8.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 4.4.5.0; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 4.4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 4.4.7.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 4.4.7.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 4.5.1.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Hotbar 4.5.1.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; IESYM6; Hotbar 4.5.0.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; IOpener Release 1.1.04)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; iOpus-I-M; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; iOpus-I-M; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; MathPlayer 2.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; MyIE2; Maxthon; SV1; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; MyIE2; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; MyIE2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.0.2914; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.0.3705; .NET CLR 1.2.2125; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; NN5.0.600.11)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; OptusNetDSL6; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Paul BunyaNet; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Q-07122002-K2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; (R1 1.3); .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Roadrunner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Roadrunner; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; Roadrunner; TheFreeDictionary.com; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; sbcydsl 3.12; YComp 5.0.0.0; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SIK30; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; 18ko/; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; ATB; Visited by ATB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; GIL 2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; IBP; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; SV1; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; T312461; SV1; EnergyPlugIn; dial; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; TeomaBar 2.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; TeomaBar 2.01; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; TeomaBar 2.01; SV1; MSN 6.1; MSNbMSFT; MSNmja-jp; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; tiscali; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; TUCOWS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; TVA Build 2001-10-11)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.0.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.0.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.2.5; Hotbar 4.2.8.0; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YComp 5.0.2.6; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YPC 3.0.1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461; YPC 3.0.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312462)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312463)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312464)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312465)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312466)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312467)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312468)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312469)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q321017)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q321017; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q321120; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q321120; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q321120; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q321150; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q342532)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q822925; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QinetiQ IE6 V02; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QS 4.1.1.2; DVD Owner; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QS 4.1.2.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QS 4.1.2.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QS 4.1.2.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Queensland Government; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QUT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QUT Printing Services; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Qwest - 11122003-a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Qwest - 11122003-a; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Qwest - 12302003-sms)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Qwest - 12302003-sms; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QXW0330d; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QXW0339d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QXW0340e; www.ASPSimply.com; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.1); FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.1); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.1); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3)),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3); MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; [R1 1.3]; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3); .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.3); .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); MSN 6.1; MSNbMSFT; MSNmen-ca; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; (R1 1.5); (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; RD&E v.6.0 r.6; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; RD&E v.6.0 r.6; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Really Firefox-It works fine asshole)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Renault)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Renault; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; RI-ADMIN12112003)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; FunWebProducts; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Roadrunner; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; Hotbar 4.4.2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; Hotbar 4.4.2.0; SV1; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; iebar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; TheFreeDictionary.com; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; YPC 3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; YPC 3.1.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Rogers Hi-Speed Internet; YPC 3.1.0; yplus 4.5.03b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; RSD66)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; rtc user)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; rtc user; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; RWE Dea AG)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)-s" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SALT 1.0.3404.1 1007 Developer; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SALT 1.0.4223.1 0111 Developer; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SALT 1.0.4223.1 0111 Developer; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SALT 1.0.4613.0 0111 Developer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SALT 1.0.5507.1 0111 Developer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SAVEWEALTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; ESB{E49F02C9-B446-4F5C-9EB8-5A2DF808DA80}; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; FunWebProducts; YPC 3.0.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; SV1; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; SV1; YPC 3.0.3; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.1.4322; yplus 3.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YComp 5.0.0.0; yplus 3.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; yie6_SBCDSL; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YPC 3.0.1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sbcydsl 3.12; YPC 3.0.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SBS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SBS; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SC/5.10/1.14/Telenor)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SC/5.10/1.14/Telenor; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SC/5.60/1.01/FS-Internett; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; School of Business and Computing; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SCL Build)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; ScreenSurfer.de; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SEARCHALOT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SEARCHALOT.COM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SEARCHALOT.COM; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SearchFox Toolbar 2.0b1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sfgdata=5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SFIE60122601; SFIEAUTH1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SFIEAUTH1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SGC; SGC STUDENTS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Sgrunt|V107|634|S-1869674593|dialno; alice01; snprtz|dialno; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Sgrunt|V109|1684|S-129601565|dial; snprtz|S03037726560360)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Sgrunt|V109|622|S1290160941|dialno; snprtz|dialno)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Sgrunt|V109|69|S-327757572|dialno)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Shazam; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Siemens A/S; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; FunWebProducts; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; FunWebProducts; SV1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SIK30; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SINGNET)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SINGNET/HTMLAB; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SiteCoach 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SKY11a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SKY13; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SlimBrowser [flashpeak.com])" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Smart Explorer 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Smart Explorer 6.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Smart Explorer 6.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Smart Explorer v6.0 ( Evaluation Period ))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Smart Explorer v6.0 ( Evaluation Period ); .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; snft internet; SV1; OptusNetDSL6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; snopud.com client; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Snowdrop Systems; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; snprtz|dialno; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; snprtz|S03037726560360)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; snprtz|T03022004250337; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; snprtz|T04125278003990)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SOK)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SON-1102CD; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SON-1102CD; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; sp1, AHS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SP/6.35/1.01/ONLINE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SPARTA AREA SCHOOLS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SPServe)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; **SPS**; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SS.CC. Palma)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StarBand Version 1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StarBand Version 4.0.0.2; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StarBand Version 4.0.0.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StarBand Version 4.0.0.2; SV1; .NET CLR 1.0.3705; Media Center PC 2.8; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {Starpower})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; STB; 560x384; MSNTV 4.1; THMDR)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; STIE60-021004; STIE60-020212; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; STI; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; STI; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; stokeybot)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Stonehenge School)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StopTrackingMe; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Stratford ISD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.733; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.735; MyIE2; SV1; Maxthon; JyxoToolbar1.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.735; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.736; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.744)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.755)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.755; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.758; MyIE2; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.758; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.760)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.760; iRider 2.21.1108; .NET CLR 1.1.4322)" + family: "iRider" + major: '2' + minor: '21' + patch: '1108' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.760; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.760; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.760; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.763)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.763; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.818; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.818; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.820; SV1; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.901; FDM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.906; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.910; Maxthon; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.910; SV1; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.910; SV1; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.917; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.917; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.917; SV1; Hotbar 4.5.1.0; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.919; Maxthon; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; StumbleUpon.com 1.919; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; stumbleupon.com 1.923; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; stumbleupon.com 1.923; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; stumbleupon.com 1.924; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; stumbleupon.com 1.924; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; stumbleupon.com 1.925; .NET CLR 1.0.3705; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; stumbleupon.com 1.926; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; stumbleupon.com 1.926; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; subagente; Agente; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Sunrise; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Supplied by blueyonder)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Supplied by blueyonder; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Supplied by blueyonder; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Supplied by blueyonder; SV1; Hotbar 4.5.1.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Supplied by blueyonder; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Supplied by Tesco.net)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Surf Mechanic; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; 1.41.1 ; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; 1.56.1 ; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; 9LA; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AAPT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; ACTC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AIRF; NetCaptor 7.2.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AIRF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Alexa Toolbar; jd; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Alexa Toolbar; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Alexa Toolbar; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Alexa Toolbar; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; ALL YOUR BASE ARE BELONG TO US; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Antenna Preview Window)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Antenna Preview Window; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AOL7)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; APCMAG; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Arcor 5.002; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Arcor 5.002; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Arcor 5.003)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AskBar 3.00; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AT&T CSM6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AT&T CSM7.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AT&T CSM8.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AUTOSIGN W2000 WNT VER03)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AVPersonalSerial 2b206c294a291e6470432759423669f000255953; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; BBIP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; BCD2000; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Berg Network Client; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; BMD Melbourne; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Boeing Kit; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; brip1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; BTHS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; BT Openworld BB; YPC 3.0.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; BT Openworld Broadband; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; BT Openworld Broadband; YPC 3.2.0; yplus 4.3.02d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; BTY; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Burnie High Student)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Canning College)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CaseDOSA/Operator; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CDSource=BP1b.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CDSource=v11c.01; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CDSource=v9e.04; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CIM Gruppen; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Citrix)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Compatible; Version; ISP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Cox High Speed Internet Customer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Cox High Speed Internet Customer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Creative; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CSIE60SP02; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CursorZone 1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CursorZone Grip Toolbar 2.08; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; custom; custom; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; custom; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Deepnet Explorer)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Deepnet Explorer 1.3.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Deepnet Explorer 1.3.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Deepnet Explorer 1.3.2; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Deepnet Explorer; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Deepnet Explorer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Deepnet Explorer; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; DHSI60SP1001; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; DI60SP1001)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; DigExt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; DigExt; FunWebProducts; Media Center PC 3.0; .NET CLR 1.0.3705; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; digit_may2002)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; D-M1-200309AC;D-M1-MSSP1; D-M1-200309AC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; DOJ3jx7bf; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Domain user; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Donkey; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; DownloadSpeed; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; DVD Owner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; DVD Owner; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Editor 3.0 - http://www.e-ditor.com; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; ESB{77898B69-9C1F-433D-B8EA-FD6FA2B8A2CC}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; ESB{C6B1C008-FCCB-4A07-BF79-6BEED181D1F0})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; E-train)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; evUI; Agency Manager Management Console; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FDM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FeedEater; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Feedreader; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Feedreader; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Feedreader; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Feedreader; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Feedreader; (R1 1.5); .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; formsPlayer 1.3; nxforms/1.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FREE; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FTDv3 Browser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FTDv3 Browser; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; 1.56.1 ; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; 1.56.1 ; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; Alawar 2.08; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; Hotbar4.5.3.0; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; Hotbar4.5.3.0; MSN 6.1; MSNbMSFT; MSNmen-ca; MSNc00; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; Hotbar4.5.3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; i-NavFourF; onlineTV; www.cdesign.de; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; MSN 6.1; MSNbMSFT; MSNmen-gb; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts-MyWay)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts-MyWay; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts-MyWay; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts-MyWay; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-ca; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.1.4322; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmnl-nl; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; (R1 1.1); (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; SpamBlockerUtility 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; FunWebProducts; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; GambleEnt; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; gameland)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; GIS IE6.0 Build 20031111; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; GMX AG by USt; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; gogo)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Golfing Paradise; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Tablet PC 1.7)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Grip Toolbar 2.07a)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Grip Toolbar 2.08; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Headline-Reader; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; HEL INTERNET EXPLORER)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.2.14.0; .NET CLR 1.0.3705; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.4.5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.4.6.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.4.6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.5.1.0; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.5.1.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.5.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar4.5.3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar4.5.3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar4.5.3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar4.5.3.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar4.6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar 4.6.1; MSN 6.1; MSNbMSFT; MSNmnl-nl; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Hotbar Unknown; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; HTMLAB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; http://www.aztrx.com/ )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; http://www.tropicdesigns.net)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; http://www.tropicdesigns.net; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; IBP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; IBP; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; IBP; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; IBP; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iebar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iebar; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iebar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iebar; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iebar; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Imperial College; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; i-NavFourF; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; i-NavFourF; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; i-NavFourF; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; i-NavFourF; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iOpus-I-M)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iOpus-I-M; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iOpus-I-M; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iOpus-I-M; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iOpus-I-M; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iOpus-I-M; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iOpus-I-M; Wanadoo 6.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iP-CMPQ-2003; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; iP-CMPQ-HDD; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; IWSS:wxp4432/00114366da97; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; JNet; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; JUNO)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; KATIESOFT 6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; KKman3.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; LetNet Connect, [www.letu.edu]; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; lWh.lgS.rfU.lxd; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Manor Trust::)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MathPlayer 2.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MathPlayer 2.0; i-NavFourF; .NET CLR 1.1.4322; .NET CLR 2.0.41202)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MathPlayer 2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; Alexa Toolbar)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; FREE)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; FREE; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; NetCaptor 7.5.4)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322; FDM)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322; FDM; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; (R1 1.5); .NET CLR 2.0.40903)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MaxXium; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Media Center PC 3.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Media Center PC 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Media Center PC 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MediaPilot)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; Campus Bundaberg;))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.0 (build 00768); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.0 (build 00768); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSCS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbDELL; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmen-ca; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmen-gb; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmfr-fr; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 6.1; MSNbMSFT; MSNmnl-nl; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 9.0;MSN 9.1; MSNbQ002; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MTI; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MTK; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; iebar)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; Maxthon)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; Maxthon; Alexa Toolbar)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; Maxthon; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; Maxthon; (R1 1.3))" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; Maxthon; TaxWise19.00[0016]; TaxWise19.01[0003]; TaxWise19.02[0005]; TaxWise19.03[0001]; TaxWise19.04[0001]; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; .NET CLR 1.0.3705)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Neostrada Plus 5.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Neostrada TP 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.2.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.0 Gold; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.2; FDM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.2; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.3; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.3; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.4; Media Center PC 3.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetCaptor 7.5.4; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Alexa Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Media Center PC 2.8; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Media Center PC 2.8; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Media Center PC 3.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Media Center PC 3.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; MSN 6.1; MSNbMSFT; MSNmit-it; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 3.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 3.1; Googlebot/2.1)" + family: "Googlebot" + major: '2' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 3.1; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 3.1; .NET CLR 2.0.40209)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Q342532)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Tablet PC 1.7)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; XMPP TipicIM v.RC6 1.6.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 2.0.40607; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Tablet PC 1.7)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Tablet PC 1.7; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; Tablet PC 1.7; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; 45c42354c4e5r4cw!(s)4sd)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Alexa Toolbar; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Alexa Toolbar; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322) Babya Discoverer 8.0:" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; FDM; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Hotbar 4.6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Hotbar 4.6.1; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Hotbar 4.6.1; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Lunascape 1.4.0beta3)" + family: "Lunascape" + major: '1' + minor: '4' + patch: '0' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Lunascape 1.4.1)" + family: "Lunascape" + major: '1' + minor: '4' + patch: '1' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Lunascape 1.4.1),gzip(gfe) (via translate.google.com)" + family: "Lunascape" + major: '1' + minor: '4' + patch: '1' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Lunascape 2.0.1)" + family: "Lunascape" + major: '2' + minor: '0' + patch: '1' + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmde-at; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-ca; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-gb; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-gb; MSNc0z; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc11; MSNc11)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc11; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-us; MSNc21; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmit-it; MSNc0z; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbBC01; MSNmen-ca; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbBC01; MSNmfr-ca; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-gb; MSNcOTH)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcIA; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbMSNI; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbQ002; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSN 9.0;MSN 9.1; MSNbVZ02; MSNmen-us; MSNcOTH; MPLUS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MSNc11; MSN 6.1; MSNbMSFT; MSNmen-us)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.2914; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.2914; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; Media Center PC 3.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40903)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; Version; Platform; Compatible)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40209)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40301)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40903)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40903; Avalon 6.0.4030)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.41115)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.41202)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50110)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50110; Avalon 6.0.4030)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50215)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; NOKTURNAL KICKS ASS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Q342532)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Secure IE 3.3.1263)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; Tablet PC 1.7)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.40607; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.40607; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.40607; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.40607; .NET CLR 2.0.40426; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.40903; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.41118; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50126)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Net M@nager V4.00 - www.vinn.com.au)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NetPanel:763771; npUID:763771; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NN4.2.0.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; N_O_K_I_A)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) NS8/0.9.6" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; nxforms/1.00; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OfficeWorld.com/1.082)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusIE55-31)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusIE55-31; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusNetCable-02)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusNetDSL6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusNetDSL6; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusNetDSL6; FDM; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusNetDSL6; MathPlayer 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusNetDSL6; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; OptusNetDSL6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Overture; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; PeoplePal 3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Poco 0.31)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Poco 0.31; TencentTraveler ; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; PrimusDSLEN; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Prisoner; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; provided by blueyonder; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Q342532)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Quik Internet (0102098b))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.1))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.3); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.3); .NET CLR 1.0.3705; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.3); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.3); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.3); .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc0z; MSNc00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.3); (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); MSN 6.1; MSNbMSFT; MSNmen-us; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 3.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); onlineTV; www.cdesign.de)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (R1 1.5); snprtz|T04077983781234)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; RCBIE6XPMAN; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Rogers Hi-Speed Internet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SALT 1.0.3404.1 1007 Developer; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SALT 1.0.5507.1 0111 Developer; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SALT 1.0.5507.1 0111 Developer; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Sgrunt|V108|654|S-2135541317|dial; snprtz|T03087750360356; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Sgrunt|V109|34|S-1398421108|dialno; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Sgrunt|V109|547|S1107901103|dial; XBE|29|S04039483631143; snprtz|S04048557771347)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Sgrunt|V109|598|S76509116|dialno)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SIK30)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SIK30; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SIK30; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SLPS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SmartShop)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SON-1102CD)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SON-1102CD; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SPARTA AREA SCHOOLS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; sumit)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Suncorp Metway Ltd; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Supplied by blueyonder)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Supplied by blueyonder; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Supplied by Tesco.net; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; surfEU FI V3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Tablet PC 1.7; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Tablet PC 1.7; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40903)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; TBP_6.1_AC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; TencentTraveler )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; TeomaBar 2.01; AskBar 3.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; TeomaBar 2.01; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; TheFreeDictionary.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; TheFreeDictionary.com; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; TNET5.0NL; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; urSQL; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; User Agent; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; UserAgent; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Virgin 3.00)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; VND Toolbar; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; VNIE5 RefIE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; VNIE5 RefIE5; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; VNIE60; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; VNIE60; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Wanadoo 5.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Wanadoo 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Wanadoo 6.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Wassup; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; WebSpeedReader 8.6.96; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) WebWasher 3.3" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; WHCC/0.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; WHCC/0.6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; WHCC/0.6; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; WI4C 3.5.3.001; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; www.ASPSimply.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; www.aztrx.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; www.k2pdf.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Wysigot 5.51)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; XMPP TipicIM v.RC6 1.6.8; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; XN2K3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; yie6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; yie6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; yie6_SBC; YPC 3.0.3; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.1; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.2; .NET CLR 1.1.4322; yplus 4.4.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.3; .NET CLR 1.1.4322; yplus 4.0.00d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.0.3; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.1.0; bgft; Media Center PC 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.1.0; Media Center PC 3.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.1.0; yplus 4.5.03b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; YPC 3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SWSIT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SWSIT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Sykes Enterprises Inc. B.V.)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SYMPA)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SYMPA; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SYMPA; Q312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SYMPA; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; Artabus)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; DI IE 5.5 SP2 Standard; GESM IE 5.5 SP2 Standard; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; PGE; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; Q312461; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; SV1; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; SV1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; SV1; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; YComp 5.0.0.0; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; T312461; YComp 5.0.0.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TARGET HQ; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TaxWise19.00[0016]; TaxWise19.05[0002]; TaxWise19.07[0006]; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_6.1_AC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_6.1_AC; NetCaptor 7.5.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_6.1_AC; (R1 1.3); Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_7.0_GS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_7.0_GS; FunWebProducts; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_7.0_GS; Hotbar 4.5.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_7.0_GS; .NET CLR 1.1.4322; MSN 6.1; MSNbMSFT; MSNmen-au; MSNc00; v5m)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_7.0_GS; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBP_7.0_GS; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TBPH_601)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TDSNET8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; telus.net_v450HS; SV1; Hotbar 4.5.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; telus.net_v5.0.1; Hotbar 4.5.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TencentTraveler )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TencentTraveler ; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TeomaBar 2.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TeomaBar 2.01; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TeomaBar 2.01; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Testing.net; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Texas Instruments)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Texas Instruments, Inc; [R1 1.3]; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; The Department of Treasury - Bureau Of The Public Debt)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TheFreeDictionary.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TheFreeDictionary.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TheFreeDictionary.com; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; The Free Lance-Star Publishing Company)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Thiess Pty Ltd)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; tip; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TiscaliFreeNet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Tiscali; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TMS Inst 5.5; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TNT Australia Pty Ltd; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Total Internet; Q312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TR.NET Dialup Ver.2.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TRPIT; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TRPIT; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TS User; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TUCOWS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TUCOWS; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TVA Build 2002-05-16)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; TVA Build 2002-05-16; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; U)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; UBIS-RESNET 2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; UKPORTAL; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; UrIE 4.0; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; urSQL; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; %username%; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 2.8)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; USERNAME_PASSWORD_IS_ENABLED; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; UUNET)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; V1.0Tomorrow1000; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; v11b.01; FunWebProducts; SV1; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; V6.00-003)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; v6.1b; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; V6; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Videotron)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Videotron; SV1; CustomExchangeBrowser; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VIRTUALIT.BIZ; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Virtual IT - http://www.virtualit.biz)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE4 3.1.814; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE5 RefIE5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE5 RefIE5; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE5 RefIE5; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE5 RefIE5; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE60)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE60; MyIE2)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE60; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE60; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; VNIE60; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Voicecrying.com; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Voyager II; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; vtown v1.0; FunWebProducts; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo042NLPP01HCFFFFFFEC; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo042NLPP01HCFFFFFFFA; AtHome033)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.5)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.5; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.5; SV1),gzip(gfe) (via translate.google.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.5; Wanadoo 6.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.5; Wanadoo 6.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.5; Wanadoo 6.2; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.6; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 5.6; Wanadoo 6.1; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0; i-NavFourF)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0; i-NavFourF; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.1; Wanadoo 6.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo 6.2; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wanadoo Câble 5.6; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Was guckst du?; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WCCTA; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; weasel & chicken; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WebSpeedReader 8.7.4; Hotbar 4.5.1.0; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) WebWasherEE/3.4.1 3.4.1" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Westerville Public Library; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WestNet)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Weybridge; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WHCC/0.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WHCC/0.6; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WHCC/0.6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WHCC/0.6; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WHCC/0.6; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WHO Synergy II; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wile E. Coyote Build - ACME)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Windows XP SP2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Windows XP SP2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WinXP-SOE v3.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WODC; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .WONKZ)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wooohooooooooooooooooooooooooooo!; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; World Interactive Software)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {World Online})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WRV)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; W&S; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; WWIEPlugin; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.amorosi4u.de.vu)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.ASPSimply.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.ASPSimply.com; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.ASPSimply.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.ASPSimply.com; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.ASPSimply.com; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.ASPSimply.com; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.Bertram-Engel.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.BERTRAM-ENGEL.com Webmaster; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.k2pdf.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.k2pdf.com; Compatible; Version; Platform)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.k2pdf.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.k2pdf.com; SV1; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.k2pdf.com; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.oxy-com.com; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.spambully.com)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.spambully.com; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; www.wbglinks.net)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wysigot 5.22; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Wysigot 5.4; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; X Channel Browser)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; XTM02b Beta 1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; XTM02b Beta 1; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; FunWebProducts; Hotbar 4.5.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; FunWebProducts-MyWay; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; Hotbar 4.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; Maxthon; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; .NET CLR 1.0.2914)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; Rogers Hi-Speed Internet; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; sbcydsl 3.11; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; sbcydsl 3.12; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; SEARCHALOT; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0; yplus 3.01)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.4)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.4; AskBar 2.11)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.4; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.5; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6; Feedreader)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6; Hotbar 4.4.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.2.6; ntlworld v2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.8.6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.8.6; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.8.6; SV1; yplus 1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6; DVD Owner)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6)Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6_SBC)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6_SBCDSL; FunWebProducts; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6_SBCDSL; sbcydsl 3.12; YComp 5.0.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6_SBCDSL; sbcydsl 3.12; YPC 3.0.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6_SBC; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6; sbcydsl 3.12; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6_SBC; YPC 3.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6; SV1; (R1 1.5))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6; YComp 5.0.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6; YPC 3.0.3; (R1 1.3))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yie6; YPC 3.0.3; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; BT Openworld BB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; BTopenworld; yplus 4.3.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; FunWebProducts; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; SV1; (R1 1.1); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; SV1; yplus 4.0.00d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.0; yplus 4.3.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; FunWebProducts; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; FunWebProducts; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; Hotbar 4.4.2.0; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; NetCaptor 7.5.0 Gold)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.0.3705; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.0.3705; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; (R1 1.3); (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; (R1 1.5; yplus 4.1.00b))" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; SV1; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; SV1; .NET CLR 1.0.3705; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; SV1; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; SV1; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; SV1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; yie6_SBC; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; BT Openworld BB)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; BT Openworld BB; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; BT Openworld BB; .NET CLR 1.1.4322; yplus 4.3.02d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; BT Openworld BB; SV1; yplus 4.3.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; BT Openworld BB; SV1; yplus 4.3.02d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; .NET CLR 1.0.3705; yplus 4.4.02d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; .NET CLR 1.1.4322; .NET CLR 1.0.3705; yplus 4.4.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; .NET CLR 1.1.4322; yplus 4.3.01b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; .NET CLR 1.1.4322; yplus 4.3.02b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; SV1; ESB{4146F2DC-3320-4F28-8906-D3591D69426E}; TheFreeDictionary.com; yie6-uk; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; SV1; yplus 4.3.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; SV1; yplus 4.3.02b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; yplus 4.3.02b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; yplus 4.3.02d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.2; yplus 4.4.01d)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; FunWebProducts; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; .NET CLR 1.1.4322; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; SV1; .NET CLR 1.0.3705; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; SV1; .NET CLR 1.1.4322; Hotbar 4.6.1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; SV1; .NET CLR 1.1.4322; yplus 4.0.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.0.3; SV1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.1.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.1.0; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.1.0; SV1; FunWebProducts)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.1.0; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.1.0; SV1; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.2.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.2.0; .NET CLR 1.0.3705; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; yplus 4.1.00b)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Z-HARPE)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Zurich North America; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2;)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; {2C2E9759-7422-4D75-89A2-9C0419FE3957}; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; {2D24C5F8-6342-4582-8057-099D1FBBF5EC}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; {4372BAAC-73EB-4BF5-9A5F-E4F106925C4E}; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; {61F2E4DF-60B7-4C8A-8BD9-98853FF61315}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; {85167A96-330B-4FA4-B250-90A9AA0F0FCF}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; {8D08774B-017A-4392-97D1-F9D354660A55}; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; ATLAS.SK_01; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Data Center; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2;;) [de]" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Deepnet Explorer 1.3.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; demne is my dog)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; digit_may2002; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; EFW TSC2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Feedreader; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; FunWebProducts-MyWay; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; FunWebProducts-MyWay; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; FunWebProducts; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Glazenzaal; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; GruppoMPS; Maxthon; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; H; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; i-NavFourF; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; i-NavFourF; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Infowalker v1.01; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; iTreeSurf 3.6.1 (Build 056); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; LCC Internal User - 010; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; LCC Internal User - 014; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Maxthon; .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Maxthon; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Maxthon; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Maxthon; (R1 1.5); .NET CLR 1.1.4322)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Maxthon; SV1; Deepnet Explorer 1.3.2; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "Maxthon" + major: '0' + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Moneysupermarket.com Financial Group; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; MyIE2; iTreeSurf 3.6.1 (Build 056); .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; MyIE2; Maxthon; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; MyIE2; .NET CLR 1.1.4322)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; MyIE2; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "MyIE2" + major: "0" + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; NetCaptor 7.5.0 Gold; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; NetCaptor 7.5.1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; NetCaptor 7.5.3; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40420)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; FDM)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; MSIECrawler)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40903)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.40301)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.40419)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.41115)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 2.0.31113;)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Poco 0.31; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Q312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Q321120; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; (R1 1.5); .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; (R1 1.5); .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SALT 1.0.0.0 1007 Developer; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; stumbleupon.com 1.923; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; TencentTraveler ; .NET CLR 1.1.4322; Alexa Toolbar)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Weybridge; .NET CLR 1.1.4322; .NET CLR 2.0.40903)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Win64)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Win64; AMD64)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Win64; x64; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Win64; x64; SV1; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; WOW64; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; WOW64; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; www.ASPSimply.com; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 6.0; .NET CLR 1.2.30703)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows XP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible;MSIE 6.0; Windows XP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows XP Professional Bot v.5.)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows 2000)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible;MSIE 6.0; Windows 3.11)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.0; T312461)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible;MSIE 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.40607)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.2)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 8.3; )" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Windows XP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (compatible;MSIE 6.0;Windows XP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 [de] (compatible; MSIE 6.0; Windows 98)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 [en] (compatible; MSIE 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/6.0 (compatible; MSIE 6.0; Windows 3.11 For workgroups; {6BD3E7C1-0732-43E8-8828-291A709CC070})" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "MSIE/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MSIE 6.0 (compatible; MSIE 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "MSIE 6.0 (compatible; MSIE 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "MSIE/6.0 (compatible; MSIE 6.0; Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "MSIE 6.0 (compatible; MSIE 6.0; Windows NT 5.1)/4.78 (TuringOS; Turing Machine; 0.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "MSIE 6.0)\" (MSIE 6.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "MSIE 6.0 (+MSIE 6.0; Windows NT 5.0; Q312461;; MSIE; Windows)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "MSIE 6.0 (Windows NT 5.1)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "MSIE/6.0 ( Windows NT 5.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MSIE/6.0 (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MSIE 6.0 (Win XP)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.01; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.02; Windows 98)" + family: "IE" + major: '6' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.3 (compatible; MSIE 6.2; Windows NT 6.0)" + family: "IE" + major: '6' + minor: '2' + patch: + - user_agent_string: "Mozilla/6.1 (compatible;MSIE 6.5; Windows 98)" + family: "IE" + major: '6' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 7.66; Windows NT 5.1; SV1)" + family: "IE" + major: '7' + minor: '66' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 7.66; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" + family: "IE" + major: '7' + minor: '66' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 8.0; Windows 94)(2000/08/12-2000/08/24)" + family: "IE" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)" + family: "IE" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 7.0a1; Windows NT 5.1; SV1; .NET CLR 1.1.4322; MS IdentiServ 1.4.12)" + family: "IE" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSXPLAYer2.014)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; MuscatFerret/1.6.3; claude@euroferret.com) via proxy gateway CERN-HTTPD/3.0 libwww/2.17" + family: "Other" + major: + minor: + patch: + - user_agent_string: "MVAClient" + family: "Other" + major: + minor: + patch: + - user_agent_string: "My Browser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; NCSA_Mosaic; windows; SV1; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NCSA_Mosaic/2.6 (X11;IRIX 4.0.5F IP12)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01 (compatible; Netbox/3.5 R92.5; Linux 2.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01 (compatible; NetBox/3.5 R92.3; Linux 2.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01 (compatible; Netbox/3.5 R93rc3; Linux 2.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01 (compatible; Netgem/3.6.7; netbox; Linux 2.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ZoneSurf/2.4 (BeOS; U; BeOS 5.0 BePC; en-US; 0.8)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; NetPositive/2.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; NetPositive/2.2.1; BeOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; NetPositive/2.2.2; BeOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; NetPositive/2.2.3; FreeBSD 5.2.1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "netscape (compatible; netscape; linux; SV1; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Netscape 7.0; Windows 98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Netscape 7.0; Windows NT 4.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible;Netscape 7.1; Windows 98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Netscape 7.3R; Windows 92)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 Netscape 7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (Netscape 4.79; Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.5; Windows NT 5.0) Netscape 7.1" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Netscape 4.08; Windows 98; DigExt)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible;Netscape 4.76 Mozilla 1.4;Linux 2.6.7)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Netscape 7.0; Windows 98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Netscape Gecko/20040803" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows XP; en-US; rv:1.7.5) Netscape 7.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-CA; rv:0.9.4) Gecko/20011128 Netscape 7.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113 Netscape 7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040626 Netscape Navigator 4.x/4.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.0.1) Gecko/20020921 BigBrother/Netscape6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/7.1 [en] (Windows NT 5.1; U)Netscape" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Navigator/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape 1.22 (Win16; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape 2.1 (compatible; MSIE 2.0B1; Windows for Workgroup 3.11; i386; en-US)" + family: "IE" + major: '2' + minor: '0' + patch: + - user_agent_string: "Netscape 4.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.04 [en]C-WNS2.5 (Wim95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.04 [en] (Win2000; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.04 [en] (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.04 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.04 [en] (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.04 [en] (X11; I; HP-UX B.10.20 9000/712)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.04 [en] (X11; I; SunOS 5.5.1 sun4m)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.04 (Linux i686; 1.7.3; Linux i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.05 [en] (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.05 [en] (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.05 [fr] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.05 (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.06 [en] (Direct Hit Grabber)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.06 [en] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.06 [en] (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.06 [en] (X11; U; Linux 2.0.27 i586)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.06 (Macintosh; I; PPC, Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.06 (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.07C-SGI [en] (X11; I; IRIX 6.5 IP32)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.07 [en] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.07 [en] (X11; I; Linux 2.0.36 i586)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.07 (X11; I; Nav; Linux 5.1.33 i586; )" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (Win16; I ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (Win16; U ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en](Win95; U; Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (Win98; I ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (Win98; U ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (Windows 3.11; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (WinNT; I ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (WinNT; U ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [en] (X11; U; Linux 2.4.9-34 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 [fr] (Win95; I ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 (Macintosh; U; PPC, Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.08 (PDA; PalmOS/sony/model atom/Revision:2.0.22 (en)) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.08 (PDA; PalmOS/sony/model atom/Revision:2.0.26 (de)) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.08 (PDA; PalmOS/sony/model luke/Revision:2.0.22 (en)) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.08 (PDA; PalmOS/sony/model luke/Revision:2.0.26 (de)) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.08 (PDA; PalmOS/sony/model prmr/Revision:2.0.22 (en)) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.08 (PDA; Windows CE/1.0.0) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.08 (PPC; Windows CE/1.0.0) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.08 (SmartPhone; Symbian OS-Series60/1.03) NetFront/3.2" + family: "NetFront" + major: '3' + minor: '2' + patch: + - user_agent_string: "Mozilla/4.1 (BEOS; U ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.1 [ja] (X11; I; Linux 2.2.13-33cmc1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.41 (BEOS; U ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [de] (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [en]C-AtHome0405 (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [en]C-CCK-MCD snapN45b1 (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [en]C-CCK-MCD (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [en] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [en] (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [en] (X11; I; Alpha 06; Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [en] (X11; I; IRIX64 6.5 IP30) Mozilla/4.08 [en] (Win95; I ;Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 [fr] (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 RPT-HTTPClient/0.3-2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 (Windows; U; Windows NT 5.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape/4.5 (WindowsNT;8-bit)" + family: "Netscape" + major: '4' + minor: '5' + patch: + - user_agent_string: "Netscape Navigator 4.5 (Windows; U; Windows NT 5.1; sl-SI; rv:1.4) Netscape/4.5" + family: "Netscape" + major: '4' + minor: '5' + patch: + - user_agent_string: "Mozilla/4.51C-ASML_1N06S [en] (X11; I; SunOS 5.8 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.51 [de]C-CCK-MCD DT (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.51 [de]C-CCK-MCD FS SBS (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.51 [de]C-CCK-MCD QXW03200 (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.51 [de]C-CCK-MCD QXW03200 (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.51 [de] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.51 [en]C-CCK-MCD (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.51 [en] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.6 [de]C-freenet 4.0 (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.6 [de] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.6 [en] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [de] (OS/2; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en]C-CCK-MCD (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en]C-CCK-MCD (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en] (OS/2; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en] (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en] (X11; I; Linux 2.2.13-33cmc1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en] (X11; I; Linux 2.4.25 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [en] (X11; U; ) - BrowseX (2.0.0 Windows)" + family: "BrowseX" + major: '2' + minor: '0' + patch: '0' + - user_agent_string: "Mozilla/4.61 [en] (X11; U; FreeBSD 4.9-RC i386)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 [ja] (X11; I; Linux 2.2.13-33cmc1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.61 (X11; )" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7C-CCK-MCD {C-UDP; EBM-APPLE} (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7C-CCK-MCD [en] (X11; I; SunOS 5.6 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [de]C-CCK-MCD 1&1 PureTec Edition 02/2000 (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [de]C-CCK-MCD QXW0322a (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [de]C-freenet 4.0 (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [de]C-SYMPA (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [de] (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [de] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [de] (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [de] (X11; Linux)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en]C-CCK-MCD EBM-Compaq1 (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en]C-CCK-MCD NSCPCD47 (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en]C-SYMPA (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en-gb] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en, US, en_US] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (X11; I; AIX 4.2)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (X11; I; HP-UX B.10.20 9000/782)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (X11; I; Linux 2.6.4 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (X11; I; OSF1 V4.0 alpha)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (X11; I; SunOS 5.8 i86pc)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [en] (X11; I; SunOS 5.8 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [fr]C-CCK-MCD C_ASPI_1_0 (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [fr] (WinNT; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [fr] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [ja] (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [ja] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 [ja] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (Macintosh; ppc)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (X11; Linux)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7x [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7x [en] (Win9x)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.71 [en]C-NECCK (Win95; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.71 [en] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.71 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.72 [en] (Win95; I) WebWasher 3.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.72 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.72 [en] (Win98; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.72 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.72 [en] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.72 [en] (X11; I; Linux 2.2.14 i586)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.72 (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73C-CCK-MCD VerizonDSL (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [de]C-CCK-MCD DT (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [de]C-CCK-MCD DT (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [de]C-CCK-MCD DT (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [de] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [en]C-SYMPA (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [en] (Windows NT 5.0; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.73 [en] (X11; U; Linux 2.2.19 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.74 [en]C-DIAL (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.74 [en] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.74 (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75C-CCK-MCD {C-UDP; EBM-APPLE} (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75C-CCK-MCD {C-UDP; EBM-APPLE} (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75C-CERN UNIX pcjinr02 45 [en] (X11; U; Linux 2.2.19-6.2.1.1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 compatible - Mozilla/5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [de]C-CCK-MCD DT (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [de]C-CCK-MCD QXW0325g (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [de] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en]C-CCK-MCD {C-UDP; VUT} (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en]C-CCK-MCD {Nokia} (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en]C-CCK-MCD (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en] (X11; U; Linux 2.2.16-22 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en] (X11; U; SunOS 5.6 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en] (X11; U; SunOS 5.7 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 [en] (X11; U; SunOS 5.8 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.75 (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 (000000000; 0; 000)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76C-SGI [en] (X11; I; IRIX 6.5 IP32)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en]C-bls40 (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en]C-CCK-MCD cf476 (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en]C-CCK-MCD (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (PalmOS; U; WebPro/3.0; Palm-Arzl)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; FreeBSD 5.2-RC i386)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; HP-UX B.11.00 9000/785)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; Linux 2.2.18 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; Linux 2.4.16 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; Linux 2.4.2-2 i586)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; Linux 2.4.2-2 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; OSF1 V5.1 alpha)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; SunOS 5.7 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; SunOS 5.8 i86pc)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; SunOS 5.8 sun4m)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 [en] (X11; U; SunOS 5.8 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76iC-CCK-MCD [en_US] (X11; U; AIX 4.3)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 (Macintosh; I; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 (Macintosh; I; PPC; Incompatible my ass! What if I don't want your jerky, elitist, ugly-assed css crap? Screw you!)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.76 (X11; U; Linux 2.6.3 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 (BeOS; U; BeOS BePC; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77C-CCK-MCD {C-UDP; EBM-APPLE} (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [de] (X11; U; Linux 2.2.19-SMP i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en]C-SYMPAL (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en]C-SYMPAL (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (X11; U; AIX 4.3)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (X11; U; Linux 2.2.19-6.2.1 i586)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (X11; U; Linux 2.4.2-2 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (X11; U; Linux 2.4.24 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (X11; U; Linux 2.4.27-c800-1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (X11; U; Linux 2.4.9-34 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.77 [en] (X11; U; SunOS 5.7 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78C-br_XT_4_78 [en] (X11; U; SunOS 5.8 i86pc; Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78C-CCK-MCD [en] (X11; U; HP-UX B.10.26 9000/785)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78C-CCK-MCD vg_472 [en] (X11; U; SunOS 5.8 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78C-ja [ja/Vine] (X11; U; Linux 2.4.22-0vl2.11 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [de]C-CCK-MCD DT (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [de] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [de] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [de] (X11; U; Linux 2.4.7-10 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (Win98; I) IBrowse/2.3 (MorphOS 1.4)" + family: "IBrowse" + major: '2' + minor: '3' + patch: + - user_agent_string: "Mozilla/4.78 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (X11; U; AIX 4.3)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (X11; U; Linux 2.2.13 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (X11; U; Linux 2.4.16-4GB i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (X11; U; Linux 2.4.7-10 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (X11; U; Linux 2.4.8-26mdk i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (X11; U; Linux 2.4.9-34 i686; Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (X11; U; SunOS 5.9 i86pc)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [en] (X11; U; SunOS 5.9 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [ja] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [ja] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.78 [uk] (WinME; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79C-Boeing UNIX Kit [en] (X11; U; SunOS 5.8 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79C-CCK-MCD [en] (X11; U; Linux 2.4.28-1-p4smp i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79C-CCK-MCD [en] (X11; U; SunOS 5.9 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79C-SGI [en] (X11; I; IRIX64 6.5 IP30)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79C-SGI [en] (X11; I; IRIX64 6.5 IP35)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79C-SGI [en] (X11; I; IRIX 6.5 IP32)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [de] (X11; U; Linux 2.2.20 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en]C-CCK-MCD {UMUC/CCKUS} (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (WinNT; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (X11; U; HP-UX B.11.00 9000/785)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (X11; U; Linux 2.2.12 i386)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (X11; U; Linux 2.4.18-3 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (X11; U; Linux 2.4.2 i386)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (X11; U; SunOS 5.8 sun4m)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (X11; U; SunOS 5.8 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (X11; U; SunOS 5.8 sun4u; Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 [en] (X11; U; SunOS 5.9 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.79 (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape 4.79" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 (AmigaOS 3.5; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8C-SGI [en] (X11; U; IRIX64 6.5 IP30)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8C-SGI [en] (X11; U; IRIX 6.5-ALPHA-1278921420 IP32)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8C-SGI [en] (X11; U; IRIX 6.5 IP32)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [de] (X11; U; Linux 2.6.4-52-default i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en]C-CCK-MCD EBM-Compaq (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en]C-CCK-MCD (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (Linux; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (MSIE; Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (Solaris)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (Win3.11; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (Win95; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (Win98; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (Windows NT 5.0; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (Windows NT 5.1; U) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (wouw)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; Linux 2.2.16-22 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; Linux 2.4.18-3smp i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; Linux 2.4.20-4GB i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; Linux 2.4.26 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; Linux 2.4.27-ow1 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; Linux 2.4.2 i386)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; Linux 2.4.2 i386; Nav)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; Linux 2.4.2 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [en] (X11; U; SunOS 5.8 sun4u)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [fr] (Windows NT 5.1; U)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 (Macintosh; U; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 [us] (X11; U; Linux 2.4.26 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.8 (Win)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.25 Netscape/5.0 (X11; U; IRIX 6.3 IP32)" + family: "Netscape" + major: '5' + minor: '0' + patch: + - user_agent_string: "Netscape/5.001 (windows; U; NT4.0; en-us) Gecko/25250101" + family: "Netscape" + major: '5' + minor: '001' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; m18) Gecko/20001108 Netscape6/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; m18) Gecko/20001108 Netscape6/6.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en; rv:1.0) Netscape/6.0" + family: "Netscape" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; m18) Gecko/20010131 Netscape6/6.01" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux 2.4.2-2 i586; en-US; m18) Gecko/20010131 Netscape6/6.01" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Linux 2.6.5) Gecko/20010726 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:0.9.2) Gecko/20010726 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1\"" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:7.01) Gecko/20010726 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.6) Gecko/20040206 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US) Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; HP-UX 9000/785; en-US; rv:1.6) Gecko/20020604 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:0.9.2) Gecko/20011002 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.5 (Windows; U; Windows NT 5.1; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape 6.1 (X11; I; Linux 2.4.18 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; Netscape6/6.2.1; Macintosh; en-US)" + family: "Netscape" + major: '6' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 Galeon/1.3.17 (X11; Linux i686; U;) Gecko/0-pie Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:0.9.4.1) Gecko/20020318 Netscape6/6.2.2" + family: "Netscape" + major: '6' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:0.9.4) Gecko/20011022 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:0.9.4) Gecko/20011130 Netscape6/6.2.1" + family: "Netscape" + major: '6' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; fr-FR; rv:0.9.4) Gecko/20011130 Netscape6/6.2.1" + family: "Netscape" + major: '6' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-CA; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-GB; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-GB; rv:0.9.4) Gecko/20011019 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.4) Gecko/20011019 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.4) Gecko/20011128 Netscape6/6.2.1" + family: "Netscape" + major: '6' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:0.9.4) Gecko/20011019 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-CA; rv:0.9.4) Gecko/20011128 Netscape6/6.2.1" + family: "Netscape" + major: '6' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3 (CK-SillyDog)" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.4) Gecko/20011019 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.4) Gecko/20011022 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; mag1001; rv:0.9.4) Gecko/20011019 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3 (ax)" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4) Gecko/20011019 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4) Gecko/20011128 Netscape6/6.2.1" + family: "Netscape" + major: '6' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; pl-PL; rv:1.7.6) Gecko/20050309 Netscape/6.2" + family: "Netscape" + major: '6' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-DE; rv:0.9.4) Gecko/20011128 Netscape6/6.2.1" + family: "Netscape" + major: '6' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:0.9.4.1) Gecko/20020314 Netscape6/6.2.2" + family: "Netscape" + major: '6' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT5.1; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4.1) Gecko/20020314 Netscape6/6.2.2" + family: "Netscape" + major: '6' + minor: '2' + patch: '2' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4) Gecko/20011022 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4) Gecko/20011126 Netscape6/6.2.1" + family: "Netscape" + major: '6' + minor: '2' + patch: '1' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4) Gecko/20020508 Netscape6/6.2.3" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv 1.3) Gecko/20030313 Netscape6/6.2.3_STRS" + family: "Netscape" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20011022 Netscape6/6.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape 6.2 (Macintosh; N; PPC; ja)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040803 Netscape6/6.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.5; Windows; NT 5.0) Netscape/7" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Netscape 7" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Netscape/7.0;)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-CA; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-GB; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-CMIL)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (nscd2)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; es-ES; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; mag0802; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.0.1) Gecko/20040823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-Friars!)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-LucentTPES)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-NGA)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-N_O_K_I_A)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0rc2) Gecko/20020512 Netscape/7.0b1" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0rc2) Gecko/20020618 Netscape/7.0b1" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; es-ES; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.0.1) Gecko/20020823 Netscape/7.0 (BDP)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.0.1) Gecko/20020823 Netscape/7.0 (BDP),gzip(gfe) (via translate.google.com)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-10527)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-4arcade)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-AAPT)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-FRS)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (CK-WICGR/MIT)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 (OEM-HPQ-PRS1C03)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.0 (NSEUPD V44 14.11.2003)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; AIX 000F384A4C00; en-US; rv:1.0.1) Gecko/20030213 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux 2.4.2-2 i586; en-US; m18) Gecko/20010131 Netscape7/7.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux-2.6.4-4GB i686; en-US; m18;) Gecko/20030624 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux; en-US; rv:1.0.1) Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0rc2) Gecko/20020513 Netscape/7.0b1" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4m; en-US; rv:1.0.1) Gecko/20020920 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.0.1) Gecko/20020719 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.0.1) Gecko/20020920 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.0.1) Gecko/20020921 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4a) Gecko/20020920 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; fr-FR; rv:1.0.1) Gecko/20020920 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4u; ja-JP; rv:1.0.1) Gecko/20020920 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; SunOS sun4us; en-US; rv:1.0.1) Gecko/20020920 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/7.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010726 Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "\"Netscape 7.0\"" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape/7.0" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Netscape/7.0 (BeOS 5; x86; NetServer; en-US) Gecko/20040604" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Netscape/7.0 [en] (Windows NT 5.1; U)" + family: "Netscape" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; ja-JP; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.01 (CK-FEL-IcD)" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01 (CK-Disanet)" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01 (CK-N_O_K_I_A)" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.01 (ax) (CK-SillyDog)" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01" + family: "Netscape" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; de-DE; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; fr-FR; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC; ja-JP; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-FR; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-CA; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-GB; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02 (ax)" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02 (CK-SillyDog)" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02 (CK-DNJ702R1)" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040617 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; fr-FR; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; pt-BR; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-CA; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02 (ax)" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02 (CK-MIT)" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02 (VAUSSU03)" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.0.2) Gecko/20030208 Netscape/7.02 (CK-Ifremer)" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US) Netscape7/7.02" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; fr-FR; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i386; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:1.0.2) Gecko/20030208 Netscape/7.02" + family: "Netscape" + major: '7' + minor: '02' + patch: + - user_agent_string: "Netscape 7.02" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.5; Windows NT 5.0) Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; X11; U; SunOS 5.8 sun4u) Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4) Gecko/20030624 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; ja-JP; rv:1.4) Gecko/20030624 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Netscape7.1; Windows NT 5.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; rv:1.4; U) Gecko/20030624 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U; de-DE; rv:1.4) Gecko/20030619 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; ja-JP; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:0.9.2) Gecko/20010726 Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.4) Gecko/20030619 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; Localization; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.2) Gecko/20010726 Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax; CDonDemand-Dom)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax; PROMO)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax) WebWasher 3.3" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; fr-FR; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; ja-JP; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; de-DE; rv:1.4) Gecko/20030619 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax; CDonDemand-Dom)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.4) Gecko/20030619 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.4) Gecko/20030619 Netscape/7.1 (CK-UKL)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010726 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010726 Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030603 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax; CDonDemand-Dom)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax) (CK-SillyDog)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax; PROMO)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 StumbleUpon/1.906 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040210 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707 Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.4) Gecko/20030619 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.2) Gecko/20010726 Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax; BDP)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax; CDonDemand-Dom)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax) (CK-SillyDog)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax; PROMO)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Mozilla; Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041204 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.7) Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Mozilla/5.0 (Windows; U; Win98; en-US; Localization; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)/0.10 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.4) Gecko/20030624 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 7.0; en-US; rv:1.7.3) Gecko/20040910 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; de-DE; rv:1.4) Gecko/20030619 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US) Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (CK-DNJ71R1)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.8a2) Gecko/20040527 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; fr-FR; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT; en-US; Localization; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; Windows NT 5.1; .NET CLR) Gecko/20030624 Netscape/7.1 (ax)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686) Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20030624 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040418 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux-2.6.4-4GB i686; en-US; m18;) Gecko/20030624 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (BDP)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031007 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040324 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040913 Netscape/7.1" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/7.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010726 Netscape7/7.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape/7.1 (compatible; Linux; X11; de_DE; U) [Firefox 0.8]" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Netscape/7.1 [de] (Windows NT 5.1; U)" + family: "Netscape" + major: '7' + minor: '1' + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 5.5; Windows NT 5.0; PPC Mac OS X; en-us) Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 [en] (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050204 Netscape/7.2 (PowerBook)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b) Gecko/20050208 Netscape/7.2 (PowerBook)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031007 Netscape/7.2e6/6.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (OpenBSD; en-US) Gecko/20030624 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; en-GB; rv:1.7.2) Gecko/20040804 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win95; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; Localization; rv:1.4) Gecko/20030624 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; nl-NL; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9.2) Gecko/20010726 Netscape7/7.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax) Mnenhy/0.6.0.104" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; sk-SK; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5) Gecko/20031007 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax [RLP])" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (Donzilla/0.2)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (Donzilla/0.6a)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (Donzilla/0.6a2)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 StumbleUpon/1.995 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040625 Netscape/7.2 (as)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040625 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.5) Gecko/20031007 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6 (Compatible with Netscape/7.2)) Gecko/20041027 Debian/1.6-5.1.0.45.lindows0.69" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040805 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041107 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050306 Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Netscape 7.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Netscape/7.2" + family: "Netscape" + major: '7' + minor: '2' + patch: + - user_agent_string: "Netscape 7.2 (X11; I; Linux 2.4.18 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2) Gecko/20050208 Netscape/7.20" + family: "Netscape" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Netscape/7.3 (ax)" + family: "Netscape" + major: '7' + minor: '3' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.6) Gecko/20050225 Netscape/8.0" + family: "Netscape" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win98; en-US; Localization; rv1.4) Gecko20030624 Netscape7.1 (ax)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; NetVisualize b202)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/2.0 (compatible; NEWT ActiveX; Win32)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Nintendo64/1.0 (SuperMarioOS with Cray-II Y-MP Emulation)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Nintendo64/1.7 (SuperMarioOS with Sun 15K Y-MP Emulation)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NoctBrowser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Nokia 6600" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3100/1.0 (04.01) Profile/MIDP-1.0 Configuration/CLDC-1.0" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3200/1.0 (4.18) Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3200/1.0 () Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3220/2.0 (03.30) Profile/MIDP-2.0 Configuration/CLDC-1.1 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3410" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3510i/1.0 (04.01) Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3510i/1.0 (04.01) Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Link/5.1.1.5a (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3510i/1.0 (04.44) Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3510i/1.0 (05.30) Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3650" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3650/1.0 (4.13) SymbianOS/6.1 Series60/1.2 Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3650/1.0 (4.17) SymbianOS/6.1 Series60/1.2 Profile/MIDP-1.0 Configuration/CLDC-1.0" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3650/1.0 SymbianOS/6.1 Series60/1.2 Profile/MIDP-1.0 Configuration/CLDC-1.0" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3650/1.0 SymbianOS/6.1 Series60/1.2 Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia3650/1.0 SymbianOS/6.1 Series60/1.2 Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Link/5.1.2.7 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6010/1.0 (8.18) Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6100" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6100/1.0 (05.16)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6100/1.0 (05.16) Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Link/1.1 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6100/1.0 (05.16) Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Link/mainline (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6600" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6600/1.0 (3.42.1) SymbianOS/7.0s Series60/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6600/1.0 (3.42.1) SymbianOS/7.0s Series60/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6600/1.0 (4.09.1) SymbianOS/7.0s Series60/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6600/1.0 (4.09.1) SymbianOS/7.0s Series60/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6600/1.0 SymbianOS" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6610/1.0 (5.63) Profile/MIDP-1.0 Configuration/CLDC-1.0" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6610I/1.0 (3.10) Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6610I/1.0 (3.10) Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Link/5.1.2.7 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6630" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6630/1.0 (3.45.113) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia6800" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia7250/1.0 (3.12) Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia7250/1.0 (3.14)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia7610/2.0 (3.0417.0ch) Symbian" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia7650" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "Nokia7650/1.0 SymbianOS/6.1 Series60/0.9 Profile/MIDP-1.0 Configuration/CLDC-1.0 (Google WAP Proxy/1.0)" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "NokiaN-Gage/1.0 (4.03) SymbianOS/6.1 Series60/0.9 Profile/MIDP-1.0 Configuration/CLDC-1.0" + family: "Nokia Services (WAP) Browser" + major: + minor: + patch: + - user_agent_string: "NP/0.1 (NP; http://www.nameprotect.com; npbot@nameprotect.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.01 (compatible; NPT 0.0 beta)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS/0.01-beta (Nutch; http://www.nutch.org/docs/en/bot.html; nutch-agent@lists.sourceforge.net)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS/0.03-dev (Nutch; http://www.nutch.org/docs/bot.html; nutch-agent@lists.sourceforge.net)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS/0.03-dev (Nutch; http://www.nutch.org/docs/en/bot.html; nutch-agent@lists.sourceforge.net)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS/0.06-dev (bot; http://www.nebel.de:8080/en/bot.html; nutch-agent@nebel.de)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS/0.06-dev (bot; http://www.nebel.de/bot.html; nutch-agent@nebel.de)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS/0.06-dev (Nutch; http://www.nutch.org/docs/en/bot.html; jagdeepssandhu@hotmail.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS/0.06-dev (Nutch; http://www.nutch.org/docs/en/bot.html; nutch-agent@lists.sourceforge.net)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchCVS/0.06-dev (Nutch; http://www.s14g.com/en/search.html; travelbot@s14g.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NutchOSUOSL/0.05-dev (Nutch; http://www.nutch.org/docs/en/bot.html; nutch-agent@lists.sourceforge.net)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Nutscrape/1.0 (CP/M; 8-bit)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Nutscrape/9.0 (CP/M; 8-bit)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SEC-SGHC225-C225UVDH1-NW.Browser3.01 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "NWSpider 0.9" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ObjectsSearch/0.01 (ObjectsSearch; http://www.ObjectsSearch.com/bot.html; support@thesoftwareobjects.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ObjectsSearch/0.06 (ObjectsSearch; http://www.ObjectsSearch.com/bot.html; support@thesoftwareobjects.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ObjectsSearch/0.07 (ObjectsSearch; http://www.ObjectsSearch.com/bot.html; support@thesoftwareobjects.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (compatible; OffByOne; Windows 2000)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (compatible; OffByOne; Windows 2000) Webster Pro V3.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (compatible; OffByOne; Windows 2000) Webster Pro V3.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (compatible; OffByOne; Windows 98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (compatible; OffByOne; Windows 98) Webster Pro V3.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.7 (compatible; OffByOne; Windows NT 4.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.5 (compatible; OmniWeb/4.1.1-v423; Mac_PowerPC)" + family: "OmniWeb" + major: '4' + minor: '1' + patch: '1' + - user_agent_string: "Mozilla/4.5 (compatible; OmniWeb/4.3-v435; Mac_PowerPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Opera" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Opera/ (X11; Linux i686; U) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (BeOS R4.5;US) Opera 3.60 [en]" + family: "Opera" + major: '3' + minor: '60' + patch: + - user_agent_string: "Mozilla/3.0 (Windows 3.10;US) Opera 3.62 [en]" + family: "Opera" + major: '3' + minor: '62' + patch: + - user_agent_string: "Mozilla/4.71 (Windows 3.10; US) Opera 3.62 [en]" + family: "Opera" + major: '3' + minor: '62' + patch: + - user_agent_string: "Mozilla/4.71 (Windows 3.10;US) Opera 3.62 [en]" + family: "Opera" + major: '3' + minor: '62' + patch: + - user_agent_string: "Mozilla/4.71 (Windows 98;US) Opera 3.62 [en]" + family: "Opera" + major: '3' + minor: '62' + patch: + - user_agent_string: "Mozilla/4.72 (Windows 98;US) Opera 4.0 Beta 3 [en]" + family: "Opera" + major: '4' + minor: '0' + patch: + - user_agent_string: "Opera/4.02 (Windows 98; U) [en]" + family: "Opera" + major: '4' + minor: '02' + patch: + - user_agent_string: "Opera/4.03 (Windows NT 4.0; U)" + family: "Opera" + major: '4' + minor: '03' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh;US;PPC) Opera 5.0 [en]" + family: "Opera" + major: '5' + minor: '0' + patch: + - user_agent_string: "Opera/5.01 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '5' + minor: '01' + patch: + - user_agent_string: "Opera/5.02 (alpha 06; AmigaOS) [en]" + family: "Opera" + major: '5' + minor: '02' + patch: + - user_agent_string: "Opera/5.02 (Windows 98; U) [en]" + family: "Opera" + major: '5' + minor: '02' + patch: + - user_agent_string: "Opera/5.02 (Windows 98; U) [en]" + family: "Opera" + major: '5' + minor: '02' + patch: + - user_agent_string: "Opera/5.02 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '5' + minor: '02' + patch: + - user_agent_string: "Opera/5.02 (X11; U; Linux i686; en-US)" + family: "Opera" + major: '5' + minor: '02' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 5.12 [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 5.12 [es]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) Opera 5.12 [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 5.12 [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 5.12 [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1) Opera 5.12 [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 98; U) Opera 5.12 [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 98; U) Opera 5.12 [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Opera/5.12 (Windows 2000; U) [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Opera/5.12 (Windows 98; U) [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Opera/5.12 (Windows NT 4.0; U) [fr]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Opera/5.12 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '5' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Linux 2.4.18-4GB i686) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Linux 2.4.18-4 i686) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Linux) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC) Opera 6.0 [ja]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Symbian OS; Series 90) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows ME; U) Opera 6.0 [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Opera/6.00 (Windows 98; U) [en]" + family: "Opera" + major: '6' + minor: '00' + patch: + - user_agent_string: "Opera/6.0 (Macintosh; PPC Mac OS X; U) [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Opera/6.0 (Windows 2000; U) [de]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Opera/6.0 (Windows 2000; U) [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Opera/6.0 (Windows 2000; U) [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Opera/6.0 (Windows 98; U) [en]" + family: "Opera" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.01 [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.01 [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.01 [es]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 6.01 [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0) Opera 6.01 [en] WebWasher 3.3" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.01 [de]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.01 [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.01 [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.01 [es]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.78 (Windows 2000; U) Opera 6.01 [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/5.0 (Windows XP; U) Opera 6.01 [en]\"" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Opera/6.01 (Windows 2000; U) [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Opera/6.01 (Windows ME; U) [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Opera/6.01 (Windows XP; U) [en]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Opera/6.01 (Windows XP; U) [ru]" + family: "Opera" + major: '6' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.02 [en]" + family: "Opera" + major: '6' + minor: '02' + patch: + - user_agent_string: "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS) Opera 6.02 [en]" + family: "Opera" + major: '6' + minor: '02' + patch: + - user_agent_string: "Mozilla/5.0 (Linux 2.4.26 i586; U) Opera 6.02 [en]" + family: "Opera" + major: '6' + minor: '02' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Linux 2.4.24 i686) Opera 6.03 [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Linux) Opera 6.03 [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.03 [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.03 [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Opera/6.03 (Linux 2.4.19-64GB-SMP i686; U) [de]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Opera/6.03 (Linux 2.4.19 i686; U) [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Opera/6.03 (OpenBSD 3.2 i386; U) [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Opera/6.03 (Windows 2000; U) [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Opera/6.03 (Windows 98; U) [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Opera/6.03 (Windows ME; U) [ja]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Opera/6.03 (Windows XP; U) [en]" + family: "Opera" + major: '6' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.04 [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.04 [en-GB]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.04 [en-GB]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 6.04 [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.04 [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 98; U) Opera 6.04 [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Opera/6.04 (Windows 2000; U) [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Opera/6.04 (Windows 2000; U) [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Opera/6.04 (Windows 2000; U) [en-GB]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Opera/6.04 (Windows 98; U) [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Opera/6.04 (Windows 98; U) [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Opera/6.04 (Windows 98; U) [en-GB]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Opera/6.04 (Windows XP; U) [en]" + family: "Opera" + major: '6' + minor: '04' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.05 [de]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.05 [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.05 [it]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.05 ~ [~ [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.05 [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.05 [es]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.05 OCV2 [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0) Opera 6.05 [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.05 [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.05 [hu]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 2000; U) Opera 6.05 [de]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/5.0 (Windows XP; U) Opera 6.05 [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Opera/6.05 (Windows 2000; U) [de]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Opera/6.05 (Windows 2000; U) [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Opera/6.05 (Windows 98; U) [de]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Opera/6.05 (Windows 98; U) [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Opera/6.05 (Windows 98; U) [en] WebWasher 3.0" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Opera/6.05 (Windows XP; U) [de]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Opera/6.05 (Windows XP; U) [en]" + family: "Opera" + major: '6' + minor: '05' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.06 [de]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.06 [en]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.06 [bg]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.06 [en]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) Opera 6.06 [en] (www.proxomitron.de)" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.06 [en]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 2000; U) Opera 6.06 [en]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Opera/6.06 (Windows 2000; U) [en]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Opera/6.06 (Windows 98; U) [de]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Opera/6.06 (Windows 98; U) [en]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Opera/6.06 (Windows 98; U) [en] (www.proxomitron.de)" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Opera/6.06 (Windows XP; U) [en]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Opera/6.06 (Windows XP; U) [ja]" + family: "Opera" + major: '6' + minor: '06' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Linux 2.4.2 i386) Opera 6.1 [en]" + family: "Opera" + major: '6' + minor: '1' + patch: + - user_agent_string: "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS; Nokia 6600;423) Opera 6.10 [de]" + family: "Opera" + major: '6' + minor: '10' + patch: + - user_agent_string: "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS; Nokia 7650;424) Opera 6.10 [de]" + family: "Opera" + major: '6' + minor: '10' + patch: + - user_agent_string: "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS; Series 60;424) Opera 6.10 [en]" + family: "Opera" + major: '6' + minor: '10' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; FreeBSD 4.4-RELEASE i386) Opera 6.11 [en]" + family: "Opera" + major: '6' + minor: '11' + patch: + - user_agent_string: "Mozilla/5.0 (UNIX; U) Opera 6.11 [en]" + family: "Opera" + major: '6' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; FreeBSD 5.3-RC2 i386) Opera 6.12 [en]" + family: "Opera" + major: '6' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; Linux 2.4.22 i686) Opera 6.12 [en]" + family: "Opera" + major: '6' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; UNIX) Opera 6.12 [en]" + family: "Opera" + major: '6' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.78 (FreeBSD 5.0-RELEASE-p7 i386; U) Opera 6.12 [en]" + family: "Opera" + major: '6' + minor: '12' + patch: + - user_agent_string: "Opera/6.12 (FreeBSD 4.8-RELEASE i386; U) [en]" + family: "Opera" + major: '6' + minor: '12' + patch: + - user_agent_string: "Opera/6.12 (UNIX; U) [en]" + family: "Opera" + major: '6' + minor: '12' + patch: + - user_agent_string: "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS; Nokia 6600;451) Opera 6.20 [en]" + family: "Opera" + major: '6' + minor: '20' + patch: + - user_agent_string: "Opera/7 (Windows 98; U) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Opera/7.x (compatible; Konqueror/2.2.2; Linux 2.8.4-rc1; X11; i686)" + family: "Konqueror" + major: '2' + minor: '2' + patch: '2' + - user_agent_string: "Opera/7.x (Windows NT 5.1; U) [hr]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0(DDIPOCKET;KYOCERA/AH-K3001V/1.1.17.65.000000/0.1/C100) Opera 7.0" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows 2000) Opera 7.0 [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows 98) Opera 7.0 [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.0 [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.0 [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows XP) Opera 7.0 [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 Opera/7.0 (X11; U; Linux i686; de-DE; rv:1.6) Gecko/20040114" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 2000; U) Opera 7.0 [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Opera/7.00 (Windows NT 5.0; U)" + family: "Opera" + major: '7' + minor: '00' + patch: + - user_agent_string: "Opera/7.0 (Windows 2000; U) [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Opera/7.0 (Windows 2000; U) [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Opera/7.0 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows 98) Opera 7.01 [en]" + family: "Opera" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows 98) Opera 7.01 [ru]" + family: "Opera" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows ME) Opera 7.01 [en]" + family: "Opera" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.01 [en]" + family: "Opera" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.01 [en]" + family: "Opera" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.01 [ru]" + family: "Opera" + major: '7' + minor: '01' + patch: + - user_agent_string: "Opera/7.01 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '01' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows 98) Opera 7.02 [en]" + family: "Opera" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows ME) Opera 7.02 [en]" + family: "Opera" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.02 [en]" + family: "Opera" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.02 [en]" + family: "Opera" + major: '7' + minor: '02' + patch: + - user_agent_string: "Opera/7.02 Bork-edition (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '02' + patch: + - user_agent_string: "Opera/7.02 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '02' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows 98) Opera 7.03 [en]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.03 [en]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.03 [ja]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.03 [en]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.03 [ru]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Opera/7.03 (Windows 98; U) [en]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Opera/7.03 (Windows NT 5.0; U) [de]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Opera/7.03 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Opera/7.03 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Opera/7.03 (Windows NT 5.0; U) [nl]" + family: "Opera" + major: '7' + minor: '03' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.10 [en]" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.10 [en]" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.10 [en]" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Opera/7.10 (Linux 2.4.20 i686; U) [en]" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Opera/7.10 (Windows ME; U) [en]" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Opera/7.10 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Opera/7.10 (Windows NT 5.0; U) [en] (www.proxomitron.de)" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Opera/7.10 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Opera/7.10 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '10' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Linux 2.4.18-bf2.4 i686) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Linux 2.4.20-8 i686) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Linux 2.4.26 i686) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Linux 2.4.2 i386) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Linux 2.6.6 i686) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.11 [es]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.11 [de]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.11 [es-ES]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.11 [pl]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.11 [ru]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/5.0 (Linux 2.4.20-openmosix-3 i686; U) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.11 [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Linux 2.4.18-xfs i686; U) [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Linux 2.4.20-gentoo-r1 i686; U) [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Linux 2.6.3-4mdk i686; U) [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows 98; U) [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.0; U) [es]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.0; U) [it]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.0; U) [pl]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.0; U) [ru]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.1; U) [es]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Opera/7.11 (Windows NT 5.2; U) [en]" + family: "Opera" + major: '7' + minor: '11' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 95) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.20 [ja]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.20 [ru]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.20 [ja]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.20 [ru]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.20 [de]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.20 [sk]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.1; U) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 98; U) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.20 [ja]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.20 [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Opera/7.20 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Opera/7.20 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Opera/7.20 (Windows NT 5.1; U) [røv]" + family: "Opera" + major: '7' + minor: '20' + patch: + - user_agent_string: "Mozilla/3.0 (Windows 98; U) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.21 [pl]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.21 [fi]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.21 [de]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.21 [pl]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.21 [ru]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.21 [zh-cn]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i586) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.1; U) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.21 [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Opera/7.21 (Windows 98; U) [de]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Opera/7.21 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Opera/7.21 (Windows NT 5.0; U) [it]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Opera/7.21 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Opera/7.21 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Opera/7.21 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Opera/7.21 (Windows NT 5.1; U) [fi]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Opera/7.21 (Windows NT 5.2; U) [en]" + family: "Opera" + major: '7' + minor: '21' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.22 [en]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.22 [en]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.22 [en]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.22 [fr]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.22 [pl]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.22 [de]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.22 [en]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.22 [es-ES]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.22 [en]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.22 [fr]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.22 [de]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Opera/7.22 (Windows NT 5.0; U) [de] WebWasher 3.3" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Opera/7.22 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Opera/7.22 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Opera/7.22 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Opera/7.22 (X11; Linux i686; U) [en]" + family: "Opera" + major: '7' + minor: '22' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Linux) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.23 [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.23 [en-GB]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.23 [es-ES]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.23 [es-LA]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.23 [hu]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.23 [nl]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.23 [en] WebWasher 3.3" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.23 [es-LA]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.23 [pl]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.23 [ru]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.23 [fr]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [en-GB]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [es-ES]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [fr]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [it]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [ja]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [nb]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [pl]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [ru]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.23 [sv]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [cs]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [en-GB]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [es-ES]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [es-LA]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [fr]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [it]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [ja]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [nb]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [nl]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [pl]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [pt-BR]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [ru]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [sv]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [zh-cn]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.23 [zh-tw] WebWasher 3.3" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.23 [pl]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.23 [ru]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; FreeBSD i386) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.23 [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.23 [es-ES]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.23 [ru]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; SunOS sun4u) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; SunOS sun4u) Opera 7.23 [ja]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 4.0; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.0; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.78 (X11; FreeBSD i386; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Opera 7.23; Windows NT 5.1)" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 98; U) Opera 7.23 [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 98; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 98; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Windows ME; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.23 [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.23 [et]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (X11; FreeBSD i386; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.23 [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.23 [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (compatible; MSIE 6.0; X11; Linux i586) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Linux 2.4.24-ck1 i686; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows 98; U) [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows 98; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows 98; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows ME; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 4.0; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U)" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U) [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U) [en-GB]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U) [es-ES]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U) [es-LA]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U) [pl]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U) [ru]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.0; U) [tr]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [cs]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [da]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [en-GB]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [es]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [es-LA]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [fi]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [fr]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [ja]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [pl]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [ru]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [sv]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [tr]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.1; U) [zh-tw]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (Windows NT 5.2; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; FreeBSD i386; U) [bg]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; Linux i386; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; Linux i686; U) [de]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; Linux i686; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; Linux i686; U) [en-GB]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; Linux i686; U) [es-ES]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; Linux i686; U) [fi]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; Linux i686; U) [sv]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Opera/7.23 (X11; SunOS sun4u; U) [en]" + family: "Opera" + major: '7' + minor: '23' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Qt embedded; Linux armv5tel; 640x480) Opera 7.30 [en]" + family: "Opera" + major: '7' + minor: '30' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Opera 7.30; Irax)" + family: "Opera" + major: '7' + minor: '30' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.0; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/3.0 (X11; SunOS sun4u; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Mac_PowerPC) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 2000; Opera 7.50 [en])" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.50 [ru]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.50 [ru]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.50 [sv]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.50 [de]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.50 [IT]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.50 [pl]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.50 [ru]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.50 [de] (www.proxomitron.de)" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; FreeBSD i386) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.50 [es-ES]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; SunOS sun4u) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.78 (Windows 98; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.0; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.1; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/4.78 (X11; Linux i686; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.50 [ru]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.50 [ru]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/5.0 (X11; FreeBSD i386; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.50 [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.50 [es-LA]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Macintosh; U; PPC Mac OS X 10.3.3; en-US; rv:1.1 ) via HTTP/1.0 offshore.unitedbanks.org/" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows 95; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows 98; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows 98; U) [en-US]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.0; U) [cs]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.0; U) [pl]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.0; U) [ru]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.1; U) [en-GB]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.1; U) [pl]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (Windows NT 5.2; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (X11; FreeBSD i386; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Opera/7.50 (X11; Linux i686; U) [en]" + family: "Opera" + major: '7' + minor: '50' + patch: + - user_agent_string: "Mozilla/3.0 (X11; Linux i686; U) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.51 [cs]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.51 [ru]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; FreeBSD i386) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.51 [de]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux ppc) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.1; U) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.78 (X11; Linux i686; U) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/5.0 (Windows ME; U) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.51 [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Linux) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Mac_PowerPC; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows 95; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows 98; U) [de]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows 98; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows ME; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows NT 4.0; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows NT 5.0; U) [de]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows NT 5.1; U) [fr]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (Windows NT 5.1; U) [pl]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (X11; Linux i686; U) [de]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (X11; Linux i686; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (X11; Linux i686; U) [fi]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Opera/7.51 (X11; SunOS sun4u; U) [en]" + family: "Opera" + major: '7' + minor: '51' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.52 [pl]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.52 [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.52 [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.52 [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; FreeBSD i386) Opera 7.52 [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.52 [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Mozilla/4.78 (X11; Linux i686; U) Opera 7.52 [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.52 [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Macintosh; PPC Mac OS X; U) [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.0; U) [en] WebWasher 3.3" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.1; U) [nb]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.1; U) [pl]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (Windows NT 5.2; U) [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Opera/7.52 (X11; Linux i686; U) [en]" + family: "Opera" + major: '7' + minor: '52' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.53 [da]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.53 [ja]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.53 [de]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.53 [es-ES]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.53 [ja]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; FreeBSD i386) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.0; U) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.1; U) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.53 [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (Windows NT 5.0; U) [de]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (Windows NT 5.0; U) [ja]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (Windows NT 5.1; U) [ja]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (Windows XP; U) [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Opera/7.53 (X11; Linux i686; U) [en]" + family: "Opera" + major: '7' + minor: '53' + patch: + - user_agent_string: "Mozilla/3.0 (Windows 98; U) Opera 7.54 [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.0; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.1; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.1; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.1; U) Opera 7.54 [es-ES]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.1; U) Opera 7.54 [sv]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.1; U) Opera 7.54u1 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC) Opera 7.54u1 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 95) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.54 [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.54 [fr]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.54 [nb]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.54 [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.54u1 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Opera 7.54u1 [nl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.54u1 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME) Opera 7.54u1 [hu]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54 [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54 [es-ES]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54 [fi]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54 [fr]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54 [IT]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54 [ja]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54 [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54u1 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54u1 [fr]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.54u1 [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [bg]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [cs]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [da]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [de],gzip(gfe) (via translate.google.com)" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [es-ES]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [et]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [fi]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [fr]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [hu]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [it]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [IT]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [nb]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [nl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54 [pt-BR]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54u1 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54u1 [ja]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.54u1 [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2) Opera 7.54u1 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; FreeBSD i386) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; FreeBSD i386) Opera 7.54 [ru]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.54 [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686) Opera 7.54 [it]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; SunOS sun4u) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.1; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/4.78 (X11; Linux i686; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; PPC Mac OS X; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows 98; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows ME; U) Opera 7.54 [ja]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.54 [it]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.54u1 [en] WebWasher 3.0" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.54 [ca]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.54 [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.54 [sv]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.54u1 [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.54u1 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (X11; FreeBSD i386; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U) Opera 7.54 [fr]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux x86_64; U) Opera 7.54 [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Amiga) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (AmigaOS 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (FreeBSD; U)" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Linux 2.4.18-xfs i686; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Linux) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Macintosh; PPC Mac OS X; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera 7.54 (Macintosh; U; PPC Mac OS X v10.4 Tiger ) via HTTP/1.0 deep.space.star-travel.org/" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows 98; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows 98; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows ME; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 4.0; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 4.0; U) [en] WebWasher 2.2.1" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.0; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.0; U) [ja]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.1; U) [hu]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.1; U) [ja]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.1; U) [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.1; U) [pt-BR]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows NT 5.2; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54u1 (Windows; U)" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Unix; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows 95; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows 98; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows 98; U) [es-ES]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows 98; U) [hu]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows 98; U) [nl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows 98; U) [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows ME; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows ME; U) [es-ES]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 4.0; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 4.0; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 4.0; U) [es-ar]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [fi]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [fr]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U; have a nice day :) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U; have a nice day;) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [ja]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.0; U) [sv]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1)" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [cs]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [es-ES]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [fr]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [hu]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [it]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [IT]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [nb]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [nl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [ru]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows NT 5.1; U) [sv]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (Windows; U)" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; FreeBSD i386; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i386; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i586; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i686; U)" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i686; U) [cs]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i686; U) [de]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i686; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i686; U) [nl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i686; U) [pl]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; Linux i686; U) [sv]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; SunOS sun4u; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; SunOS sun4u; U) [en]" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Opera/7.54 (X11; U; Linux i686; fr-FR; rv:1.5)" + family: "Opera" + major: '7' + minor: '54' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.1; U) Opera 7.60 [de] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/3.0 (Windows NT 5.1; U) Opera 7.60 [en] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; en) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; en) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; es) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.60 [en]" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.60 [en] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.60 [nl] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; pl) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; en) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; IT) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.1; U) Opera 7.60 [de] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.78 (Windows NT 5.1; U) Opera 7.60 [en] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U) Opera 7.60 [en] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U; pl) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U; en) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.60 [de] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U) Opera 7.60 [en] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U; pl) Opera 7.60" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera 7.60 (FreeBSD i686; U) [en] via HTTP/1.0 foot.fetish-expert.org/" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera 7.60 (Linux 2.4.10-4GB i686; U)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera 7.60 (Linux 2.4.8-26mdk i686; U) [en] FreeSurf tmfweb.nl v1.1 via HTTP/1.0 vienna.unitedworldcouncil.org/" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 preview 4 (Mac OS X 10.3)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows 98; U; pl)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera 7.60 (Windows NT 4.0; U) [en] via HTTP/1.0 l33t0-HaX0r.hiddenip.com/" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.0; U; en)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.0; U; ja)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.0; U; ja),gzip(gfe) (via translate.google.com)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.0; U; pl)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.1; U; de)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.1; U) [de] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.1; U; en)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.1; U) [en] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.1; U) [pl]" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.1; U) [pl] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.2; U; en)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.2; U) [en] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (Windows NT 5.2; U) [en] (IBM EVV/3.0/EAK01AG9/LE)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera 7.60 (X11; Linux i386; U) [en] via HTTP/1.0 evil-uncle.trojanchecker.com/" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (X11; Linux i686; U; en)" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Opera/7.60 (X11; Linux i686; U) [en]" + family: "Opera" + major: '7' + minor: '60' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Mac_PowerPC Mac OS X; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows ME; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; de) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; en) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; cs) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; de) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; hu) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; en) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; IT) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; pl) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux ppc; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.0; U; ru) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/5.0 (Windows NT 5.1; U; en) Opera 8.00" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Mozilla/5.0 (X11; Linux i686; U; en) Opera 8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.00 (Windows 98; U; de)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.0; U)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.0; U; de)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.0; U; en)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.0; U; pl)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.1; U; bg)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.1; U; cs)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.1; U; de)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.1; U; en)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.1; U; es)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.1; U; Mockingbird)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows NT 5.2; U; en)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.00 (Windows; U)" + family: "Opera" + major: '8' + minor: '00' + patch: + - user_agent_string: "Opera/8.0 (Macintosh; PPC Mac OS X; U; en)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (Windows 98; U; en)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (Windows ME; U; en)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (Windows NT 5.0; U; en)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (Windows NT 5.1; U; de)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (Windows NT 5.1; U; en)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (Windows NT 5.1; U; pl)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (Windows NT 5.2; U; en)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (X11; Linux i686; U; en)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Opera/8.0 (X11; Linux i686; U; pt-BR)" + family: "Opera" + major: '8' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Opera 8.4; Windows ME; Maxthon; .NET CLR 1.1.4322)" + family: "Opera" + major: '8' + minor: '4' + patch: + - user_agent_string: "Operah" + family: "Other" + major: + minor: + patch: + - user_agent_string: "OZ Browser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "P3P Client" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PenguinFear (compatible; windows ce;; Windows NT 5.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PHILIPS-Fisio311/2.1 UP/4.1.19m" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PHP/4.2.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PHP/4.2.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PhpDig/PHPDIG_VERSION (+http://www.phpdig.net/robot.php)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PHP version tracker" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (compatible; MSIE 6.0; Pike HTTP client) Pike/7.6.25" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "PinkSock/1.0 (eComStation 1.2; en-CA; rv:0.4.9) PinkSock/20040416" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PinkSock/1.1 [en] (X11; U; SunOS 5.9 i86)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PinkSock/1.2 [en_CA] (OpenBeOS 0.2 i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PinkSock/1.3 [en_CA] (X11; U; SunOS 5.10 i86)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PinkSock/1.4 [en_CA] (16-bit; U; DR-DOS 7.22)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "PinkSock/1.5 [en_CA] (X11R6.7.0; U; FreeBSD 4.10-RELEASE)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "pipeLiner/0.10 (PipeLine Spider; http://www.pipeline-search.com/webmaster.html)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "POE-Component-Client-HTTP/0.510 (perl; N; POE; en; rv:0.510)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Popdexter/1.0 (http://www.popdex.com/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "portalmmm/2.0_M341i(c10;TB)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Powermarks/3.5; Windows 95/98/2000/NT)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Privoxy/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Privoxy/3.0 (Anonymous)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Program Shareware 1.0.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Progressive Download" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Proxomitron (www.proxomitron.de)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "puf/0.93.2a (Linux 2.4.20-19.9; i686)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Python-urllib/1.15" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Python-urllib/2.0a1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Python-urllib/2.0a1, Dowser/0.26 (http://dowser.sourceforge.net)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Qarp-1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ReadAheadWebBrowserHost" + family: "Other" + major: + minor: + patch: + - user_agent_string: "RealDownload/4.0.0.40" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Reaper/2.07 (+http://www.sitesearch.ca/reaper)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "RPT-HTTPClient/0.3-3E" + family: "Other" + major: + minor: + patch: + - user_agent_string: "RT-browser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SA/0.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Safari" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/01 (KHTML, like Gecko) Safari/01" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; cs-cz) AppleWebKit/103u (KHTML, like Gecko) Safari/100" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/103u (KHTML, like Gecko) Safari/100" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (macintosh; U; PPC mac OS X; en) AppleWebKit/103u (KHTML, like Gecko) Safari/100" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/103u (KHTML, like Gecko) Safari/100" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/103u (KHTML, like Gecko) Safari/100" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/103u (KHTML, like Gecko) Safari/100" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/106.2 (KHTML, like Gecko) Safari/100" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/103u (KHTML, like Gecko) Safari/100" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/103u (KHTML, like Gecko) Safari/100.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/106.2 (KHTML, like Gecko) Safari/100.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/106.2 (KHTML, like Gecko) Safari/100.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es-es) AppleWebKit/106.2 (KHTML, like Gecko) Safari/100.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Safari 1.2 (Macintosh; U; PPC Mac OS X; en-us)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/124 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/146.1 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/124 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5.7 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/185 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/124 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-au) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-gb) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es-es) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fi-fi) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; is-is) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.11" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; el-gr) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.11" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.11" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.11" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es-es) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.11" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.11" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.11" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.11" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; da-dk) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-at) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.7 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5.7 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-au) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-au) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-ca) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-ca) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-gb) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-gb) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5.7 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es-es) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es-es) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-ca) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.5.7 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; he-il) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; is-is) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/125.5.7 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; no-no) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/125.5.7 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; th-th) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; zh-tw) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; zh-tw) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-gb) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (000000000; 0; 000 000 00 0; 00) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-gb) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.2.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es-es) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; is-is) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ru-ru) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.4.2 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.5 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/125.5 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/125.5 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/125.5 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; is-is) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/125.5 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/125.5 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; no-no) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; pt-pt) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/125.4 (KHTML, like Gecko) Safari/125.9" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/175 (KHTML, like Gecko) Safari/1.3" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/146.1 (KHTML, like Gecko) Safari/146" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/146 (KHTML, like Gecko) Safari/146" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-gb) AppleWebKit/146.1 (KHTML, like Gecko) Safari/146" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/146.1 (KHTML, like Gecko) Safari/146" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es) AppleWebKit/146.1 (KHTML, like Gecko) Safari/146" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/146.1 (KHTML, like Gecko) Safari/146" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/146.1 (KHTML, like Gecko) Safari/146" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/164 (KHTML, like Gecko) Safari/164" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/168 (KHTML, like Gecko) Safari/168" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-gb) AppleWebKit/168 (KHTML, like Gecko) Safari/168" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/168 (KHTML, like Gecko) Safari/168" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/168 (KHTML, like Gecko) Safari/168" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/168 (KHTML, like Gecko) Safari/168" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/172 (KHTML, like Gecko) Safari/172" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/176 (KHTML, like Gecko) Safari/176" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/179 (KHTML, like Gecko) Safari/179" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/185 (KHTML, like Gecko) Safari/185" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/401 (KHTML, like Gecko) Safari/401" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/403 (KHTML, like Gecko) Safari/403" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/405 (KHTML, like Gecko) Safari/405" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/412 (KHTML, like Gecko) Safari/412" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/48 (like Gecko) Safari/48" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/64 (KHTML, like Gecko) Safari/64" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/73 (KHTML, like Gecko) Safari/73" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/85 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.8.5 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/85 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/85 (KHTML, like Gecko) Safari/85" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.5" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.5" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.5" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.5" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Windows; U; Win16; en-US; rv:1.7) Safari/85.5" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.6" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.6" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.6" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.6" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-au) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-gb) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; it-it) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.7" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-au) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/225 (KHTML, like Gecko) Safari/85.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; es) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/85.8.5 (KHTML, like Gecko) Safari/85.8.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-au) AppleWebKit/85.8.5 (KHTML, like Gecko) Safari/85.8.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85.8.5 (KHTML, like Gecko) Safari/85.8.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/85.8.5 (KHTML, like Gecko) Safari/85.8.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/85.8.2 (KHTML, like Gecko) Safari/85.8.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sa) AppleWebKit/85.8.5 (KHTML, like Gecko) Safari/85.8.1" + family: "Safari" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppeWebKit/XX (KHTML, like Gecko) Safari/YY" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/XX (KHTML, like Gecko) Safari/YY" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SafariBookmarkChecker/1.27 (+http://www.coriolis.ch/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.0; SaferSurf; DigExt)" + family: "IE" + major: '5' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.5; SaferSurf; DigExt)" + family: "IE" + major: '5' + minor: '5' + patch: + - user_agent_string: "Satan 666 (7th level of Hell)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "savvybot/0.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Search-Channel" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SecretBrowser/007" + family: "Other" + major: + minor: + patch: + - user_agent_string: "S.E.K Tron (AmigaOS; alpha/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "S.E.K Tron (AmigaOS; alpha/06; AmigaOS 3.5; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "S.E.K Tron (AmigaOS; alpha/06; AmigaOS; .NET CLR 1.1.4322)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "S.E.K Tron (AmigaOS; alpha/06; Win98)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "S.E.K-Tron Systems" + family: "Other" + major: + minor: + patch: + - user_agent_string: "S.E.K-Tron Systems(compatible; MSIE 6.0; Matrix; SEK-Tron Systems; Windows NT 5.0)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "SEK Tron (AmigaOS; alpha/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "S.E.K-Tron Systems(compatible; MSIE 6.0; Matrix; SEK-Tron Systems; AmigaOS)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "S.E.K-Tron Systems(SEK-Tron; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SHARP-TQ-GX10" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SHARP-TQ-GX30" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Shockwave Flash" + family: "Other" + major: + minor: + patch: + - user_agent_string: "ShowLinks/1.0 libwww/5.4.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SIE-S55/16" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Simpy/1.1 (Simpy; http://www.simpy.com/?ref=bot; feedback at simpy dot com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SISLink" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SiteBar/3.2.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 6.0; Slackware)" + family: "IE" + major: '6' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; SmartPhone; Symbian OS/1.1.0) NetFront/3.1" + family: "NetFront" + major: '3' + minor: '1' + patch: + - user_agent_string: "Smurf Power" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Snoopy v1.01" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Snowstorm/0.1.0 (windows; U; SnowStep0.6.0; en-us) Gecko/20201231" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Solar Conflict (www.solarconflict.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "sony ericsson" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonP800/" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonP900/" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonP900/ UP.Link/5.1.2.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT230/R101 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT306/R101 UP.Link/1.1 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT616" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SonyEricssonT68/R502 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Sopheus Project/0.01 (Nutch; http://www.thenetplanet.com; info@thenetplanet.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SpaceBison/0.01 [fu] (Win67; X; Lolzor)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SpaceBison/0.01 [fu] (Win67; X; ShonenKnife)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Space Bison/0.02 [fu] (Win67; X; SK)" + family: "Space Bison" + major: '0' + minor: '02' + patch: + - user_agent_string: "Space Bison/0.69 [fu] (Win72; incompatible)" + family: "Space Bison" + major: '0' + minor: '69' + patch: + - user_agent_string: "SpiderMan 3.0.1-2-11-111 (CP/M;8-bit)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SquidClamAV_Redirector 1.6" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Squid-Prefetch" + family: "Other" + major: + minor: + patch: + - user_agent_string: "StackRambler/2.0 (MSIE incompatible)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "StarDownloader/1.44" + family: "Other" + major: + minor: + patch: + - user_agent_string: "StarDownloader/1.52" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Steeler/2.0 (http://www.tkl.iis.u-tokyo.ac.jp/~crawler/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; SuperCleaner 2.81; Windows NT 5.1)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Supergrass (GNU/Windows; U) [sr]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SuperMarioBrowser/3.0 [en] (NintendoOS 0.4.27)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SuperMarioBrowser/3.0 (WarioOS; U; WarioWare 2.1.4; en-US)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "SymbianOS/6.1 Series60/1.2 Profile/MIDP-" + family: "Nokia OSS Browser" + major: '1' + minor: '2' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; Synapse)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Teleport Pro/1.29" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Teleport Pro/1.29.1590" + family: "Other" + major: + minor: + patch: + - user_agent_string: "TheBlacksheepbrowser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "theConcept/1.0 (Macintosh)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "theConcept/1.1 (Macintosh)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Toaster/2.0 (X11; U; BeOS i786; en, de; rv:7.8.9) Gecko/20250223 Toaster/2.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Tutorial Crawler 1.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "TygoProwler (http://www.tygo.com/)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "UP.Browser/3.1.02-SC01 UP.Link/5.0.2.9 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '3' + minor: '1' + patch: '02' + - user_agent_string: "OWG1 UP/4.1.20a UP.Browser/4.1.20a-XXXX UP.Link/5.1.2.12 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '4' + minor: '1' + patch: '20' + - user_agent_string: "QC2135 UP.Browser/4.1.22b UP.Link/4.2.1.8 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '4' + minor: '1' + patch: '22' + - user_agent_string: "MOT-85/01.04 UP.Browser/4.1.26m.737 UP.Link/5.1.2.12 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '4' + minor: '1' + patch: '26' + - user_agent_string: "MOT-A-0A/00.06 UP.Browser/4.1.27a1 UP.Link/4.2.3.5h" + family: "UP.Browser" + major: '4' + minor: '1' + patch: '27' + - user_agent_string: "MOT-A-2D/00.02 UP.Browser/4.1.27a1 UP.Link/5.1.2.12 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '4' + minor: '1' + patch: '27' + - user_agent_string: "MOT-A-86/00.00 UP.Browser/4.1.27a1 UP.Link/4.2.3.5h (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '4' + minor: '1' + patch: '27' + - user_agent_string: "MOT-A-86/00.00 UP.Browser/4.1.27a1 UP.Link/5.1.2.12 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '4' + minor: '1' + patch: '27' + - user_agent_string: "Motorola-T33/1.5.1a UP.Browser/5.0.1.7.c.2 (GUI) (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '5' + minor: '0' + patch: '1' + - user_agent_string: "Alcatel-BG3/1.0 UP.Browser/5.0.3.1.2 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '5' + minor: '0' + patch: '3' + - user_agent_string: "KDDI/CA23/UP. Browser/6.0.2.254 (GUI) MMP/1.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Panasonic-G60/1.0 UP.Browser/6.1.0.7 MMP/1.0 UP.Browser/6.1.0.7 (GUI) MMP/1.0 UP.Link/5.1.1a (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SAGEM-myX-5m/1.0 UP.Browser/6.1.0.6.1.c.3 (GUI) MMP/1.0 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SAMSUNG-SGH-E700/BSI UP.Browser/6.1.0.6 (GUI) MMP/1.0" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SAMSUNG-SGH-E700/BSI UP.Browser/6.1.0.6 (GUI) MMP/1.0 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SAMSUNG-SGH-E700-OLYMPIC2004/1.0 UP.Browser/6.1.0.6 (GUI) MMP/1.0 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SAMSUNG-SGH-X600/K3 UP.Browser/6.1.0.6 (GUI) MMP/1.0" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SIE-C60/12 UP.Browser/6.1.0.5.c.6 (GUI) MMP/1.0 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SIE-M55/11 Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Browser/6.1.0.7.3 (GUI) MMP/1.0 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SIE-MC60/10 Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Browser/6.1.0.7.3 (GUI) MMP/1.0 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SIE-MC60/10 Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Browser/6.1.0.7.3 (GUI) MMP/1.0 UP.Link/5.1.1.5a" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SIE-S55/11 UP.Browser/6.1.0.5.c.2 (GUI) MMP/1.0 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "SIE-S55/20 UP.Browser/6.1.0.5.c.6 (GUI) MMP/1.0 UP.Link/1.1 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "UP.Browser/6.1.0.1.140 (Google CHTML Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '1' + patch: '0' + - user_agent_string: "KDDI-HI32 UP.Browser/6.2.0.5 (GUI) MMP/2.0" + family: "UP.Browser" + major: '6' + minor: '2' + patch: '0' + - user_agent_string: "SHARP-TQ-GX20/1.0 UP.Browser/6.2.0.1.185 (GUI) MMP/2.0" + family: "UP.Browser" + major: '6' + minor: '2' + patch: '0' + - user_agent_string: "OPWV-SDK/62 UP.Browser/6.2.2.1.208 (GUI) MMP/2.0" + family: "UP.Browser" + major: '6' + minor: '2' + patch: '2' + - user_agent_string: "VM4050/132.037 UP.Browser/6.2.2.4.e.1.100 (GUI) MMP/2.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" + family: "UP.Browser" + major: '6' + minor: '2' + patch: '2' + - user_agent_string: "LGE-VX7000/1.0 UP.Browser/6.2.3.1.174 (GUI) MMP/2.0 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '6' + minor: '2' + patch: '3' + - user_agent_string: "SIE-CX65/12 UP.Browser/7.0.0.1.c.3 (GUI) MMP/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 (Google WAP Proxy/1.0)" + family: "UP.Browser" + major: '7' + minor: '0' + patch: '0' + - user_agent_string: "SIE-S65/25 UP.Browser/7.0.0.1.c.3 (GUI) MMP/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1" + family: "UP.Browser" + major: '7' + minor: '0' + patch: '0' + - user_agent_string: "SEC-SGHX427M UP.Link/1.1 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Uptimebot" + family: "Other" + major: + minor: + patch: + - user_agent_string: "UptimeBot" + family: "Other" + major: + minor: + patch: + - user_agent_string: "User-Agent: Mozilla/5.0 (Windows; U; Windows; de-DE; rv:1.7.5)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040329" + family: "Other" + major: + minor: + patch: + - user_agent_string: "User-Agent: S.E.K Tron (AmigaOS; alpha/06; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Veczilla/0.35beta (X11; U; UNICOS/mk 21164a(EV5.6) Cray T3E; en-US; m18) Gecko/20020202 Netscape6/6.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Veczilla/0.35beta (X11; U; UNICOS/mk 21164a(EV5.6) Cray T3E; en-US; m18) Gecko/20040329" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/5.5 (compatible; Voyager; AmigaOS)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "W32/Trojan.Coced.226" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Emacs-W3/4.0pre.46 URL/p4.0pre.46 (i386-suse-linux; X11)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.3" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.3.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.3.1+cvs-1.411" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.3.1+cvs-1.414" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.3.2+mee-p24-19+moe-1.5.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.4.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.4.1-m17n-20030308" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.4.2" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.5" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.5+cvs-1.916" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.5 (FreeBSD),gzip(gfe) (via translate.google.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "w3m/0.5.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WannaBe (Macintosh; PPC)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Wap" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WAP" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Web Browser" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; WebCapture 2.0; Auto; Windows)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; WebCapture 2.0; Windows)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WebCatSv" + family: "Other" + major: + minor: + patch: + - user_agent_string: "webcollage/1.114" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WebForm 1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/6.0 (compatible; WebGod 9.1; Windows NT 6.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WebHopper" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 (compatible; WebMon 1.0.10; Windows 98 SE)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WebPix 1.0 (www.netwu.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WebRescuer v0.2.4" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WebStripper/2.20" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WebStripper/2.58" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/3.0 WebTV/1.2 (compatible; MSIE 2.0)" + family: "IE" + major: '2' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 4.0; WebTV/2.6)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 WebTV/2.6 (compatible; MSIE 4.0)" + family: "IE" + major: '4' + minor: '0' + patch: + - user_agent_string: "WebZIP/4.1 (http://www.spidersoft.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "wget 1.1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Wget/1.8.2 modified" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Wget/1.9+cvs-stable (Red Hat modified)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 5.00; Window 98)" + family: "IE" + major: '5' + minor: '00' + patch: + - user_agent_string: "WinHTTP Example/1.0" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WinWAP-PRO/3.1 (3.1.5.190) UP.Link/5.1.2.5 (Google WAP Proxy/1.0)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WM2003/1 (Windows CE 3.0; U) [en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WordPress/1.2.1 PHP/4.3.9-1" + family: "Other" + major: + minor: + patch: + - user_agent_string: "WorldWideWeb-X/3.2 (+Web Directory)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Wotbox/0.7-alpha (bot@wotbox.com; http://www.wotbox.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Wotbox/alpha0.6 (bot@wotbox.com; http://www.wotbox.com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "www.WebSearch.com.au" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 9.0b; Xbox-OS2) Obsidian" + family: "IE" + major: '9' + minor: '0' + patch: + - user_agent_string: "Mozilla/4.0 (compatible; MSIE 7.0b; Xbox-OS2) Obsidian" + family: "IE" + major: '7' + minor: '0' + patch: + - user_agent_string: "XBoX 64 (NVidea GForce 3 Architecture)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Xtreme Browser/0.14 (Linux; U) [i386-en]" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Yahoo-MMAudVid/1.0 (mms dash mmaudvidcrawler dash support at yahoo dash inc dot com)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "Yandex/1.01.001 (compatible; Win16; I)" + family: "Other" + major: + minor: + patch: + - user_agent_string: "YottaShopping_Bot/4.12 (+http://www.yottashopping.com) Shopping Search Engine" + family: "Other" + major: + minor: + patch: diff --git a/node_modules/karma/node_modules/useragent/test/fixtures/static.custom.yaml b/node_modules/karma/node_modules/useragent/test/fixtures/static.custom.yaml new file mode 100644 index 00000000..bacf1a08 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/test/fixtures/static.custom.yaml @@ -0,0 +1,13 @@ +test_cases: + + - user_agent_string: 'curl/7.12.1 (i686-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6' + family: 'cURL' + major: '7' + minor: '12' + patch: '1' + + - user_agent_string: 'Wget/1.10.1 (Red Hat modified)' + family: 'Wget' + major: '1' + minor: '10' + patch: '1' diff --git a/node_modules/karma/node_modules/useragent/test/fixtures/testcases.yaml b/node_modules/karma/node_modules/useragent/test/fixtures/testcases.yaml new file mode 100644 index 00000000..d60c8863 --- /dev/null +++ b/node_modules/karma/node_modules/useragent/test/fixtures/testcases.yaml @@ -0,0 +1,389 @@ +test_cases: + + - user_agent_string: 'Mozilla/5.0 (X11i; Linux; C) AppleWebKikt/533.3 (KHTML, like Gecko) QtCarBrowser Safari/533.3' + family: 'QtCarBrowser' + major: '1' + minor: + patch: + + - user_agent_string: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.8+ (KHTML, like Gecko) Version/6.0 Safari/536.25' + family: 'WebKit Nightly' + major: '537' + minor: '8' + patch: + + - user_agent_string: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) Version/5.1.1 Safari/534.51.22' + family: 'WebKit Nightly' + major: '534' + minor: + patch: + + - user_agent_string: 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)' + family: 'FacebookBot' + major: '1' + minor: '1' + patch: + + - user_agent_string: 'Pingdom.com_bot_version_1.4_(http://www.pingdom.com/)' + family: 'PingdomBot' + major: '1' + minor: '4' + patch: + + - user_agent_string: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) Version/5.1.1 Safari/534.51.22' + family: 'WebKit Nightly' + major: '534' + minor: + patch: + + - user_agent_string: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1+ (KHTML, like Gecko) Version/5.1.1 Safari/534.51.22' + family: 'WebKit Nightly' + major: '537' + minor: '1' + patch: + + - user_agent_string: 'Mozilla/5.0 (Linux x86_64) AppleWebKit/534.26+ WebKitGTK+/1.4.1 luakit/f3a2dbe' + family: 'LuaKit' + major: + minor: + patch: + + - user_agent_string: 'Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20110408 conkeror/0.9.3' + family: 'Conkeror' + major: '0' + minor: '9' + patch: '3' + + - user_agent_string: 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.16) Gecko/20110302 Conkeror/0.9.2 (Debian-0.9.2+git100804-1)' + family: 'Conkeror' + major: '0' + minor: '9' + patch: '2' + + + - user_agent_string: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.17) Gecko/20110414 Lightning/1.0b3pre Thunderbird/3.1.10' + family: 'Lightning' + major: '1' + minor: '0' + patch: 'b3pre' + + - user_agent_string: 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.17) Gecko/20110414 Thunderbird/3.1.10 ThunderBrowse/3.3.5' + family: 'ThunderBrowse' + major: '3' + minor: '3' + patch: '5' + + - user_agent_string: 'Mozilla/5.0 (Windows; U; en-US) AppleWebKit/531.9 (KHTML, like Gecko) AdobeAIR/2.5.1' + family: 'AdobeAIR' + major: '2' + minor: '5' + patch: '1' + + - user_agent_string: 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' + family: 'Googlebot' + major: '2' + minor: '1' + patch: + + - user_agent_string: 'Mozilla/5.0 YottaaMonitor;' + family: 'YottaaMonitor' + major: + minor: + patch: + + - user_agent_string: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) RockMelt/0.8.34.841 Chrome/6.0.472.63 Safari/534.3' + family: 'RockMelt' + major: '0' + minor: '8' + patch: '34' + + - user_agent_string: 'Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20110417 IceCat/4.0' + family: 'IceCat' + major: '4' + minor: '0' + patch: + + - user_agent_string: 'Mozilla/5.0 (X11; U; Linux i686; nl-NL) AppleWebKit/534.3 (KHTML, like Gecko) WeTab-Browser Safari/534.3' + family: 'WeTab' + major: + minor: + patch: + + - user_agent_string: 'Mozilla/4.0 (compatible; Linux 2.6.10) NetFront/3.3 Kindle/1.0 (screen 600x800)' + family: 'Kindle' + major: '1' + minor: '0' + patch: + + - user_agent_string: 'Opera/9.80 (Android 3.2; Linux; Opera Tablet/ADR-1106291546; U; en) Presto/2.8.149 Version/11.10' + family: 'Opera Tablet' + major: '11' + minor: '10' + patch: + + - user_agent_string: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) FireWeb/1.0.0.0' + family: 'FireWeb' + major: '1' + minor: '0' + patch: '0' + + - user_agent_string: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Comodo_Dragon/4.1.1.11 Chrome/4.1.249.1042 Safari/532.5' + family: 'Comodo Dragon' + major: '4' + minor: '1' + patch: '1' + + - user_agent_string: 'Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5' + family: 'Mobile Safari' + major: '5' + minor: '0' + patch: '2' + + - user_agent_string: 'Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; GT-P7510 Build/HRI83) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13' + family: 'Android' + major: '3' + minor: '0' + patch: '1' + + - user_agent_string: 'Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.58 Safari/534.6 TouchPad/1.0' + family: 'webOS TouchPad' + major: '1' + minor: '0' + patch: + + - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; SAMSUNG; SGH-i917)' + family: 'IE Mobile' + major: '7' + minor: '0' + patch: + + + - user_agent_string: 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17 Skyfire/2.0' + family: 'Skyfire' + major: '2' + minor: '0' + patch: + + - user_agent_string: 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/0.0.1 Safari/534.8+' + family: 'Blackberry WebKit' + major: '1' + minor: '0' + patch: '0' + + - user_agent_string: 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.648.133 Chrome/10.0.648.133 Safari/534.16' + family: 'Chromium' + major: '10' + minor: '0' + patch: '648' + + - user_agent_string: 'Mozilla/5.0 (Windows NT 5.1; rv:2.0) Gecko/20110407 Firefox/4.0.3 PaleMoon/4.0.3' + family: 'Pale Moon (Firefox Variant)' + major: '4' + minor: '0' + patch: '3' + + - user_agent_string: 'Opera/9.80 (Series 60; Opera Mini/6.24455/25.677; U; fr) Presto/2.5.25 Version/10.54' + family: 'Opera Mini' + major: '6' + minor: '24455' + patch: + + - user_agent_string: 'Mozilla/5.0 (X11; Linux i686 (x86_64); rv:2.0b4) Gecko/20100818 Firefox/4.0b4' + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: 'b4' + + - user_agent_string: 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.12) Gecko/20101027 Ubuntu/10.04 (lucid) Firefox/3.6.12' + family: 'Firefox' + major: '3' + minor: '6' + patch: '12' + + - user_agent_string: 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.1pre) Gecko/20090717 Ubuntu/9.04 (jaunty) Shiretoko/3.5.1pre' + family: 'Firefox (Shiretoko)' + major: '3' + minor: '5' + patch: '1pre' + + - user_agent_string: 'Mozilla/5.0 (X11; Linux x86_64; rv:2.0b8pre) Gecko/20101031 Firefox-4.0/4.0b8pre' + family: 'Firefox Beta' + major: '4' + minor: '0' + patch: 'b8pre' + + - user_agent_string: 'Mozilla/5.0 (X11; U; BSD Four; en-US) AppleWebKit/533.3 (KHTML, like Gecko) rekonq Safari/533.3' + family: 'Rekonq' + major: + minor: + patch: + + - user_agent_string: 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) rekonq/1.0 Safari/534.34' + family: 'Rekonq' + major: '1' + minor: '0' + patch: + + - user_agent_string: 'Mozilla/5.0 (X11; U; Linux; de-DE) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) konqueror/4.3.1' + family: 'Konqueror' + major: '4' + minor: '3' + patch: '1' + + - user_agent_string: 'SomethingWeNeverKnewExisted' + family: 'Other' + major: + minor: + patch: + + - user_agent_string: 'Midori/0.2 (X11; Linux; U; en-us) WebKit/531.2 ' + family: 'Midori' + major: '0' + minor: '2' + patch: + + - user_agent_string: 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.3a1) Gecko/20100208 MozillaDeveloperPreview/3.7a1 (.NET CLR 3.5.30729)' + family: 'MozillaDeveloperPreview' + major: '3' + minor: '7' + patch: 'a1' + + - user_agent_string: 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.5.24 Version/10.53' + family: 'Opera' + major: '10' + minor: '53' + patch: + + - user_agent_string: 'Opera/9.80 (S60; SymbOS; Opera Mobi/275; U; es-ES) Presto/2.4.13 Version/10.00' + family: 'Opera Mobile' + major: '10' + minor: '00' + patch: + + - user_agent_string: 'Mozilla/5.0 (webOS/1.2; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Desktop/1.0' + family: 'webOSBrowser' + major: '1' + minor: '2' + patch: + + - user_agent_string: 'Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10' + family: 'Mobile Safari' + major: '4' + minor: '0' + patch: '4' + + - user_agent_string: 'Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8500/S8500XXJEE; U; Bada/1.0; nl-nl) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WVGA SMM-MMS/1.2.0 OPN-B' + family: 'Dolfin' + major: '2' + minor: '0' + patch: + + - user_agent_string: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.101) AppleWebKit/530 (KHTML, like Gecko) Version/4.0 Safari/530.17' + family: 'BOLT' + major: '2' + minor: '101' + patch: + + # Safari + - user_agent_string: 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3' + family: 'Safari' + major: + minor: + patch: + + - user_agent_string: 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-us) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5' + family: 'Safari' + major: '5' + minor: '0' + patch: '2' + + # BlackBerry devices + - user_agent_string: 'Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en-GB) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.141 Mobile Safari/534.1+' + family: 'Blackberry WebKit' + major: '6' + minor: '0' + patch: '0' + + - user_agent_string: 'Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en-US) AppleWebKit/534.1 (KHTML, like Gecko) Version/6.0.0.91 Mobile Safari/534.1 ' + family: 'Blackberry WebKit' + major: '6' + minor: '0' + patch: '0' + + # Chrome frame + - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; chromeframe; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; Sleipnir 2.8.5)3.0.30729)' + js_ua: "{'js_user_agent_string': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.1 (KHTML, like Gecko) Chrome/2.0.169.1 Safari/530.1'}" + family: 'Chrome Frame (Sleipnir 2)' + major: '2' + minor: '0' + patch: '169' + + - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; chromeframe; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)' + js_ua: "{'js_user_agent_string': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.1 (KHTML, like Gecko) Chrome/2.0.169.1 Safari/530.1'}" + family: 'Chrome Frame (IE 8)' + major: '2' + minor: '0' + patch: '169' + + # Chrome Frame installed but not enabled + - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6; chromeframe; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)' + js_ua: "{'js_user_agent_string': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; chromeframe; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)'}" + family: 'IE' + major: '8' + minor: '0' + patch: + + - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6; .NET CLR 2.0.50727; .NET CLR 1.1.4322)' + js_ua: "{'js_user_agent_string': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322)', 'js_user_agent_family': 'IE Platform Preview', 'js_user_agent_v1': '9', 'js_user_agent_v2': '0', 'js_user_agent_v3': '1'}" + family: 'IE Platform Preview' + major: '9' + minor: '0' + patch: '1' + + - user_agent_string: 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-80) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true' + family: 'Silk' + major: '1' + minor: '1' + patch: '0-80' + +# - user_agent_string: 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; XBLWP7; ZuneWP7)' +# family: 'IE Mobile' +# major: '9' +# minor: '0' +# patch: + + - user_agent_string: 'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; SGH-i917)' + family: 'IE Mobile' + major: '9' + minor: '0' + patch: + + - user_agent_string: 'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; SGH-i917)' + family: 'IE Mobile' + major: '9' + minor: '0' + patch: + + - user_agent_string: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; chromeframe/11.0.660.0)' + family: 'Chrome Frame' + major: '11' + minor: '0' + patch: '660' + + - user_agent_string: 'PyAMF/0.6.1' + family: 'PyAMF' + major: '0' + minor: '6' + patch: '1' + + - user_agent_string: 'python-requests/0.14 CPython/2.6 Linux/2.6-43-server' + family: 'Python Requests' + major: '0' + minor: '14' + patch: + + - user_agent_string: 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0)' + family: 'IE' + major: '10' + minor: '0' + patch: diff --git a/node_modules/karma/node_modules/useragent/test/mocha.opts b/node_modules/karma/node_modules/useragent/test/mocha.opts new file mode 100644 index 00000000..bf0875dd --- /dev/null +++ b/node_modules/karma/node_modules/useragent/test/mocha.opts @@ -0,0 +1,4 @@ +--reporter spec +--ui bdd +--require should +--growl diff --git a/node_modules/karma/node_modules/useragent/test/parser.qa.js b/node_modules/karma/node_modules/useragent/test/parser.qa.js new file mode 100644 index 00000000..fda5434a --- /dev/null +++ b/node_modules/karma/node_modules/useragent/test/parser.qa.js @@ -0,0 +1,45 @@ +var useragent = require('../') + , should = require('should') + , yaml = require('yamlparser') + , fs = require('fs'); + +// run over the testcases, some might fail, some might not. This is just qu +// test to see if we can parse without errors, and with a reasonable amount +// of errors. +[ + 'testcases.yaml' + , 'static.custom.yaml' + , 'firefoxes.yaml' + , 'pgts.yaml' +].forEach(function (filename) { + var testcases = fs.readFileSync(__dirname +'/fixtures/' + filename).toString() + , parsedyaml = yaml.eval(testcases); + + testcases = parsedyaml.test_cases; + testcases.forEach(function (test) { + // we are unable to parse these tests atm because invalid JSON is used to + // store the useragents + if (typeof test.user_agent_string !== 'string') return; + + // these tests suck as the test files are broken, enable this to have about + // 40 more failing tests + if (test.family.match(/googlebot|avant/i)) return; + + // attempt to parse the shizzle js based stuff + var js_ua; + if (test.js_ua) { + js_ua = (Function('return ' + test.js_ua)()).js_user_agent_string; + } + + exports[filename + ': ' + test.user_agent_string] = function () { + var agent = useragent.parse(test.user_agent_string, js_ua); + + agent.family.should.equal(test.family); + // we need to test if v1 is a string, because the yamlparser transforms + // empty v1: statements to {} + agent.major.should.equal(typeof test.major == 'string' ? test.major : '0'); + agent.minor.should.equal(typeof test.minor == 'string' ? test.minor : '0'); + agent.patch.should.equal(typeof test.patch == 'string' ? test.patch : '0'); + } + }); +}); diff --git a/node_modules/karma/node_modules/useragent/test/parser.test.js b/node_modules/karma/node_modules/useragent/test/parser.test.js new file mode 100644 index 00000000..ab6473fe --- /dev/null +++ b/node_modules/karma/node_modules/useragent/test/parser.test.js @@ -0,0 +1,214 @@ +describe('useragent', function () { + 'use strict'; + + var useragent = require('../') + , ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.24 Safari/535.2"; + + it('should expose the current version number', function () { + useragent.version.should.match(/^\d+\.\d+\.\d+$/); + }); + + it('should expose the Agent interface', function () { + useragent.Agent.should.be.a('function'); + }); + + it('should expose the OperatingSystem interface', function () { + useragent.OperatingSystem.should.be.a('function'); + }); + + it('should expose the Device interface', function () { + useragent.Device.should.be.a('function'); + }); + + it('should expose the dictionary lookup', function () { + useragent.lookup.should.be.a('function'); + }); + + it('should expose the parser', function () { + useragent.parse.should.be.a('function'); + }); + + it('should expose the useragent tester', function () { + useragent.is.should.be.a('function'); + }); + + describe('#parse', function () { + it('correctly transforms everything to the correct instances', function () { + var agent = useragent.parse(ua); + + agent.should.be.an.instanceOf(useragent.Agent); + agent.os.should.be.an.instanceOf(useragent.OperatingSystem); + agent.device.should.be.an.instanceOf(useragent.Device); + }); + + it('correctly parsers the operating system', function () { + var os = useragent.parse(ua).os; + + os.toString().should.equal('Mac OS X 10.7.1'); + os.toVersion().should.equal('10.7.1'); + JSON.stringify(os).should.equal('{"family":"Mac OS X","major":"10","minor":"7","patch":"1"}'); + + os.major.should.equal('10'); + os.minor.should.equal('7'); + os.patch.should.equal('1'); + }); + + it('should not throw errors when no useragent is given', function () { + var agent = useragent.parse(); + + agent.family.should.equal('Other'); + agent.major.should.equal('0'); + agent.minor.should.equal('0'); + agent.patch.should.equal('0'); + + agent.os.toString().should.equal('Other'); + agent.toVersion().should.equal('0.0.0'); + agent.toString().should.equal('Other 0.0.0 / Other'); + agent.toAgent().should.equal('Other 0.0.0'); + JSON.stringify(agent).should.equal('{"family":"Other","major":"0","minor":"0","patch":"0","device":{"family":"Other"},"os":{"family":"Other"}}'); + }); + + it('should not throw errors on empty strings and default to unkown', function () { + var agent = useragent.parse(''); + + agent.family.should.equal('Other'); + agent.major.should.equal('0'); + agent.minor.should.equal('0'); + agent.patch.should.equal('0'); + + agent.os.toString().should.equal('Other'); + agent.toVersion().should.equal('0.0.0'); + agent.toString().should.equal('Other 0.0.0 / Other'); + agent.toAgent().should.equal('Other 0.0.0'); + JSON.stringify(agent).should.equal('{"family":"Other","major":"0","minor":"0","patch":"0","device":{"family":"Other"},"os":{"family":"Other"}}'); + }); + + it('should correctly parse chromes user agent', function () { + var agent = useragent.parse(ua); + + agent.family.should.equal('Chrome'); + agent.major.should.equal('15'); + agent.minor.should.equal('0'); + agent.patch.should.equal('874'); + + agent.os.toString().should.equal('Mac OS X 10.7.1'); + agent.toVersion().should.equal('15.0.874'); + agent.toString().should.equal('Chrome 15.0.874 / Mac OS X 10.7.1'); + agent.toAgent().should.equal('Chrome 15.0.874'); + JSON.stringify(agent).should.equal('{"family":"Chrome","major":"15","minor":"0","patch":"874","device":{"family":"Other"},"os":{"family":"Mac OS X","major":"10","minor":"7","patch":"1"}}'); + }); + }); + + describe('#fromJSON', function () { + it('should re-generate the Agent instance', function () { + var agent = useragent.parse(ua) + , string = JSON.stringify(agent) + , agent2 = useragent.fromJSON(string); + + agent2.family.should.equal(agent.family); + agent2.major.should.equal(agent.major); + agent2.minor.should.equal(agent.minor); + agent2.patch.should.equal(agent.patch); + + agent2.device.family.should.equal(agent.device.family); + + agent2.os.family.should.equal(agent.os.family); + agent2.os.major.should.equal(agent.os.major); + agent2.os.minor.should.equal(agent.os.minor); + agent2.os.patch.should.equal(agent.os.patch); + }); + + it('should also work with legacy JSON', function () { + var agent = useragent.fromJSON('{"family":"Chrome","major":"15","minor":"0","patch":"874","os":"Mac OS X"}'); + + agent.family.should.equal('Chrome'); + agent.major.should.equal('15'); + agent.minor.should.equal('0'); + agent.patch.should.equal('874'); + + agent.device.family.should.equal('Other'); + + agent.os.family.should.equal('Mac OS X'); + }); + }); + + describe('#is', function () { + var chrome = ua + , firefox = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20100101 Firefox/8.0' + , ie = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; yie8)' + , opera = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; de) Opera 11.51' + , safari = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; da-dk) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1' + , ipod = 'Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5'; + + it('should not throw errors when called without arguments', function () { + useragent.is(); + useragent.is(''); + }); + + it('should correctly detect google chrome', function () { + useragent.is(chrome).chrome.should.equal(true); + useragent.is(chrome).webkit.should.equal(true); + useragent.is(chrome).safari.should.equal(false); + useragent.is(chrome).firefox.should.equal(false); + useragent.is(chrome).mozilla.should.equal(false); + useragent.is(chrome).ie.should.equal(false); + useragent.is(chrome).opera.should.equal(false); + useragent.is(chrome).mobile_safari.should.equal(false); + }); + + it('should correctly detect firefox', function () { + useragent.is(firefox).chrome.should.equal(false); + useragent.is(firefox).webkit.should.equal(false); + useragent.is(firefox).safari.should.equal(false); + useragent.is(firefox).firefox.should.equal(true); + useragent.is(firefox).mozilla.should.equal(true); + useragent.is(firefox).ie.should.equal(false); + useragent.is(firefox).opera.should.equal(false); + useragent.is(firefox).mobile_safari.should.equal(false); + }); + + it('should correctly detect internet explorer', function () { + useragent.is(ie).chrome.should.equal(false); + useragent.is(ie).webkit.should.equal(false); + useragent.is(ie).safari.should.equal(false); + useragent.is(ie).firefox.should.equal(false); + useragent.is(ie).mozilla.should.equal(false); + useragent.is(ie).ie.should.equal(true); + useragent.is(ie).opera.should.equal(false); + useragent.is(ie).mobile_safari.should.equal(false); + }); + + it('should correctly detect opera', function () { + useragent.is(opera).chrome.should.equal(false); + useragent.is(opera).webkit.should.equal(false); + useragent.is(opera).safari.should.equal(false); + useragent.is(opera).firefox.should.equal(false); + useragent.is(opera).mozilla.should.equal(false); + useragent.is(opera).ie.should.equal(false); + useragent.is(opera).opera.should.equal(true); + useragent.is(opera).mobile_safari.should.equal(false); + }); + + it('should correctly detect safari', function () { + useragent.is(safari).chrome.should.equal(false); + useragent.is(safari).webkit.should.equal(true); + useragent.is(safari).safari.should.equal(true); + useragent.is(safari).firefox.should.equal(false); + useragent.is(safari).mozilla.should.equal(false); + useragent.is(safari).ie.should.equal(false); + useragent.is(safari).opera.should.equal(false); + useragent.is(safari).mobile_safari.should.equal(false); + }); + + it('should correctly detect safari-mobile', function () { + useragent.is(ipod).chrome.should.equal(false); + useragent.is(ipod).webkit.should.equal(true); + useragent.is(ipod).safari.should.equal(true); + useragent.is(ipod).firefox.should.equal(false); + useragent.is(ipod).mozilla.should.equal(false); + useragent.is(ipod).ie.should.equal(false); + useragent.is(ipod).opera.should.equal(false); + useragent.is(ipod).mobile_safari.should.equal(true); + }); + }); +}); diff --git a/node_modules/karma/package.json b/node_modules/karma/package.json new file mode 100644 index 00000000..8e8af9bb --- /dev/null +++ b/node_modules/karma/package.json @@ -0,0 +1,392 @@ +{ + "name": "karma", + "description": "Spectacular Test Runner for JavaScript.", + "homepage": "http://karma-runner.github.io/", + "repository": { + "type": "git", + "url": "git://github.com/karma-runner/karma.git" + }, + "bugs": { + "url": "https://github.com/karma-runner/karma/issues" + }, + "keywords": [ + "karma", + "spectacular", + "runner", + "karma", + "js", + "javascript", + "testing", + "test", + "remote", + "execution" + ], + "author": { + "name": "Vojta Jína", + "email": "vojta.jina@gmail.com" + }, + "contributors": [ + { + "name": "Friedel Ziegelmayer", + "email": "friedel.ziegelmayer@gmail.com" + }, + { + "name": "taichi", + "email": "ryushi@gmail.com" + }, + { + "name": "Liam Newman", + "email": "bitwiseman@gmail.com" + }, + { + "name": "Shyam Seshadri", + "email": "shyamseshadri@gmail.com" + }, + { + "name": "Kim Joar Bekkelund", + "email": "kjbekkelund@gmail.com" + }, + { + "name": "Tim Cuthbertson", + "email": "tim@gfxmonk.net" + }, + { + "name": "Andrew Martin", + "email": "sublimino@gmail.com" + }, + { + "name": "Daniel Aleksandersen", + "email": "code@daniel.priv.no" + }, + { + "name": "Ilya Volodin", + "email": "ivolodin@vistaprint.com" + }, + { + "name": "Iristyle", + "email": "Iristyle@github" + }, + { + "name": "Marcello Nuccio", + "email": "marcello.nuccio@gmail.com" + }, + { + "name": "pavelgj", + "email": "pavelgj@gmail.com" + }, + { + "name": "Bulat Shakirzyanov", + "email": "mallluhuct@gmail.com" + }, + { + "name": "Ethan J. Brown", + "email": "ethan_j_brown@hotmail.com" + }, + { + "name": "Hugues Malphettes", + "email": "hmalphettes@gmail.com" + }, + { + "name": "Igor Minar", + "email": "iiminar@gmail.com" + }, + { + "name": "James Ford", + "email": "jford@psyked.co.uk" + }, + { + "name": "Roarke Gaskill", + "email": "roarke.gaskill@gmail.com" + }, + { + "name": "ngiebel", + "email": "ngiebel@starkinvestments.com" + }, + { + "name": "rdodev", + "email": "rubenoz@gmail.com" + }, + { + "name": "Alexander Shtuchkin", + "email": "ashtuchkin@gmail.com" + }, + { + "name": "Andy Joslin", + "email": "andytjoslin@gmail.com" + }, + { + "name": "AvnerCohen", + "email": "israbirding@gmail.com" + }, + { + "name": "Breno Calazans", + "email": "breno@vtex.com.br" + }, + { + "name": "Brian Ford", + "email": "btford@umich.edu" + }, + { + "name": "Chad Smith", + "email": "chad@configit.com" + }, + { + "name": "Chris Dawson", + "email": "xrdawson@gmail.com" + }, + { + "name": "Danny Croft", + "email": "danny.croft@yahoo.co.uk" + }, + { + "name": "David Jensen", + "email": "david@frode.(none)", + "url": "none" + }, + { + "name": "David M. Karr", + "email": "dk068x@att.com" + }, + { + "name": "David Souther", + "email": "davidsouther@gmail.com" + }, + { + "name": "Dillon", + "email": "mdillon@reachmail.com" + }, + { + "name": "Ed Rooth", + "email": "ed.rooth@rackspace.com" + }, + { + "name": "Eldar Jafarov", + "email": "djkojb@gmail.com" + }, + { + "name": "Eric Baer", + "email": "me@ericbaer.com" + }, + { + "name": "Franck Garcia", + "email": "garcia.franck@gmail.com" + }, + { + "name": "Fred Sauer", + "email": "fredsa@google.com" + }, + { + "name": "Geert Van Laethem", + "email": "geert.van.laethem@pandora.be" + }, + { + "name": "Igor Minar", + "email": "igor@angularjs.org" + }, + { + "name": "James Shore", + "email": "jshore@jamesshore.com" + }, + { + "name": "Jeff Froom", + "email": "jeff@jfroom.com" + }, + { + "name": "Jeff Jewiss", + "email": "jeffjewiss@gmail.com" + }, + { + "name": "Julian Connor", + "email": "julian.connor@venmo.com" + }, + { + "name": "Karolis Narkevicius", + "email": "karolis.n@gmail.com" + }, + { + "name": "Kevin Ortman", + "email": "kevin_ortman@msn.com" + }, + { + "name": "Lukasz Zatorski", + "email": "lzatorski@gmail.com" + }, + { + "name": "Marko Anastasov", + "email": "marko@renderedtext.com" + }, + { + "name": "Martin Lemanski", + "email": "martin.lemanski@gmx.at" + }, + { + "name": "Matias Niemelä", + "email": "matias@yearofmoo.com" + }, + { + "name": "Merrick Christensen", + "email": "merrick.christensen@gmail.com" + }, + { + "name": "Milan Aleksic", + "email": "milanaleksic@gmail.com" + }, + { + "name": "Nick Payne", + "email": "nick@kurai.co.uk" + }, + { + "name": "Nish", + "email": "nishantpatel611@gmail.com" + }, + { + "name": "Nuno Job", + "email": "nunojobpinto@gmail.com" + }, + { + "name": "Pascal Hartig", + "email": "phartig@rdrei.net" + }, + { + "name": "Patrick Lussan", + "email": "patrick.lussan@componize.com" + }, + { + "name": "Patrik Henningsson", + "email": "patrik.henningsson@gmail.com" + }, + { + "name": "Pete Bacon Darwin", + "email": "pete@bacondarwin.com" + }, + { + "name": "Pete Swan", + "email": "pete@indabamusic.com" + }, + { + "name": "Peter Yates", + "email": "pd.yates@gmail.com" + }, + { + "name": "Remy Sharp", + "email": "remy@remysharp.com" + }, + { + "name": "Shane Osbourne", + "email": "shane.osbourne8@gmail.com" + }, + { + "name": "Tim Olshansky", + "email": "tim.olshansky@gmail.com" + }, + { + "name": "Veronica Lynn", + "email": "veronica.lynn@redjack.com" + }, + { + "name": "Yi Wang", + "email": "e@yi-wang.me" + }, + { + "name": "Zhang zhengzheng", + "email": "code@tychio.net" + }, + { + "name": "ahaurw01", + "email": "ahaurwitz@gmail.com" + }, + { + "name": "ashaffer", + "email": "darawk@gmail.com" + }, + { + "name": "hrgdavor", + "email": "hrgdavor@gmail.com" + }, + { + "name": "lanshunfang", + "email": "lanshunfang@gmail.com" + }, + { + "name": "toran billups", + "email": "toranb@gmail.com" + } + ], + "dependencies": { + "di": "~0.0.1", + "socket.io": "~0.9.13", + "chokidar": "~0.7.0", + "glob": "~3.1.21", + "minimatch": "~0.2", + "http-proxy": "~0.10", + "optimist": "~0.3", + "coffee-script": "~1.6", + "rimraf": "~2.1", + "q": "~0.9", + "colors": "0.6.0-1", + "lodash": "~1.1", + "mime": "~1.2", + "log4js": "~0.6.3", + "useragent": "~2.0.4", + "graceful-fs": "~1.2.1", + "connect": "~2.8.4" + }, + "peerDependencies": { + "karma-jasmine": "*", + "karma-requirejs": "*", + "karma-coffee-preprocessor": "*", + "karma-html2js-preprocessor": "*", + "karma-chrome-launcher": "*", + "karma-firefox-launcher": "*", + "karma-phantomjs-launcher": "*", + "karma-script-launcher": "*" + }, + "devDependencies": { + "grunt": "~0.4", + "grunt-simple-mocha": "git://github.com/yaymukund/grunt-simple-mocha.git", + "grunt-contrib-jshint": "~0.3", + "grunt-coffeelint": "~0.0.6", + "grunt-npm": "~0.0.1", + "grunt-bump": "~0.0.10", + "grunt-conventional-changelog": "~1.0.0", + "grunt-auto-release": "~0.0.3", + "mocks": "~0.0.10", + "which": "~1.0", + "sinon-chai": "~2.3", + "chai": "~1.5", + "mocha": "~1.8", + "sinon": "~1.6", + "timer-shim": "~0.2", + "chai-as-promised": "~3.2", + "qq": "~0.3", + "karma-jasmine": "*", + "karma-mocha": "*", + "karma-qunit": "*", + "karma-coverage": "*", + "karma-requirejs": "*", + "karma-growl-reporter": "*", + "karma-junit-reporter": "*", + "karma-chrome-launcher": "*", + "karma-firefox-launcher": "*", + "karma-sauce-launcher": "*", + "karma-phantomjs-launcher": "*", + "karma-ng-scenario": "*", + "karma-coffee-preprocessor": "*", + "karma-html2js-preprocessor": "*", + "karma-browserstack-launcher": "git://github.com/karma-runner/karma-browserstack-launcher.git", + "semver": "~1.1.4", + "grunt-contrib-watch": "~0.5.0" + }, + "main": "./lib/index", + "bin": { + "karma": "./bin/karma" + }, + "engines": { + "node": "~0.8 || ~0.10" + }, + "version": "0.10.6", + "readme": "# Karma [![Build Status](https://secure.travis-ci.org/karma-runner/karma.png?branch=master)](http://travis-ci.org/karma-runner/karma)\n\nA simple tool that allows you to execute JavaScript code in multiple\n_real_ browsers, powered by [Node.js] and [Socket.io].\n\n> The main purpose of Karma is to make your TDD development easy,\n> fast, and fun.\n\n## When should I use Karma?\n\n* You want to test code in *real* browsers.\n* You want to test code in multiple browsers (desktop, mobile,\n tablets, etc.).\n* You want to execute your tests locally during development.\n* You want to execute your tests on a continuous integration server.\n* You want to execute your tests on every save.\n* You love your terminal.\n* You don't want your (testing) life to suck.\n* You want to use [Istanbul] to automagically generate coverage\n reports.\n* You want to use [RequireJS] for your source files.\n\n\n## But I still want to use \\_insert testing library\\_\n\nKarma is not a testing framework, neither an assertion library,\nso for that you can use pretty much anything you like. Right now out\nof the box there is support for\n\n* [Mocha]\n* [Jasmine]\n* [QUnit]\n* \\_anything else\\_ Write your own adapter. It's not that hard. And we\n are here to help.\n\n\n## Which Browsers can I use?\n\nAll the major browsers are supported, if you want to know more see the\n[Browsers] page.\n\n\n## I want to use it. Where do I sign?\n\nYou don't need to sign anything but here are some resources to help\nyou to get started. And if you need even more infos have a look at our\ngreat [website].\n\n### Obligatory Screencast.\n\nEvery serious project has a screencast, so here is ours. Just click\n[here] and let the show begin.\n\n### NPM Installation.\n\nIf you have [Node.js] installed, it's as simple as\n\n```bash\n$ npm install -g karma\n```\n\nThis will give you the latest stable version available on npm. If you\nwant to live life on the edge you can do so by\n\n```bash\n$ npm install -g karma@canary\n```\n\nThe curious can have a look at the documentation articles for\n[Getting Started] and [Versioning].\n\n### Using it.\n\nGo into your project and create a Karma configuration. That is\njust a simple JavaScript or CoffeeScript file that tells Karma\nwhere all the awesomeness of your project are.\n\nYou can find a simple example in\n[test/client/karma.conf.js](https://github.com/karma-runner/karma/blob/master/test/client/karma.conf.js)\nwhich contains most of the options.\n\nTo create your own from scratch there is the `init` command, which\nwill be named `karma.conf.js` by default:\n\n```bash\n$ karma init\n```\nThis will ask you many questions and if you answered them all correct\nyou will be allowed to use Karma.\n\nFor more information on the configuration options see\n[Configuration File Overview].\n\nNow that you have your configuration all that is left to do is to\nstart Karma:\n```bash\n$ karma start\n```\n\nIf you want to run tests manually (without auto watching file changes), you can:\n```bash\n$ karma run\n```\nBut only if you have started the Karma server before.\n\n\n## Why did you create this?\n\nThroughout the development of [AngularJS], we've been using [JSTD] for\ntesting. I really think that JSTD is a great idea. Unfortunately, we\nhad many problems with JSTD, so we decided to write our own test\nrunner based on the same idea. We wanted a simple tool just for\nexecuting JavaScript tests that is both stable and fast. That's why we\nuse the awesome [Socket.io] library and [Node.js].\n\n\n## I still don't get it. Where can I get help?\n\n* [Docs]\n* [Mailing List]\n* [Issuetracker]\n* [@JsKarma] on Twitter\n\n## This is so great. I want to help.\n\nSee\n[Contributing.md](https://github.com/karma-runner/karma/blob/master/CONTRIBUTING.md)\nor the [docs] for more information.\n\n\n## My boss wants a license. So where is it?\n\n### The MIT License\n\n> Copyright (C) 2011-2013 Vojta Jína.\n>\n> Permission is hereby granted, free of charge, to any person\n> obtaining a copy of this software and associated documentation files\n> (the \"Software\"), to deal in the Software without restriction,\n> including without limitation the rights to use, copy, modify, merge,\n> publish, distribute, sublicense, and/or sell copies of the Software,\n> and to permit persons to whom the Software is furnished to do so,\n> subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n> BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n> ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n\n\n[AngularJS]: http://angularjs.org/\n[JSTD]: http://code.google.com/p/js-test-driver/\n[Socket.io]: http://socket.io/\n[Node.js]: http://nodejs.org/\n[Jasmine]: http://pivotal.github.io/jasmine/\n[Mocha]: http://visionmedia.github.io/mocha/\n[QUnit]: http://qunitjs.com/\n[here]: http://www.youtube.com/watch?v=MVw8N3hTfCI\n[Mailing List]: https://groups.google.com/forum/#!forum/karma-users\n[Issuetracker]: https://github.com/karma-runner/karma/issues\n[@JsKarma]: http://twitter.com/JsKarma\n[RequireJS]: http://requirejs.org/\n[Istanbul]: https://github.com/gotwarlost/istanbul\n\n[Browsers]: http://karma-runner.github.io/0.8/config/browsers.html\n[Versioning]: http://karma-runner.github.io/0.8/about/versioning.html\n[Configuration File Overview]: http://karma-runner.github.io/0.8/config/configuration-file.html\n[docs]: http://karma-runner.github.io\n[Docs]: http://karma-runner.github.io\n[website]: http://karma-runner.github.io\n", + "readmeFilename": "README.md", + "_id": "karma@0.10.6", + "_from": "karma@>=0.9" +} diff --git a/node_modules/karma/static/client.html b/node_modules/karma/static/client.html new file mode 100644 index 00000000..5a139223 --- /dev/null +++ b/node_modules/karma/static/client.html @@ -0,0 +1,115 @@ + + + + + Karma + + + + + + + + +
    + + + + + + + diff --git a/node_modules/karma/static/context.html b/node_modules/karma/static/context.html new file mode 100644 index 00000000..a1d6cb9e --- /dev/null +++ b/node_modules/karma/static/context.html @@ -0,0 +1,30 @@ + + + + + + + + + + + + %SCRIPTS% + + + diff --git a/node_modules/karma/static/debug.html b/node_modules/karma/static/debug.html new file mode 100644 index 00000000..772c1fd9 --- /dev/null +++ b/node_modules/karma/static/debug.html @@ -0,0 +1,48 @@ + + + + + Karma DEBUG RUNNER + + + + + + + + + %SCRIPTS% + + + diff --git a/node_modules/karma/static/karma.js b/node_modules/karma/static/karma.js new file mode 100644 index 00000000..d23a1e4f --- /dev/null +++ b/node_modules/karma/static/karma.js @@ -0,0 +1,294 @@ +(function(window, document, io) { + +var CONTEXT_URL = 'context.html'; +var VERSION = '%KARMA_VERSION%'; +var KARMA_URL_ROOT = '%KARMA_URL_ROOT%'; + +// connect socket.io +// https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO +var socket = io.connect('http://' + location.host, { + 'reconnection delay': 500, + 'reconnection limit': 2000, + 'resource': KARMA_URL_ROOT.substr(1) + 'socket.io', + 'sync disconnect on unload': true, + 'max reconnection attempts': Infinity +}); + +var browsersElement = document.getElementById('browsers'); +socket.on('info', function(browsers) { + var items = [], status; + for (var i = 0; i < browsers.length; i++) { + status = browsers[i].isReady ? 'idle' : 'executing'; + items.push('
  • ' + browsers[i].name + ' is ' + status + '
  • '); + } + browsersElement.innerHTML = items.join('\n'); +}); +socket.on('disconnect', function() { + browsersElement.innerHTML = ''; +}); + +var titleElement = document.getElementById('title'); +var bannerElement = document.getElementById('banner'); +var updateStatus = function(status) { + return function(param) { + var paramStatus = param ? status.replace('$', param) : status; + titleElement.innerHTML = 'Karma v' + VERSION + ' - ' + paramStatus; + bannerElement.className = status === 'connected' ? 'online' : 'offline'; + }; +}; + +socket.on('connect', updateStatus('connected')); +socket.on('disconnect', updateStatus('disconnected')); +socket.on('reconnecting', updateStatus('reconnecting in $ ms...')); +socket.on('reconnect', updateStatus('re-connected')); +socket.on('reconnect_failed', updateStatus('failed to reconnect')); + +var instanceOf = function(value, constructorName) { + return Object.prototype.toString.apply(value) === '[object ' + constructorName + ']'; +}; + +/* jshint unused: false */ +var Karma = function(socket, context, navigator, location) { + var hasError = false; + var store = {}; + var self = this; + + var resultsBufferLimit = 1; + var resultsBuffer = []; + + this.VERSION = VERSION; + this.config = {}; + + this.setupContext = function(contextWindow) { + if (hasError) { + return; + } + + var getConsole = function(currentWindow) { + return currentWindow.console || { + log: function() {}, + info: function() {}, + warn: function() {}, + error: function() {}, + debug: function() {} + }; + }; + + contextWindow.__karma__ = this; + + // This causes memory leak in Chrome (17.0.963.66) + contextWindow.onerror = function() { + return contextWindow.__karma__.error.apply(contextWindow.__karma__, arguments); + }; + + contextWindow.onbeforeunload = function(e, b) { + if (context.src !== 'about:blank') { + // TODO(vojta): show what test (with explanation about jasmine.UPDATE_INTERVAL) + contextWindow.__karma__.error('Some of your tests did a full page reload!'); + } + }; + + // patch the console + var localConsole = contextWindow.console = getConsole(contextWindow); + var browserConsoleLog = localConsole.log; + var logMethods = ['log', 'info', 'warn', 'error', 'debug']; + var patchConsoleMethod = function(method) { + var orig = localConsole[method]; + if (!orig) { + return; + } + localConsole[method] = function() { + self.log(method, arguments); + return Function.prototype.apply.call(orig, localConsole, arguments); + }; + }; + for (var i = 0; i < logMethods.length; i++) { + patchConsoleMethod(logMethods[i]); + } + + contextWindow.dump = function() { + self.log('dump', arguments); + }; + + contextWindow.alert = function(msg) { + self.log('alert', [msg]); + }; + }; + + this.log = function(type, args) { + var values = []; + + for (var i = 0; i < args.length; i++) { + values.push(this.stringify(args[i], 3)); + } + + this.info({log: values.join(', '), type: type}); + }; + + this.stringify = function(obj, depth) { + + if (depth === 0) { + return '...'; + } + + if (obj === null) { + return 'null'; + } + + switch (typeof obj) { + case 'string': + return '\'' + obj + '\''; + case 'undefined': + return 'undefined'; + case 'function': + return obj.toString().replace(/\{[\s\S]*\}/, '{ ... }'); + case 'boolean': + return obj ? 'true' : 'false'; + case 'object': + var strs = []; + if (instanceOf(obj, 'Array')) { + strs.push('['); + for (var i = 0, ii = obj.length; i < ii; i++) { + if (i) { + strs.push(', '); + } + strs.push(this.stringify(obj[i], depth - 1)); + } + strs.push(']'); + } else if (instanceOf(obj, 'Date')) { + return obj.toString(); + } else if (instanceOf(obj, 'Text')) { + return obj.nodeValue; + } else if (instanceOf(obj, 'Comment')) { + return ''; + } else if (obj.outerHTML) { + return obj.outerHTML; + } else { + strs.push(obj.constructor.name); + strs.push('{'); + var first = true; + for(var key in obj) { + if (obj.hasOwnProperty(key)) { + if (first) { first = false; } else { strs.push(', '); } + strs.push(key + ': ' + this.stringify(obj[key], depth - 1)); + } + } + strs.push('}'); + } + return strs.join(''); + default: + return obj; + } + }; + + + var clearContext = function() { + context.src = 'about:blank'; + }; + + // error during js file loading (most likely syntax error) + // we are not going to execute at all + this.error = function(msg, url, line) { + hasError = true; + socket.emit('error', url ? msg + '\nat ' + url + (line ? ':' + line : '') : msg); + this.complete(); + return false; + }; + + this.result = function(result) { + if (resultsBufferLimit === 1) { + return socket.emit('result', result); + } + + resultsBuffer.push(result); + + if (resultsBuffer.length === resultsBufferLimit) { + socket.emit('result', resultsBuffer); + resultsBuffer = []; + } + }; + + this.complete = function(result) { + if (resultsBuffer.length) { + socket.emit('result', resultsBuffer); + resultsBuffer = []; + } + + // give the browser some time to breath, there could be a page reload, but because a bunch of + // tests could run in the same event loop, we wouldn't notice. + setTimeout(function() { + socket.emit('complete', result || {}); + clearContext(); + }, 0); + }; + + this.info = function(info) { + socket.emit('info', info); + }; + + // all files loaded, let's start the execution + this.loaded = function() { + // has error -> cancel + if (!hasError) { + this.start(this.config); + } + + // remove reference to child iframe + this.start = null; + }; + + this.store = function(key, value) { + if (typeof value === 'undefined') { + return store[key]; + } + + if (Object.prototype.toString.apply(value) === '[object Array]') { + var s = store[key] = []; + for (var i = 0; i < value.length; i++) { + s.push(value[i]); + } + } else { + // TODO(vojta): clone objects + deep + store[key] = value; + } + }; + + // supposed to be overriden by the context + // TODO(vojta): support multiple callbacks (queue) + this.start = this.complete; + + socket.on('execute', function(cfg) { + // reset hasError and reload the iframe + hasError = false; + self.config = cfg; + context.src = CONTEXT_URL; + + // clear the console before run + // works only on FF (Safari, Chrome do not allow to clear console from js source) + if (window.console && window.console.clear) { + window.console.clear(); + } + }); + + // report browser name, id + socket.on('connect', function() { + var transport = socket.socket.transport.name; + + // TODO(vojta): make resultsBufferLimit configurable + if (transport === 'websocket' || transport === 'flashsocket') { + resultsBufferLimit = 1; + } else { + resultsBufferLimit = 50; + } + + socket.emit('register', { + name: navigator.userAgent, + id: parseInt((location.search.match(/\?id=(.*)/) || [])[1], 10) || null + }); + }); +}; + + +window.karma = new Karma(socket, document.getElementById('context'), window.navigator, window.location); + +})(window, document, window.io); diff --git a/node_modules/karma/test-results.xml b/node_modules/karma/test-results.xml new file mode 100644 index 00000000..e9d7c52f --- /dev/null +++ b/node_modules/karma/test-results.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/karma/thesis.pdf b/node_modules/karma/thesis.pdf new file mode 100644 index 0000000000000000000000000000000000000000..76cf7cc8f2d74477ff54a7dcaf81d3324b743cd6 GIT binary patch literal 689519 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⋘I8^wXq5X? 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 z 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 z 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%0DvYI@7p2J|VPPqn zcByoUMgS}tVg!GS0PJfzugYNlfnP9hTDE>#!({@5l8Y}cyVC%?nV(ea{t+iCOCO9h zR*18irVPyzh^iRdT2fENkj2{pUz?E(+qp%Ym=k!LS<-Z^Yx!yIL%>;M_|~Oof01m! z&|AgaSo(VVk!MmB9G*HV7l8)*Ez@rP4z9F8s(gBjTUKfX4)}_39{B?XKLqt0v0W`G zSd-(1?QxQVb>~X#xO()QFnsu5w#E`2AH=^@k?ANov@${+Ioj}9KBK~{PZK>6$*Oe# z2X50MI_Aop{1N1ygsZE6 zGwt-T>k(rIr)$bto!(l6iGmPnEoQ|US;efIg9X$hdS^DDz8$Reymb6skMBNElw?xzRcfZ6=NFJ9NqVLx z`*|I0WEq53w9-PLGB|JOeWW?ZaUrIe# zmA?V^M=)zXdGNV{f2mcjF-=jeIRq2KnKBge@7gVdcGe-dKm_g9jr4sfsQJ+2{9^Et z8KV0aD+n#K9(oNn>Jdm@^1~X{Ut7^OwBUNz>!18i98Q-7N`e|VaBM56W)rp#WH{N@ zJrX6i!cCGaaTFs33j6ABX0|Klh+>X3aYvsf7q8p+H}o7{GDp7`jdu*YNJot9SSRPF zTx2NaUpPB{El$}Vk5ZYunVZIylqq}D!NmM{{X&4M%N=UMh8E~v%S7cRMrPwDZ3l`M zzxE4I)lWf77uZH4G-$xGBFy_R52tPSI* zTDx$eONj82W&=!yX%i93Vr;IuE?BRaxB%EI(sCH?qpPK|(YM7WRJtw;UN;BezRJox z=`>_)2$C`~+#QMcnY|daa|$;q+t`33mP$LR=7+1)CG#le7g|7p=yJ}vU#CnL)0}Ws zx3i@ChHrC&EeL-*5E%Vh7)N{MYJ_cPINd#00HHcm@Le~p_J*1Gz5Q#m_s1JJCOS?T zj2lf~;Xb5>@Qu_-kqtoMPI>Bfk5CwQOfg}HMMy>ced(&z08e!k6mH5zG@Q<6IIn`5 zbd~B%7J*XO96h5WYIpPMD)wj)oJpQM5A8t;K6Zuc$Y&GV{0rMXl+w?@G1>+;XV-*? zq}(5e)X}h})PE+G!K0lfZBM?eg4z1oCi#_ z$U4is<=7%dPzYqVjW0^G5KMr(%eQr=I;{&-hNx(I

    S*ghNOBc;PWT(9( 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 V+x?Mv`FS}6c#vpmWmIL6{s&%lEHeNA literal 0 HcmV?d00001 diff --git a/node_modules/requirejs/README.md b/node_modules/requirejs/README.md new file mode 100644 index 00000000..545b31d7 --- /dev/null +++ b/node_modules/requirejs/README.md @@ -0,0 +1,9 @@ +# requirejs + +RequireJS for use in Node. includes: + +* r.js: the RequireJS optimizer, and AMD runtime for use in Node. +* require.js: The browser-based AMD loader. + +More information at http://requirejs.org + diff --git a/node_modules/requirejs/bin/r.js b/node_modules/requirejs/bin/r.js new file mode 100755 index 00000000..55028dad --- /dev/null +++ b/node_modules/requirejs/bin/r.js @@ -0,0 +1,26059 @@ +#!/usr/bin/env node +/** + * @license r.js 2.1.9 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/* + * This is a bootstrap script to allow running RequireJS in the command line + * in either a Java/Rhino or Node environment. It is modified by the top-level + * dist.js file to inject other files to completely enable this file. It is + * the shell of the r.js file. + */ + +/*jslint evil: true, nomen: true, sloppy: true */ +/*global readFile: true, process: false, Packages: false, print: false, +console: false, java: false, module: false, requirejsVars, navigator, +document, importScripts, self, location, Components, FileUtils */ + +var requirejs, require, define, xpcUtil; +(function (console, args, readFileFunc) { + var fileName, env, fs, vm, path, exec, rhinoContext, dir, nodeRequire, + nodeDefine, exists, reqMain, loadedOptimizedLib, existsForNode, Cc, Ci, + version = '2.1.9', + jsSuffixRegExp = /\.js$/, + commandOption = '', + useLibLoaded = {}, + //Used by jslib/rhino/args.js + rhinoArgs = args, + //Used by jslib/xpconnect/args.js + xpconnectArgs = args, + readFile = typeof readFileFunc !== 'undefined' ? readFileFunc : null; + + function showHelp() { + console.log('See https://github.com/jrburke/r.js for usage.'); + } + + if ((typeof navigator !== 'undefined' && typeof document !== 'undefined') || + (typeof importScripts !== 'undefined' && typeof self !== 'undefined')) { + env = 'browser'; + + readFile = function (path) { + return fs.readFileSync(path, 'utf8'); + }; + + exec = function (string) { + return eval(string); + }; + + exists = function () { + console.log('x.js exists not applicable in browser env'); + return false; + }; + + } else if (typeof Packages !== 'undefined') { + env = 'rhino'; + + fileName = args[0]; + + if (fileName && fileName.indexOf('-') === 0) { + commandOption = fileName.substring(1); + fileName = args[1]; + } + + //Set up execution context. + rhinoContext = Packages.org.mozilla.javascript.ContextFactory.getGlobal().enterContext(); + + exec = function (string, name) { + return rhinoContext.evaluateString(this, string, name, 0, null); + }; + + exists = function (fileName) { + return (new java.io.File(fileName)).exists(); + }; + + //Define a console.log for easier logging. Don't + //get fancy though. + if (typeof console === 'undefined') { + console = { + log: function () { + print.apply(undefined, arguments); + } + }; + } + } else if (typeof process !== 'undefined' && process.versions && !!process.versions.node) { + env = 'node'; + + //Get the fs module via Node's require before it + //gets replaced. Used in require/node.js + fs = require('fs'); + vm = require('vm'); + path = require('path'); + //In Node 0.7+ existsSync is on fs. + existsForNode = fs.existsSync || path.existsSync; + + nodeRequire = require; + nodeDefine = define; + reqMain = require.main; + + //Temporarily hide require and define to allow require.js to define + //them. + require = undefined; + define = undefined; + + readFile = function (path) { + return fs.readFileSync(path, 'utf8'); + }; + + exec = function (string, name) { + return vm.runInThisContext(this.requirejsVars.require.makeNodeWrapper(string), + name ? fs.realpathSync(name) : ''); + }; + + exists = function (fileName) { + return existsForNode(fileName); + }; + + + fileName = process.argv[2]; + + if (fileName && fileName.indexOf('-') === 0) { + commandOption = fileName.substring(1); + fileName = process.argv[3]; + } + } else if (typeof Components !== 'undefined' && Components.classes && Components.interfaces) { + env = 'xpconnect'; + + Components.utils['import']('resource://gre/modules/FileUtils.jsm'); + Cc = Components.classes; + Ci = Components.interfaces; + + fileName = args[0]; + + if (fileName && fileName.indexOf('-') === 0) { + commandOption = fileName.substring(1); + fileName = args[1]; + } + + xpcUtil = { + isWindows: ('@mozilla.org/windows-registry-key;1' in Cc), + cwd: function () { + return FileUtils.getFile("CurWorkD", []).path; + }, + + //Remove . and .. from paths, normalize on front slashes + normalize: function (path) { + //There has to be an easier way to do this. + var i, part, ary, + firstChar = path.charAt(0); + + if (firstChar !== '/' && + firstChar !== '\\' && + path.indexOf(':') === -1) { + //A relative path. Use the current working directory. + path = xpcUtil.cwd() + '/' + path; + } + + ary = path.replace(/\\/g, '/').split('/'); + + for (i = 0; i < ary.length; i += 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + ary.splice(i - 1, 2); + i -= 2; + } + } + return ary.join('/'); + }, + + xpfile: function (path) { + var fullPath; + try { + fullPath = xpcUtil.normalize(path); + if (xpcUtil.isWindows) { + fullPath = fullPath.replace(/\//g, '\\'); + } + return new FileUtils.File(fullPath); + } catch (e) { + throw new Error((fullPath || path) + ' failed: ' + e); + } + }, + + readFile: function (/*String*/path, /*String?*/encoding) { + //A file read function that can deal with BOMs + encoding = encoding || "utf-8"; + + var inStream, convertStream, + readData = {}, + fileObj = xpcUtil.xpfile(path); + + //XPCOM, you so crazy + try { + inStream = Cc['@mozilla.org/network/file-input-stream;1'] + .createInstance(Ci.nsIFileInputStream); + inStream.init(fileObj, 1, 0, false); + + convertStream = Cc['@mozilla.org/intl/converter-input-stream;1'] + .createInstance(Ci.nsIConverterInputStream); + convertStream.init(inStream, encoding, inStream.available(), + Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); + + convertStream.readString(inStream.available(), readData); + return readData.value; + } catch (e) { + throw new Error((fileObj && fileObj.path || '') + ': ' + e); + } finally { + if (convertStream) { + convertStream.close(); + } + if (inStream) { + inStream.close(); + } + } + } + }; + + readFile = xpcUtil.readFile; + + exec = function (string) { + return eval(string); + }; + + exists = function (fileName) { + return xpcUtil.xpfile(fileName).exists(); + }; + + //Define a console.log for easier logging. Don't + //get fancy though. + if (typeof console === 'undefined') { + console = { + log: function () { + print.apply(undefined, arguments); + } + }; + } + } + + /** vim: et:ts=4:sw=4:sts=4 + * @license RequireJS 2.1.9 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ +//Not using strict: uneven strict support in browsers, #392, and causes +//problems with requirejs.exec()/transpiler plugins that may not be strict. +/*jslint regexp: true, nomen: true, sloppy: true */ +/*global window, navigator, document, importScripts, setTimeout, opera */ + + +(function (global) { + var req, s, head, baseElement, dataMain, src, + interactiveScript, currentlyAddingScript, mainScript, subPath, + version = '2.1.9', + commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, + cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, + jsSuffixRegExp = /\.js$/, + currDirRegExp = /^\.\//, + op = Object.prototype, + ostring = op.toString, + hasOwn = op.hasOwnProperty, + ap = Array.prototype, + apsp = ap.splice, + isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document), + isWebWorker = !isBrowser && typeof importScripts !== 'undefined', + //PS3 indicates loaded and complete, but need to wait for complete + //specifically. Sequence is 'loading', 'loaded', execution, + // then 'complete'. The UA check is unfortunate, but not sure how + //to feature test w/o causing perf issues. + readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? + /^complete$/ : /^(complete|loaded)$/, + defContextName = '_', + //Oh the tragedy, detecting opera. See the usage of isOpera for reason. + isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]', + contexts = {}, + cfg = {}, + globalDefQueue = [], + useInteractive = false; + + function isFunction(it) { + return ostring.call(it) === '[object Function]'; + } + + function isArray(it) { + return ostring.call(it) === '[object Array]'; + } + + /** + * Helper function for iterating over an array. If the func returns + * a true value, it will break out of the loop. + */ + function each(ary, func) { + if (ary) { + var i; + for (i = 0; i < ary.length; i += 1) { + if (ary[i] && func(ary[i], i, ary)) { + break; + } + } + } + } + + /** + * Helper function for iterating over an array backwards. If the func + * returns a true value, it will break out of the loop. + */ + function eachReverse(ary, func) { + if (ary) { + var i; + for (i = ary.length - 1; i > -1; i -= 1) { + if (ary[i] && func(ary[i], i, ary)) { + break; + } + } + } + } + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + function getOwn(obj, prop) { + return hasProp(obj, prop) && obj[prop]; + } + + /** + * Cycles over properties in an object and calls a function for each + * property value. If the function returns a truthy value, then the + * iteration is stopped. + */ + function eachProp(obj, func) { + var prop; + for (prop in obj) { + if (hasProp(obj, prop)) { + if (func(obj[prop], prop)) { + break; + } + } + } + } + + /** + * Simple function to mix in properties from source into target, + * but only if target does not already have a property of the same name. + */ + function mixin(target, source, force, deepStringMixin) { + if (source) { + eachProp(source, function (value, prop) { + if (force || !hasProp(target, prop)) { + if (deepStringMixin && typeof value !== 'string') { + if (!target[prop]) { + target[prop] = {}; + } + mixin(target[prop], value, force, deepStringMixin); + } else { + target[prop] = value; + } + } + }); + } + return target; + } + + //Similar to Function.prototype.bind, but the 'this' object is specified + //first, since it is easier to read/figure out what 'this' will be. + function bind(obj, fn) { + return function () { + return fn.apply(obj, arguments); + }; + } + + function scripts() { + return document.getElementsByTagName('script'); + } + + function defaultOnError(err) { + throw err; + } + + //Allow getting a global that expressed in + //dot notation, like 'a.b.c'. + function getGlobal(value) { + if (!value) { + return value; + } + var g = global; + each(value.split('.'), function (part) { + g = g[part]; + }); + return g; + } + + /** + * Constructs an error with a pointer to an URL with more information. + * @param {String} id the error ID that maps to an ID on a web page. + * @param {String} message human readable error. + * @param {Error} [err] the original error, if there is one. + * + * @returns {Error} + */ + function makeError(id, msg, err, requireModules) { + var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); + e.requireType = id; + e.requireModules = requireModules; + if (err) { + e.originalError = err; + } + return e; + } + + if (typeof define !== 'undefined') { + //If a define is already in play via another AMD loader, + //do not overwrite. + return; + } + + if (typeof requirejs !== 'undefined') { + if (isFunction(requirejs)) { + //Do not overwrite and existing requirejs instance. + return; + } + cfg = requirejs; + requirejs = undefined; + } + + //Allow for a require config object + if (typeof require !== 'undefined' && !isFunction(require)) { + //assume it is a config object. + cfg = require; + require = undefined; + } + + function newContext(contextName) { + var inCheckLoaded, Module, context, handlers, + checkLoadedTimeoutId, + config = { + //Defaults. Do not set a default for map + //config to speed up normalize(), which + //will run faster if there is no default. + waitSeconds: 7, + baseUrl: './', + paths: {}, + pkgs: {}, + shim: {}, + config: {} + }, + registry = {}, + //registry of just enabled modules, to speed + //cycle breaking code when lots of modules + //are registered, but not activated. + enabledRegistry = {}, + undefEvents = {}, + defQueue = [], + defined = {}, + urlFetched = {}, + requireCounter = 1, + unnormalizedCounter = 1; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i += 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @param {Boolean} applyMap apply the map config to the value. Should + * only be done if this normalization is for a dependency ID. + * @returns {String} normalized name + */ + function normalize(name, baseName, applyMap) { + var pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment, + foundMap, foundI, foundStarMap, starI, + baseParts = baseName && baseName.split('/'), + normalizedBaseParts = baseParts, + map = config.map, + starMap = map && map['*']; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + if (getOwn(config.pkgs, baseName)) { + //If the baseName is a package name, then just treat it as one + //name to concat the name with. + normalizedBaseParts = baseParts = [baseName]; + } else { + //Convert baseName to array, and lop off the last part, + //so that . matches that 'directory' and not name of the baseName's + //module. For instance, baseName of 'one/two/three', maps to + //'one/two/three.js', but we want the directory, 'one/two' for + //this normalization. + normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); + } + + name = normalizedBaseParts.concat(name.split('/')); + trimDots(name); + + //Some use of packages may use a . path to reference the + //'main' module name, so normalize for that. + pkgConfig = getOwn(config.pkgs, (pkgName = name[0])); + name = name.join('/'); + if (pkgConfig && name === pkgName + '/' + pkgConfig.main) { + name = pkgName; + } + } else if (name.indexOf('./') === 0) { + // No baseName, so this is ID is resolved relative + // to baseUrl, pull off the leading dot. + name = name.substring(2); + } + } + + //Apply map config if available. + if (applyMap && map && (baseParts || starMap)) { + nameParts = name.split('/'); + + for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join('/'); + + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = getOwn(map, baseParts.slice(0, j).join('/')); + + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = getOwn(mapValue, nameSegment); + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break; + } + } + } + } + + if (foundMap) { + break; + } + + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) { + foundStarMap = getOwn(starMap, nameSegment); + starI = i; + } + } + + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } + } + + return name; + } + + function removeScript(name) { + if (isBrowser) { + each(scripts(), function (scriptNode) { + if (scriptNode.getAttribute('data-requiremodule') === name && + scriptNode.getAttribute('data-requirecontext') === context.contextName) { + scriptNode.parentNode.removeChild(scriptNode); + return true; + } + }); + } + } + + function hasPathFallback(id) { + var pathConfig = getOwn(config.paths, id); + if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) { + //Pop off the first array value, since it failed, and + //retry + pathConfig.shift(); + context.require.undef(id); + context.require([id]); + return true; + } + } + + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; + } + + /** + * Creates a module mapping that includes plugin prefix, module + * name, and path. If parentModuleMap is provided it will + * also normalize the name via require.normalize() + * + * @param {String} name the module name + * @param {String} [parentModuleMap] parent module map + * for the module name, used to resolve relative names. + * @param {Boolean} isNormalized: is the ID already normalized. + * This is true if this call is done for a define() module ID. + * @param {Boolean} applyMap: apply the map config to the ID. + * Should only be true if this map is for a dependency. + * + * @returns {Object} + */ + function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { + var url, pluginModule, suffix, nameParts, + prefix = null, + parentName = parentModuleMap ? parentModuleMap.name : null, + originalName = name, + isDefine = true, + normalizedName = ''; + + //If no name, then it means it is a require call, generate an + //internal name. + if (!name) { + isDefine = false; + name = '_@r' + (requireCounter += 1); + } + + nameParts = splitPrefix(name); + prefix = nameParts[0]; + name = nameParts[1]; + + if (prefix) { + prefix = normalize(prefix, parentName, applyMap); + pluginModule = getOwn(defined, prefix); + } + + //Account for relative paths if there is a base name. + if (name) { + if (prefix) { + if (pluginModule && pluginModule.normalize) { + //Plugin is loaded, use its normalize method. + normalizedName = pluginModule.normalize(name, function (name) { + return normalize(name, parentName, applyMap); + }); + } else { + normalizedName = normalize(name, parentName, applyMap); + } + } else { + //A regular module. + normalizedName = normalize(name, parentName, applyMap); + + //Normalized name may be a plugin ID due to map config + //application in normalize. The map config values must + //already be normalized, so do not need to redo that part. + nameParts = splitPrefix(normalizedName); + prefix = nameParts[0]; + normalizedName = nameParts[1]; + isNormalized = true; + + url = context.nameToUrl(normalizedName); + } + } + + //If the id is a plugin id that cannot be determined if it needs + //normalization, stamp it with a unique ID so two matching relative + //ids that may conflict can be separate. + suffix = prefix && !pluginModule && !isNormalized ? + '_unnormalized' + (unnormalizedCounter += 1) : + ''; + + return { + prefix: prefix, + name: normalizedName, + parentMap: parentModuleMap, + unnormalized: !!suffix, + url: url, + originalName: originalName, + isDefine: isDefine, + id: (prefix ? + prefix + '!' + normalizedName : + normalizedName) + suffix + }; + } + + function getModule(depMap) { + var id = depMap.id, + mod = getOwn(registry, id); + + if (!mod) { + mod = registry[id] = new context.Module(depMap); + } + + return mod; + } + + function on(depMap, name, fn) { + var id = depMap.id, + mod = getOwn(registry, id); + + if (hasProp(defined, id) && + (!mod || mod.defineEmitComplete)) { + if (name === 'defined') { + fn(defined[id]); + } + } else { + mod = getModule(depMap); + if (mod.error && name === 'error') { + fn(mod.error); + } else { + mod.on(name, fn); + } + } + } + + function onError(err, errback) { + var ids = err.requireModules, + notified = false; + + if (errback) { + errback(err); + } else { + each(ids, function (id) { + var mod = getOwn(registry, id); + if (mod) { + //Set error on module, so it skips timeout checks. + mod.error = err; + if (mod.events.error) { + notified = true; + mod.emit('error', err); + } + } + }); + + if (!notified) { + req.onError(err); + } + } + } + + /** + * Internal method to transfer globalQueue items to this context's + * defQueue. + */ + function takeGlobalQueue() { + //Push all the globalDefQueue items into the context's defQueue + if (globalDefQueue.length) { + //Array splice in the values since the context code has a + //local var ref to defQueue, so cannot just reassign the one + //on context. + apsp.apply(defQueue, + [defQueue.length - 1, 0].concat(globalDefQueue)); + globalDefQueue = []; + } + } + + handlers = { + 'require': function (mod) { + if (mod.require) { + return mod.require; + } else { + return (mod.require = context.makeRequire(mod.map)); + } + }, + 'exports': function (mod) { + mod.usingExports = true; + if (mod.map.isDefine) { + if (mod.exports) { + return mod.exports; + } else { + return (mod.exports = defined[mod.map.id] = {}); + } + } + }, + 'module': function (mod) { + if (mod.module) { + return mod.module; + } else { + return (mod.module = { + id: mod.map.id, + uri: mod.map.url, + config: function () { + var c, + pkg = getOwn(config.pkgs, mod.map.id); + // For packages, only support config targeted + // at the main module. + c = pkg ? getOwn(config.config, mod.map.id + '/' + pkg.main) : + getOwn(config.config, mod.map.id); + return c || {}; + }, + exports: defined[mod.map.id] + }); + } + } + }; + + function cleanRegistry(id) { + //Clean up machinery used for waiting modules. + delete registry[id]; + delete enabledRegistry[id]; + } + + function breakCycle(mod, traced, processed) { + var id = mod.map.id; + + if (mod.error) { + mod.emit('error', mod.error); + } else { + traced[id] = true; + each(mod.depMaps, function (depMap, i) { + var depId = depMap.id, + dep = getOwn(registry, depId); + + //Only force things that have not completed + //being defined, so still in the registry, + //and only if it has not been matched up + //in the module already. + if (dep && !mod.depMatched[i] && !processed[depId]) { + if (getOwn(traced, depId)) { + mod.defineDep(i, defined[depId]); + mod.check(); //pass false? + } else { + breakCycle(dep, traced, processed); + } + } + }); + processed[id] = true; + } + } + + function checkLoaded() { + var map, modId, err, usingPathFallback, + waitInterval = config.waitSeconds * 1000, + //It is possible to disable the wait interval by using waitSeconds of 0. + expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), + noLoads = [], + reqCalls = [], + stillLoading = false, + needCycleCheck = true; + + //Do not bother if this call was a result of a cycle break. + if (inCheckLoaded) { + return; + } + + inCheckLoaded = true; + + //Figure out the state of all the modules. + eachProp(enabledRegistry, function (mod) { + map = mod.map; + modId = map.id; + + //Skip things that are not enabled or in error state. + if (!mod.enabled) { + return; + } + + if (!map.isDefine) { + reqCalls.push(mod); + } + + if (!mod.error) { + //If the module should be executed, and it has not + //been inited and time is up, remember it. + if (!mod.inited && expired) { + if (hasPathFallback(modId)) { + usingPathFallback = true; + stillLoading = true; + } else { + noLoads.push(modId); + removeScript(modId); + } + } else if (!mod.inited && mod.fetched && map.isDefine) { + stillLoading = true; + if (!map.prefix) { + //No reason to keep looking for unfinished + //loading. If the only stillLoading is a + //plugin resource though, keep going, + //because it may be that a plugin resource + //is waiting on a non-plugin cycle. + return (needCycleCheck = false); + } + } + } + }); + + if (expired && noLoads.length) { + //If wait time expired, throw error of unloaded modules. + err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads); + err.contextName = context.contextName; + return onError(err); + } + + //Not expired, check for a cycle. + if (needCycleCheck) { + each(reqCalls, function (mod) { + breakCycle(mod, {}, {}); + }); + } + + //If still waiting on loads, and the waiting load is something + //other than a plugin resource, or there are still outstanding + //scripts, then just try back later. + if ((!expired || usingPathFallback) && stillLoading) { + //Something is still waiting to load. Wait for it, but only + //if a timeout is not already in effect. + if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { + checkLoadedTimeoutId = setTimeout(function () { + checkLoadedTimeoutId = 0; + checkLoaded(); + }, 50); + } + } + + inCheckLoaded = false; + } + + Module = function (map) { + this.events = getOwn(undefEvents, map.id) || {}; + this.map = map; + this.shim = getOwn(config.shim, map.id); + this.depExports = []; + this.depMaps = []; + this.depMatched = []; + this.pluginMaps = {}; + this.depCount = 0; + + /* this.exports this.factory + this.depMaps = [], + this.enabled, this.fetched + */ + }; + + Module.prototype = { + init: function (depMaps, factory, errback, options) { + options = options || {}; + + //Do not do more inits if already done. Can happen if there + //are multiple define calls for the same module. That is not + //a normal, common case, but it is also not unexpected. + if (this.inited) { + return; + } + + this.factory = factory; + + if (errback) { + //Register for errors on this module. + this.on('error', errback); + } else if (this.events.error) { + //If no errback already, but there are error listeners + //on this module, set up an errback to pass to the deps. + errback = bind(this, function (err) { + this.emit('error', err); + }); + } + + //Do a copy of the dependency array, so that + //source inputs are not modified. For example + //"shim" deps are passed in here directly, and + //doing a direct modification of the depMaps array + //would affect that config. + this.depMaps = depMaps && depMaps.slice(0); + + this.errback = errback; + + //Indicate this module has be initialized + this.inited = true; + + this.ignore = options.ignore; + + //Could have option to init this module in enabled mode, + //or could have been previously marked as enabled. However, + //the dependencies are not known until init is called. So + //if enabled previously, now trigger dependencies as enabled. + if (options.enabled || this.enabled) { + //Enable this module and dependencies. + //Will call this.check() + this.enable(); + } else { + this.check(); + } + }, + + defineDep: function (i, depExports) { + //Because of cycles, defined callback for a given + //export can be called more than once. + if (!this.depMatched[i]) { + this.depMatched[i] = true; + this.depCount -= 1; + this.depExports[i] = depExports; + } + }, + + fetch: function () { + if (this.fetched) { + return; + } + this.fetched = true; + + context.startTime = (new Date()).getTime(); + + var map = this.map; + + //If the manager is for a plugin managed resource, + //ask the plugin to load it now. + if (this.shim) { + context.makeRequire(this.map, { + enableBuildCallback: true + })(this.shim.deps || [], bind(this, function () { + return map.prefix ? this.callPlugin() : this.load(); + })); + } else { + //Regular dependency. + return map.prefix ? this.callPlugin() : this.load(); + } + }, + + load: function () { + var url = this.map.url; + + //Regular dependency. + if (!urlFetched[url]) { + urlFetched[url] = true; + context.load(this.map.id, url); + } + }, + + /** + * Checks if the module is ready to define itself, and if so, + * define it. + */ + check: function () { + if (!this.enabled || this.enabling) { + return; + } + + var err, cjsModule, + id = this.map.id, + depExports = this.depExports, + exports = this.exports, + factory = this.factory; + + if (!this.inited) { + this.fetch(); + } else if (this.error) { + this.emit('error', this.error); + } else if (!this.defining) { + //The factory could trigger another require call + //that would result in checking this module to + //define itself again. If already in the process + //of doing that, skip this work. + this.defining = true; + + if (this.depCount < 1 && !this.defined) { + if (isFunction(factory)) { + //If there is an error listener, favor passing + //to that instead of throwing an error. However, + //only do it for define()'d modules. require + //errbacks should not be called for failures in + //their callbacks (#699). However if a global + //onError is set, use that. + if ((this.events.error && this.map.isDefine) || + req.onError !== defaultOnError) { + try { + exports = context.execCb(id, factory, depExports, exports); + } catch (e) { + err = e; + } + } else { + exports = context.execCb(id, factory, depExports, exports); + } + + if (this.map.isDefine) { + //If setting exports via 'module' is in play, + //favor that over return value and exports. After that, + //favor a non-undefined return value over exports use. + cjsModule = this.module; + if (cjsModule && + cjsModule.exports !== undefined && + //Make sure it is not already the exports value + cjsModule.exports !== this.exports) { + exports = cjsModule.exports; + } else if (exports === undefined && this.usingExports) { + //exports already set the defined value. + exports = this.exports; + } + } + + if (err) { + err.requireMap = this.map; + err.requireModules = this.map.isDefine ? [this.map.id] : null; + err.requireType = this.map.isDefine ? 'define' : 'require'; + return onError((this.error = err)); + } + + } else { + //Just a literal value + exports = factory; + } + + this.exports = exports; + + if (this.map.isDefine && !this.ignore) { + defined[id] = exports; + + if (req.onResourceLoad) { + req.onResourceLoad(context, this.map, this.depMaps); + } + } + + //Clean up + cleanRegistry(id); + + this.defined = true; + } + + //Finished the define stage. Allow calling check again + //to allow define notifications below in the case of a + //cycle. + this.defining = false; + + if (this.defined && !this.defineEmitted) { + this.defineEmitted = true; + this.emit('defined', this.exports); + this.defineEmitComplete = true; + } + + } + }, + + callPlugin: function () { + var map = this.map, + id = map.id, + //Map already normalized the prefix. + pluginMap = makeModuleMap(map.prefix); + + //Mark this as a dependency for this plugin, so it + //can be traced for cycles. + this.depMaps.push(pluginMap); + + on(pluginMap, 'defined', bind(this, function (plugin) { + var load, normalizedMap, normalizedMod, + name = this.map.name, + parentName = this.map.parentMap ? this.map.parentMap.name : null, + localRequire = context.makeRequire(map.parentMap, { + enableBuildCallback: true + }); + + //If current map is not normalized, wait for that + //normalized name to load instead of continuing. + if (this.map.unnormalized) { + //Normalize the ID if the plugin allows it. + if (plugin.normalize) { + name = plugin.normalize(name, function (name) { + return normalize(name, parentName, true); + }) || ''; + } + + //prefix and name should already be normalized, no need + //for applying map config again either. + normalizedMap = makeModuleMap(map.prefix + '!' + name, + this.map.parentMap); + on(normalizedMap, + 'defined', bind(this, function (value) { + this.init([], function () { return value; }, null, { + enabled: true, + ignore: true + }); + })); + + normalizedMod = getOwn(registry, normalizedMap.id); + if (normalizedMod) { + //Mark this as a dependency for this plugin, so it + //can be traced for cycles. + this.depMaps.push(normalizedMap); + + if (this.events.error) { + normalizedMod.on('error', bind(this, function (err) { + this.emit('error', err); + })); + } + normalizedMod.enable(); + } + + return; + } + + load = bind(this, function (value) { + this.init([], function () { return value; }, null, { + enabled: true + }); + }); + + load.error = bind(this, function (err) { + this.inited = true; + this.error = err; + err.requireModules = [id]; + + //Remove temp unnormalized modules for this module, + //since they will never be resolved otherwise now. + eachProp(registry, function (mod) { + if (mod.map.id.indexOf(id + '_unnormalized') === 0) { + cleanRegistry(mod.map.id); + } + }); + + onError(err); + }); + + //Allow plugins to load other code without having to know the + //context or how to 'complete' the load. + load.fromText = bind(this, function (text, textAlt) { + /*jslint evil: true */ + var moduleName = map.name, + moduleMap = makeModuleMap(moduleName), + hasInteractive = useInteractive; + + //As of 2.1.0, support just passing the text, to reinforce + //fromText only being called once per resource. Still + //support old style of passing moduleName but discard + //that moduleName in favor of the internal ref. + if (textAlt) { + text = textAlt; + } + + //Turn off interactive script matching for IE for any define + //calls in the text, then turn it back on at the end. + if (hasInteractive) { + useInteractive = false; + } + + //Prime the system by creating a module instance for + //it. + getModule(moduleMap); + + //Transfer any config to this other module. + if (hasProp(config.config, id)) { + config.config[moduleName] = config.config[id]; + } + + try { + req.exec(text); + } catch (e) { + return onError(makeError('fromtexteval', + 'fromText eval for ' + id + + ' failed: ' + e, + e, + [id])); + } + + if (hasInteractive) { + useInteractive = true; + } + + //Mark this as a dependency for the plugin + //resource + this.depMaps.push(moduleMap); + + //Support anonymous modules. + context.completeLoad(moduleName); + + //Bind the value of that module to the value for this + //resource ID. + localRequire([moduleName], load); + }); + + //Use parentName here since the plugin's name is not reliable, + //could be some weird string with no path that actually wants to + //reference the parentName's path. + plugin.load(map.name, localRequire, load, config); + })); + + context.enable(pluginMap, this); + this.pluginMaps[pluginMap.id] = pluginMap; + }, + + enable: function () { + enabledRegistry[this.map.id] = this; + this.enabled = true; + + //Set flag mentioning that the module is enabling, + //so that immediate calls to the defined callbacks + //for dependencies do not trigger inadvertent load + //with the depCount still being zero. + this.enabling = true; + + //Enable each dependency + each(this.depMaps, bind(this, function (depMap, i) { + var id, mod, handler; + + if (typeof depMap === 'string') { + //Dependency needs to be converted to a depMap + //and wired up to this module. + depMap = makeModuleMap(depMap, + (this.map.isDefine ? this.map : this.map.parentMap), + false, + !this.skipMap); + this.depMaps[i] = depMap; + + handler = getOwn(handlers, depMap.id); + + if (handler) { + this.depExports[i] = handler(this); + return; + } + + this.depCount += 1; + + on(depMap, 'defined', bind(this, function (depExports) { + this.defineDep(i, depExports); + this.check(); + })); + + if (this.errback) { + on(depMap, 'error', bind(this, this.errback)); + } + } + + id = depMap.id; + mod = registry[id]; + + //Skip special modules like 'require', 'exports', 'module' + //Also, don't call enable if it is already enabled, + //important in circular dependency cases. + if (!hasProp(handlers, id) && mod && !mod.enabled) { + context.enable(depMap, this); + } + })); + + //Enable each plugin that is used in + //a dependency + eachProp(this.pluginMaps, bind(this, function (pluginMap) { + var mod = getOwn(registry, pluginMap.id); + if (mod && !mod.enabled) { + context.enable(pluginMap, this); + } + })); + + this.enabling = false; + + this.check(); + }, + + on: function (name, cb) { + var cbs = this.events[name]; + if (!cbs) { + cbs = this.events[name] = []; + } + cbs.push(cb); + }, + + emit: function (name, evt) { + each(this.events[name], function (cb) { + cb(evt); + }); + if (name === 'error') { + //Now that the error handler was triggered, remove + //the listeners, since this broken Module instance + //can stay around for a while in the registry. + delete this.events[name]; + } + } + }; + + function callGetModule(args) { + //Skip modules already defined. + if (!hasProp(defined, args[0])) { + getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]); + } + } + + function removeListener(node, func, name, ieName) { + //Favor detachEvent because of IE9 + //issue, see attachEvent/addEventListener comment elsewhere + //in this file. + if (node.detachEvent && !isOpera) { + //Probably IE. If not it will throw an error, which will be + //useful to know. + if (ieName) { + node.detachEvent(ieName, func); + } + } else { + node.removeEventListener(name, func, false); + } + } + + /** + * Given an event from a script node, get the requirejs info from it, + * and then removes the event listeners on the node. + * @param {Event} evt + * @returns {Object} + */ + function getScriptData(evt) { + //Using currentTarget instead of target for Firefox 2.0's sake. Not + //all old browsers will be supported, but this one was easy enough + //to support and still makes sense. + var node = evt.currentTarget || evt.srcElement; + + //Remove the listeners once here. + removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange'); + removeListener(node, context.onScriptError, 'error'); + + return { + node: node, + id: node && node.getAttribute('data-requiremodule') + }; + } + + function intakeDefines() { + var args; + + //Any defined modules in the global queue, intake them now. + takeGlobalQueue(); + + //Make sure any remaining defQueue items get properly processed. + while (defQueue.length) { + args = defQueue.shift(); + if (args[0] === null) { + return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1])); + } else { + //args are id, deps, factory. Should be normalized by the + //define() function. + callGetModule(args); + } + } + } + + context = { + config: config, + contextName: contextName, + registry: registry, + defined: defined, + urlFetched: urlFetched, + defQueue: defQueue, + Module: Module, + makeModuleMap: makeModuleMap, + nextTick: req.nextTick, + onError: onError, + + /** + * Set a configuration for the context. + * @param {Object} cfg config object to integrate. + */ + configure: function (cfg) { + //Make sure the baseUrl ends in a slash. + if (cfg.baseUrl) { + if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') { + cfg.baseUrl += '/'; + } + } + + //Save off the paths and packages since they require special processing, + //they are additive. + var pkgs = config.pkgs, + shim = config.shim, + objs = { + paths: true, + config: true, + map: true + }; + + eachProp(cfg, function (value, prop) { + if (objs[prop]) { + if (prop === 'map') { + if (!config.map) { + config.map = {}; + } + mixin(config[prop], value, true, true); + } else { + mixin(config[prop], value, true); + } + } else { + config[prop] = value; + } + }); + + //Merge shim + if (cfg.shim) { + eachProp(cfg.shim, function (value, id) { + //Normalize the structure + if (isArray(value)) { + value = { + deps: value + }; + } + if ((value.exports || value.init) && !value.exportsFn) { + value.exportsFn = context.makeShimExports(value); + } + shim[id] = value; + }); + config.shim = shim; + } + + //Adjust packages if necessary. + if (cfg.packages) { + each(cfg.packages, function (pkgObj) { + var location; + + pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj; + location = pkgObj.location; + + //Create a brand new object on pkgs, since currentPackages can + //be passed in again, and config.pkgs is the internal transformed + //state for all package configs. + pkgs[pkgObj.name] = { + name: pkgObj.name, + location: location || pkgObj.name, + //Remove leading dot in main, so main paths are normalized, + //and remove any trailing .js, since different package + //envs have different conventions: some use a module name, + //some use a file name. + main: (pkgObj.main || 'main') + .replace(currDirRegExp, '') + .replace(jsSuffixRegExp, '') + }; + }); + + //Done with modifications, assing packages back to context config + config.pkgs = pkgs; + } + + //If there are any "waiting to execute" modules in the registry, + //update the maps for them, since their info, like URLs to load, + //may have changed. + eachProp(registry, function (mod, id) { + //If module already has init called, since it is too + //late to modify them, and ignore unnormalized ones + //since they are transient. + if (!mod.inited && !mod.map.unnormalized) { + mod.map = makeModuleMap(id); + } + }); + + //If a deps array or a config callback is specified, then call + //require with those args. This is useful when require is defined as a + //config object before require.js is loaded. + if (cfg.deps || cfg.callback) { + context.require(cfg.deps || [], cfg.callback); + } + }, + + makeShimExports: function (value) { + function fn() { + var ret; + if (value.init) { + ret = value.init.apply(global, arguments); + } + return ret || (value.exports && getGlobal(value.exports)); + } + return fn; + }, + + makeRequire: function (relMap, options) { + options = options || {}; + + function localRequire(deps, callback, errback) { + var id, map, requireMod; + + if (options.enableBuildCallback && callback && isFunction(callback)) { + callback.__requireJsBuild = true; + } + + if (typeof deps === 'string') { + if (isFunction(callback)) { + //Invalid call + return onError(makeError('requireargs', 'Invalid require call'), errback); + } + + //If require|exports|module are requested, get the + //value for them from the special handlers. Caveat: + //this only works while module is being defined. + if (relMap && hasProp(handlers, deps)) { + return handlers[deps](registry[relMap.id]); + } + + //Synchronous access to one module. If require.get is + //available (as in the Node adapter), prefer that. + if (req.get) { + return req.get(context, deps, relMap, localRequire); + } + + //Normalize module name, if it contains . or .. + map = makeModuleMap(deps, relMap, false, true); + id = map.id; + + if (!hasProp(defined, id)) { + return onError(makeError('notloaded', 'Module name "' + + id + + '" has not been loaded yet for context: ' + + contextName + + (relMap ? '' : '. Use require([])'))); + } + return defined[id]; + } + + //Grab defines waiting in the global queue. + intakeDefines(); + + //Mark all the dependencies as needing to be loaded. + context.nextTick(function () { + //Some defines could have been added since the + //require call, collect them. + intakeDefines(); + + requireMod = getModule(makeModuleMap(null, relMap)); + + //Store if map config should be applied to this require + //call for dependencies. + requireMod.skipMap = options.skipMap; + + requireMod.init(deps, callback, errback, { + enabled: true + }); + + checkLoaded(); + }); + + return localRequire; + } + + mixin(localRequire, { + isBrowser: isBrowser, + + /** + * Converts a module name + .extension into an URL path. + * *Requires* the use of a module name. It does not support using + * plain URLs like nameToUrl. + */ + toUrl: function (moduleNamePlusExt) { + var ext, + index = moduleNamePlusExt.lastIndexOf('.'), + segment = moduleNamePlusExt.split('/')[0], + isRelative = segment === '.' || segment === '..'; + + //Have a file extension alias, and it is not the + //dots from a relative path. + if (index !== -1 && (!isRelative || index > 1)) { + ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); + moduleNamePlusExt = moduleNamePlusExt.substring(0, index); + } + + return context.nameToUrl(normalize(moduleNamePlusExt, + relMap && relMap.id, true), ext, true); + }, + + defined: function (id) { + return hasProp(defined, makeModuleMap(id, relMap, false, true).id); + }, + + specified: function (id) { + id = makeModuleMap(id, relMap, false, true).id; + return hasProp(defined, id) || hasProp(registry, id); + } + }); + + //Only allow undef on top level require calls + if (!relMap) { + localRequire.undef = function (id) { + //Bind any waiting define() calls to this context, + //fix for #408 + takeGlobalQueue(); + + var map = makeModuleMap(id, relMap, true), + mod = getOwn(registry, id); + + removeScript(id); + + delete defined[id]; + delete urlFetched[map.url]; + delete undefEvents[id]; + + if (mod) { + //Hold on to listeners in case the + //module will be attempted to be reloaded + //using a different config. + if (mod.events.defined) { + undefEvents[id] = mod.events; + } + + cleanRegistry(id); + } + }; + } + + return localRequire; + }, + + /** + * Called to enable a module if it is still in the registry + * awaiting enablement. A second arg, parent, the parent module, + * is passed in for context, when this method is overriden by + * the optimizer. Not shown here to keep code compact. + */ + enable: function (depMap) { + var mod = getOwn(registry, depMap.id); + if (mod) { + getModule(depMap).enable(); + } + }, + + /** + * Internal method used by environment adapters to complete a load event. + * A load event could be a script load or just a load pass from a synchronous + * load call. + * @param {String} moduleName the name of the module to potentially complete. + */ + completeLoad: function (moduleName) { + var found, args, mod, + shim = getOwn(config.shim, moduleName) || {}, + shExports = shim.exports; + + takeGlobalQueue(); + + while (defQueue.length) { + args = defQueue.shift(); + if (args[0] === null) { + args[0] = moduleName; + //If already found an anonymous module and bound it + //to this name, then this is some other anon module + //waiting for its completeLoad to fire. + if (found) { + break; + } + found = true; + } else if (args[0] === moduleName) { + //Found matching define call for this script! + found = true; + } + + callGetModule(args); + } + + //Do this after the cycle of callGetModule in case the result + //of those calls/init calls changes the registry. + mod = getOwn(registry, moduleName); + + if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) { + if (config.enforceDefine && (!shExports || !getGlobal(shExports))) { + if (hasPathFallback(moduleName)) { + return; + } else { + return onError(makeError('nodefine', + 'No define call for ' + moduleName, + null, + [moduleName])); + } + } else { + //A script that does not call define(), so just simulate + //the call for it. + callGetModule([moduleName, (shim.deps || []), shim.exportsFn]); + } + } + + checkLoaded(); + }, + + /** + * Converts a module name to a file path. Supports cases where + * moduleName may actually be just an URL. + * Note that it **does not** call normalize on the moduleName, + * it is assumed to have already been normalized. This is an + * internal API, not a public one. Use toUrl for the public API. + */ + nameToUrl: function (moduleName, ext, skipExt) { + var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url, + parentPath; + + //If a colon is in the URL, it indicates a protocol is used and it is just + //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?) + //or ends with .js, then assume the user meant to use an url and not a module id. + //The slash is important for protocol-less URLs as well as full paths. + if (req.jsExtRegExp.test(moduleName)) { + //Just a plain path, not module name lookup, so just return it. + //Add extension if it is included. This is a bit wonky, only non-.js things pass + //an extension, this method probably needs to be reworked. + url = moduleName + (ext || ''); + } else { + //A module that needs to be converted to a path. + paths = config.paths; + pkgs = config.pkgs; + + syms = moduleName.split('/'); + //For each module name segment, see if there is a path + //registered for it. Start with most specific name + //and work up from it. + for (i = syms.length; i > 0; i -= 1) { + parentModule = syms.slice(0, i).join('/'); + pkg = getOwn(pkgs, parentModule); + parentPath = getOwn(paths, parentModule); + if (parentPath) { + //If an array, it means there are a few choices, + //Choose the one that is desired + if (isArray(parentPath)) { + parentPath = parentPath[0]; + } + syms.splice(0, i, parentPath); + break; + } else if (pkg) { + //If module name is just the package name, then looking + //for the main module. + if (moduleName === pkg.name) { + pkgPath = pkg.location + '/' + pkg.main; + } else { + pkgPath = pkg.location; + } + syms.splice(0, i, pkgPath); + break; + } + } + + //Join the path parts together, then figure out if baseUrl is needed. + url = syms.join('/'); + url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js')); + url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; + } + + return config.urlArgs ? url + + ((url.indexOf('?') === -1 ? '?' : '&') + + config.urlArgs) : url; + }, + + //Delegates to req.load. Broken out as a separate function to + //allow overriding in the optimizer. + load: function (id, url) { + req.load(context, id, url); + }, + + /** + * Executes a module callback function. Broken out as a separate function + * solely to allow the build system to sequence the files in the built + * layer in the right sequence. + * + * @private + */ + execCb: function (name, callback, args, exports) { + return callback.apply(exports, args); + }, + + /** + * callback for script loads, used to check status of loading. + * + * @param {Event} evt the event from the browser for the script + * that was loaded. + */ + onScriptLoad: function (evt) { + //Using currentTarget instead of target for Firefox 2.0's sake. Not + //all old browsers will be supported, but this one was easy enough + //to support and still makes sense. + if (evt.type === 'load' || + (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) { + //Reset interactive script so a script node is not held onto for + //to long. + interactiveScript = null; + + //Pull out the name of the module and the context. + var data = getScriptData(evt); + context.completeLoad(data.id); + } + }, + + /** + * Callback for script errors. + */ + onScriptError: function (evt) { + var data = getScriptData(evt); + if (!hasPathFallback(data.id)) { + return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id])); + } + } + }; + + context.require = context.makeRequire(); + return context; + } + + /** + * Main entry point. + * + * If the only argument to require is a string, then the module that + * is represented by that string is fetched for the appropriate context. + * + * If the first argument is an array, then it will be treated as an array + * of dependency string names to fetch. An optional function callback can + * be specified to execute when all of those dependencies are available. + * + * Make a local req variable to help Caja compliance (it assumes things + * on a require that are not standardized), and to give a short + * name for minification/local scope use. + */ + req = requirejs = function (deps, callback, errback, optional) { + + //Find the right context, use default + var context, config, + contextName = defContextName; + + // Determine if have config object in the call. + if (!isArray(deps) && typeof deps !== 'string') { + // deps is a config object + config = deps; + if (isArray(callback)) { + // Adjust args if there are dependencies + deps = callback; + callback = errback; + errback = optional; + } else { + deps = []; + } + } + + if (config && config.context) { + contextName = config.context; + } + + context = getOwn(contexts, contextName); + if (!context) { + context = contexts[contextName] = req.s.newContext(contextName); + } + + if (config) { + context.configure(config); + } + + return context.require(deps, callback, errback); + }; + + /** + * Support require.config() to make it easier to cooperate with other + * AMD loaders on globally agreed names. + */ + req.config = function (config) { + return req(config); + }; + + /** + * Execute something after the current tick + * of the event loop. Override for other envs + * that have a better solution than setTimeout. + * @param {Function} fn function to execute later. + */ + req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) { + setTimeout(fn, 4); + } : function (fn) { fn(); }; + + /** + * Export require as a global, but only if it does not already exist. + */ + if (!require) { + require = req; + } + + req.version = version; + + //Used to filter out dependencies that are already paths. + req.jsExtRegExp = /^\/|:|\?|\.js$/; + req.isBrowser = isBrowser; + s = req.s = { + contexts: contexts, + newContext: newContext + }; + + //Create default context. + req({}); + + //Exports some context-sensitive methods on global require. + each([ + 'toUrl', + 'undef', + 'defined', + 'specified' + ], function (prop) { + //Reference from contexts instead of early binding to default context, + //so that during builds, the latest instance of the default context + //with its config gets used. + req[prop] = function () { + var ctx = contexts[defContextName]; + return ctx.require[prop].apply(ctx, arguments); + }; + }); + + if (isBrowser) { + head = s.head = document.getElementsByTagName('head')[0]; + //If BASE tag is in play, using appendChild is a problem for IE6. + //When that browser dies, this can be removed. Details in this jQuery bug: + //http://dev.jquery.com/ticket/2709 + baseElement = document.getElementsByTagName('base')[0]; + if (baseElement) { + head = s.head = baseElement.parentNode; + } + } + + /** + * Any errors that require explicitly generates will be passed to this + * function. Intercept/override it if you want custom error handling. + * @param {Error} err the error object. + */ + req.onError = defaultOnError; + + /** + * Creates the node for the load command. Only used in browser envs. + */ + req.createNode = function (config, moduleName, url) { + var node = config.xhtml ? + document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') : + document.createElement('script'); + node.type = config.scriptType || 'text/javascript'; + node.charset = 'utf-8'; + node.async = true; + return node; + }; + + /** + * Does the request to load a module for the browser case. + * Make this a separate function to allow other environments + * to override it. + * + * @param {Object} context the require context to find state. + * @param {String} moduleName the name of the module. + * @param {Object} url the URL to the module. + */ + req.load = function (context, moduleName, url) { + var config = (context && context.config) || {}, + node; + if (isBrowser) { + //In the browser so use a script tag + node = req.createNode(config, moduleName, url); + + node.setAttribute('data-requirecontext', context.contextName); + node.setAttribute('data-requiremodule', moduleName); + + //Set up load listener. Test attachEvent first because IE9 has + //a subtle issue in its addEventListener and script onload firings + //that do not match the behavior of all other browsers with + //addEventListener support, which fire the onload event for a + //script right after the script execution. See: + //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution + //UNFORTUNATELY Opera implements attachEvent but does not follow the script + //script execution mode. + if (node.attachEvent && + //Check if node.attachEvent is artificially added by custom script or + //natively supported by browser + //read https://github.com/jrburke/requirejs/issues/187 + //if we can NOT find [native code] then it must NOT natively supported. + //in IE8, node.attachEvent does not have toString() + //Note the test for "[native code" with no closing brace, see: + //https://github.com/jrburke/requirejs/issues/273 + !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && + !isOpera) { + //Probably IE. IE (at least 6-8) do not fire + //script onload right after executing the script, so + //we cannot tie the anonymous define call to a name. + //However, IE reports the script as being in 'interactive' + //readyState at the time of the define call. + useInteractive = true; + + node.attachEvent('onreadystatechange', context.onScriptLoad); + //It would be great to add an error handler here to catch + //404s in IE9+. However, onreadystatechange will fire before + //the error handler, so that does not help. If addEventListener + //is used, then IE will fire error before load, but we cannot + //use that pathway given the connect.microsoft.com issue + //mentioned above about not doing the 'script execute, + //then fire the script load event listener before execute + //next script' that other browsers do. + //Best hope: IE10 fixes the issues, + //and then destroys all installs of IE 6-9. + //node.attachEvent('onerror', context.onScriptError); + } else { + node.addEventListener('load', context.onScriptLoad, false); + node.addEventListener('error', context.onScriptError, false); + } + node.src = url; + + //For some cache cases in IE 6-8, the script executes before the end + //of the appendChild execution, so to tie an anonymous define + //call to the module name (which is stored on the node), hold on + //to a reference to this node, but clear after the DOM insertion. + currentlyAddingScript = node; + if (baseElement) { + head.insertBefore(node, baseElement); + } else { + head.appendChild(node); + } + currentlyAddingScript = null; + + return node; + } else if (isWebWorker) { + try { + //In a web worker, use importScripts. This is not a very + //efficient use of importScripts, importScripts will block until + //its script is downloaded and evaluated. However, if web workers + //are in play, the expectation that a build has been done so that + //only one script needs to be loaded anyway. This may need to be + //reevaluated if other use cases become common. + importScripts(url); + + //Account for anonymous modules + context.completeLoad(moduleName); + } catch (e) { + context.onError(makeError('importscripts', + 'importScripts failed for ' + + moduleName + ' at ' + url, + e, + [moduleName])); + } + } + }; + + function getInteractiveScript() { + if (interactiveScript && interactiveScript.readyState === 'interactive') { + return interactiveScript; + } + + eachReverse(scripts(), function (script) { + if (script.readyState === 'interactive') { + return (interactiveScript = script); + } + }); + return interactiveScript; + } + + //Look for a data-main script attribute, which could also adjust the baseUrl. + if (isBrowser && !cfg.skipDataMain) { + //Figure out baseUrl. Get it from the script tag with require.js in it. + eachReverse(scripts(), function (script) { + //Set the 'head' where we can append children by + //using the script's parent. + if (!head) { + head = script.parentNode; + } + + //Look for a data-main attribute to set main script for the page + //to load. If it is there, the path to data main becomes the + //baseUrl, if it is not already set. + dataMain = script.getAttribute('data-main'); + if (dataMain) { + //Preserve dataMain in case it is a path (i.e. contains '?') + mainScript = dataMain; + + //Set final baseUrl if there is not already an explicit one. + if (!cfg.baseUrl) { + //Pull off the directory of data-main for use as the + //baseUrl. + src = mainScript.split('/'); + mainScript = src.pop(); + subPath = src.length ? src.join('/') + '/' : './'; + + cfg.baseUrl = subPath; + } + + //Strip off any trailing .js since mainScript is now + //like a module name. + mainScript = mainScript.replace(jsSuffixRegExp, ''); + + //If mainScript is still a path, fall back to dataMain + if (req.jsExtRegExp.test(mainScript)) { + mainScript = dataMain; + } + + //Put the data-main script in the files to load. + cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; + + return true; + } + }); + } + + /** + * The function that handles definitions of modules. Differs from + * require() in that a string for the module should be the first argument, + * and the function to execute after dependencies are loaded should + * return a value to define the module corresponding to the first argument's + * name. + */ + define = function (name, deps, callback) { + var node, context; + + //Allow for anonymous modules + if (typeof name !== 'string') { + //Adjust args appropriately + callback = deps; + deps = name; + name = null; + } + + //This module may not have dependencies + if (!isArray(deps)) { + callback = deps; + deps = null; + } + + //If no name, and callback is a function, then figure out if it a + //CommonJS thing with dependencies. + if (!deps && isFunction(callback)) { + deps = []; + //Remove comments from the callback string, + //look for require calls, and pull them into the dependencies, + //but only if there are function args. + if (callback.length) { + callback + .toString() + .replace(commentRegExp, '') + .replace(cjsRequireRegExp, function (match, dep) { + deps.push(dep); + }); + + //May be a CommonJS thing even without require calls, but still + //could use exports, and module. Avoid doing exports and module + //work though if it just needs require. + //REQUIRES the function to expect the CommonJS variables in the + //order listed below. + deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps); + } + } + + //If in IE 6-8 and hit an anonymous define() call, do the interactive + //work. + if (useInteractive) { + node = currentlyAddingScript || getInteractiveScript(); + if (node) { + if (!name) { + name = node.getAttribute('data-requiremodule'); + } + context = contexts[node.getAttribute('data-requirecontext')]; + } + } + + //Always save off evaluating the def call until the script onload handler. + //This allows multiple modules to be in a file without prematurely + //tracing dependencies, and allows for anonymous module support, + //where the module name is not known until the script onload event + //occurs. If no context, use the global queue, and get it processed + //in the onscript load callback. + (context ? context.defQueue : globalDefQueue).push([name, deps, callback]); + }; + + define.amd = { + jQuery: true + }; + + + /** + * Executes the text. Normally just uses eval, but can be modified + * to use a better, environment-specific call. Only used for transpiling + * loader plugins, not for plain JS modules. + * @param {String} text the text to execute/evaluate. + */ + req.exec = function (text) { + /*jslint evil: true */ + return eval(text); + }; + + //Set up with config info. + req(cfg); +}(this)); + + + + this.requirejsVars = { + require: require, + requirejs: require, + define: define + }; + + if (env === 'browser') { + /** + * @license RequireJS rhino Copyright (c) 2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +//sloppy since eval enclosed with use strict causes problems if the source +//text is not strict-compliant. +/*jslint sloppy: true, evil: true */ +/*global require, XMLHttpRequest */ + +(function () { + require.load = function (context, moduleName, url) { + var xhr = new XMLHttpRequest(); + + xhr.open('GET', url, true); + xhr.send(); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + eval(xhr.responseText); + + //Support anonymous modules. + context.completeLoad(moduleName); + } + }; + }; +}()); + } else if (env === 'rhino') { + /** + * @license RequireJS rhino Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint */ +/*global require: false, java: false, load: false */ + +(function () { + 'use strict'; + require.load = function (context, moduleName, url) { + + load(url); + + //Support anonymous modules. + context.completeLoad(moduleName); + }; + +}()); + } else if (env === 'node') { + this.requirejsVars.nodeRequire = nodeRequire; + require.nodeRequire = nodeRequire; + + /** + * @license RequireJS node Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint regexp: false */ +/*global require: false, define: false, requirejsVars: false, process: false */ + +/** + * This adapter assumes that x.js has loaded it and set up + * some variables. This adapter just allows limited RequireJS + * usage from within the requirejs directory. The general + * node adapater is r.js. + */ + +(function () { + 'use strict'; + + var nodeReq = requirejsVars.nodeRequire, + req = requirejsVars.require, + def = requirejsVars.define, + fs = nodeReq('fs'), + path = nodeReq('path'), + vm = nodeReq('vm'), + //In Node 0.7+ existsSync is on fs. + exists = fs.existsSync || path.existsSync, + hasOwn = Object.prototype.hasOwnProperty; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + function syncTick(fn) { + fn(); + } + + function makeError(message, moduleName) { + var err = new Error(message); + err.requireModules = [moduleName]; + return err; + } + + //Supply an implementation that allows synchronous get of a module. + req.get = function (context, moduleName, relModuleMap, localRequire) { + if (moduleName === "require" || moduleName === "exports" || moduleName === "module") { + context.onError(makeError("Explicit require of " + moduleName + " is not allowed.", moduleName)); + } + + var ret, oldTick, + moduleMap = context.makeModuleMap(moduleName, relModuleMap, false, true); + + //Normalize module name, if it contains . or .. + moduleName = moduleMap.id; + + if (hasProp(context.defined, moduleName)) { + ret = context.defined[moduleName]; + } else { + if (ret === undefined) { + //Make sure nextTick for this type of call is sync-based. + oldTick = context.nextTick; + context.nextTick = syncTick; + try { + if (moduleMap.prefix) { + //A plugin, call requirejs to handle it. Now that + //nextTick is syncTick, the require will complete + //synchronously. + localRequire([moduleMap.originalName]); + + //Now that plugin is loaded, can regenerate the moduleMap + //to get the final, normalized ID. + moduleMap = context.makeModuleMap(moduleMap.originalName, relModuleMap, false, true); + moduleName = moduleMap.id; + } else { + //Try to dynamically fetch it. + req.load(context, moduleName, moduleMap.url); + + //Enable the module + context.enable(moduleMap, relModuleMap); + } + + //Break any cycles by requiring it normally, but this will + //finish synchronously + require([moduleName]); + + //The above calls are sync, so can do the next thing safely. + ret = context.defined[moduleName]; + } finally { + context.nextTick = oldTick; + } + } + } + + return ret; + }; + + req.nextTick = function (fn) { + process.nextTick(fn); + }; + + //Add wrapper around the code so that it gets the requirejs + //API instead of the Node API, and it is done lexically so + //that it survives later execution. + req.makeNodeWrapper = function (contents) { + return '(function (require, requirejs, define) { ' + + contents + + '\n}(requirejsVars.require, requirejsVars.requirejs, requirejsVars.define));'; + }; + + req.load = function (context, moduleName, url) { + var contents, err, + config = context.config; + + if (config.shim[moduleName] && (!config.suppress || !config.suppress.nodeShim)) { + console.warn('Shim config not supported in Node, may or may not work. Detected ' + + 'for module: ' + moduleName); + } + + if (exists(url)) { + contents = fs.readFileSync(url, 'utf8'); + + contents = req.makeNodeWrapper(contents); + try { + vm.runInThisContext(contents, fs.realpathSync(url)); + } catch (e) { + err = new Error('Evaluating ' + url + ' as module "' + + moduleName + '" failed with error: ' + e); + err.originalError = e; + err.moduleName = moduleName; + err.requireModules = [moduleName]; + err.fileName = url; + return context.onError(err); + } + } else { + def(moduleName, function () { + //Get the original name, since relative requires may be + //resolved differently in node (issue #202). Also, if relative, + //make it relative to the URL of the item requesting it + //(issue #393) + var dirName, + map = hasProp(context.registry, moduleName) && + context.registry[moduleName].map, + parentMap = map && map.parentMap, + originalName = map && map.originalName; + + if (originalName.charAt(0) === '.' && parentMap) { + dirName = parentMap.url.split('/'); + dirName.pop(); + originalName = dirName.join('/') + '/' + originalName; + } + + try { + return (context.config.nodeRequire || req.nodeRequire)(originalName); + } catch (e) { + err = new Error('Tried loading "' + moduleName + '" at ' + + url + ' then tried node\'s require("' + + originalName + '") and it failed ' + + 'with error: ' + e); + err.originalError = e; + err.moduleName = originalName; + err.requireModules = [moduleName]; + return context.onError(err); + } + }); + } + + //Support anonymous modules. + context.completeLoad(moduleName); + }; + + //Override to provide the function wrapper for define/require. + req.exec = function (text) { + /*jslint evil: true */ + text = req.makeNodeWrapper(text); + return eval(text); + }; +}()); + + } else if (env === 'xpconnect') { + /** + * @license RequireJS xpconnect Copyright (c) 2013, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint */ +/*global require, load */ + +(function () { + 'use strict'; + require.load = function (context, moduleName, url) { + + load(url); + + //Support anonymous modules. + context.completeLoad(moduleName); + }; + +}()); + + } + + //Support a default file name to execute. Useful for hosted envs + //like Joyent where it defaults to a server.js as the only executed + //script. But only do it if this is not an optimization run. + if (commandOption !== 'o' && (!fileName || !jsSuffixRegExp.test(fileName))) { + fileName = 'main.js'; + } + + /** + * Loads the library files that can be used for the optimizer, or for other + * tasks. + */ + function loadLib() { + /** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global Packages: false, process: false, window: false, navigator: false, + document: false, define: false */ + +/** + * A plugin that modifies any /env/ path to be the right path based on + * the host environment. Right now only works for Node, Rhino and browser. + */ +(function () { + var pathRegExp = /(\/|^)env\/|\{env\}/, + env = 'unknown'; + + if (typeof Packages !== 'undefined') { + env = 'rhino'; + } else if (typeof process !== 'undefined' && process.versions && !!process.versions.node) { + env = 'node'; + } else if ((typeof navigator !== 'undefined' && typeof document !== 'undefined') || + (typeof importScripts !== 'undefined' && typeof self !== 'undefined')) { + env = 'browser'; + } else if (typeof Components !== 'undefined' && Components.classes && Components.interfaces) { + env = 'xpconnect'; + } + + define('env', { + get: function () { + return env; + }, + + load: function (name, req, load, config) { + //Allow override in the config. + if (config.env) { + env = config.env; + } + + name = name.replace(pathRegExp, function (match, prefix) { + if (match.indexOf('{') === -1) { + return prefix + env + '/'; + } else { + return env; + } + }); + + req([name], function (mod) { + load(mod); + }); + } + }); +}());/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint plusplus: true */ +/*global define */ + +define('lang', function () { + 'use strict'; + + var lang, + hasOwn = Object.prototype.hasOwnProperty; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + lang = { + backSlashRegExp: /\\/g, + ostring: Object.prototype.toString, + + isArray: Array.isArray || function (it) { + return lang.ostring.call(it) === "[object Array]"; + }, + + isFunction: function(it) { + return lang.ostring.call(it) === "[object Function]"; + }, + + isRegExp: function(it) { + return it && it instanceof RegExp; + }, + + hasProp: hasProp, + + //returns true if the object does not have an own property prop, + //or if it does, it is a falsy value. + falseProp: function (obj, prop) { + return !hasProp(obj, prop) || !obj[prop]; + }, + + //gets own property value for given prop on object + getOwn: function (obj, prop) { + return hasProp(obj, prop) && obj[prop]; + }, + + _mixin: function(dest, source, override){ + var name; + for (name in source) { + if(source.hasOwnProperty(name) && + (override || !dest.hasOwnProperty(name))) { + dest[name] = source[name]; + } + } + + return dest; // Object + }, + + /** + * mixin({}, obj1, obj2) is allowed. If the last argument is a boolean, + * then the source objects properties are force copied over to dest. + */ + mixin: function(dest){ + var parameters = Array.prototype.slice.call(arguments), + override, i, l; + + if (!dest) { dest = {}; } + + if (parameters.length > 2 && typeof arguments[parameters.length-1] === 'boolean') { + override = parameters.pop(); + } + + for (i = 1, l = parameters.length; i < l; i++) { + lang._mixin(dest, parameters[i], override); + } + return dest; // Object + }, + + + /** + * Does a type of deep copy. Do not give it anything fancy, best + * for basic object copies of objects that also work well as + * JSON-serialized things, or has properties pointing to functions. + * For non-array/object values, just returns the same object. + * @param {Object} obj copy properties from this object + * @param {Object} [result] optional result object to use + * @return {Object} + */ + deeplikeCopy: function (obj) { + var type, result; + + if (lang.isArray(obj)) { + result = []; + obj.forEach(function(value) { + result.push(lang.deeplikeCopy(value)); + }); + return result; + } + + type = typeof obj; + if (obj === null || obj === undefined || type === 'boolean' || + type === 'string' || type === 'number' || lang.isFunction(obj) || + lang.isRegExp(obj)) { + return obj; + } + + //Anything else is an object, hopefully. + result = {}; + lang.eachProp(obj, function(value, key) { + result[key] = lang.deeplikeCopy(value); + }); + return result; + }, + + delegate: (function () { + // boodman/crockford delegation w/ cornford optimization + function TMP() {} + return function (obj, props) { + TMP.prototype = obj; + var tmp = new TMP(); + TMP.prototype = null; + if (props) { + lang.mixin(tmp, props); + } + return tmp; // Object + }; + }()), + + /** + * Helper function for iterating over an array. If the func returns + * a true value, it will break out of the loop. + */ + each: function each(ary, func) { + if (ary) { + var i; + for (i = 0; i < ary.length; i += 1) { + if (func(ary[i], i, ary)) { + break; + } + } + } + }, + + /** + * Cycles over properties in an object and calls a function for each + * property value. If the function returns a truthy value, then the + * iteration is stopped. + */ + eachProp: function eachProp(obj, func) { + var prop; + for (prop in obj) { + if (hasProp(obj, prop)) { + if (func(obj[prop], prop)) { + break; + } + } + } + }, + + //Similar to Function.prototype.bind, but the "this" object is specified + //first, since it is easier to read/figure out what "this" will be. + bind: function bind(obj, fn) { + return function () { + return fn.apply(obj, arguments); + }; + }, + + //Escapes a content string to be be a string that has characters escaped + //for inclusion as part of a JS string. + jsEscape: function (content) { + return content.replace(/(["'\\])/g, '\\$1') + .replace(/[\f]/g, "\\f") + .replace(/[\b]/g, "\\b") + .replace(/[\n]/g, "\\n") + .replace(/[\t]/g, "\\t") + .replace(/[\r]/g, "\\r"); + } + }; + return lang; +}); +/** + * prim 0.0.1 Copyright (c) 2012-2013, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/requirejs/prim for details + */ + +/*global setImmediate, process, setTimeout, define, module */ + +//Set prime.hideResolutionConflict = true to allow "resolution-races" +//in promise-tests to pass. +//Since the goal of prim is to be a small impl for trusted code, it is +//more important to normally throw in this case so that we can find +//logic errors quicker. + +var prim; +(function () { + 'use strict'; + var op = Object.prototype, + hasOwn = op.hasOwnProperty; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + /** + * Helper function for iterating over an array. If the func returns + * a true value, it will break out of the loop. + */ + function each(ary, func) { + if (ary) { + var i; + for (i = 0; i < ary.length; i += 1) { + if (ary[i]) { + func(ary[i], i, ary); + } + } + } + } + + function check(p) { + if (hasProp(p, 'e') || hasProp(p, 'v')) { + if (!prim.hideResolutionConflict) { + throw new Error('nope'); + } + return false; + } + return true; + } + + function notify(ary, value) { + prim.nextTick(function () { + each(ary, function (item) { + item(value); + }); + }); + } + + prim = function prim() { + var p, + ok = [], + fail = []; + + return (p = { + callback: function (yes, no) { + if (no) { + p.errback(no); + } + + if (hasProp(p, 'v')) { + prim.nextTick(function () { + yes(p.v); + }); + } else { + ok.push(yes); + } + }, + + errback: function (no) { + if (hasProp(p, 'e')) { + prim.nextTick(function () { + no(p.e); + }); + } else { + fail.push(no); + } + }, + + finished: function () { + return hasProp(p, 'e') || hasProp(p, 'v'); + }, + + rejected: function () { + return hasProp(p, 'e'); + }, + + resolve: function (v) { + if (check(p)) { + p.v = v; + notify(ok, v); + } + return p; + }, + reject: function (e) { + if (check(p)) { + p.e = e; + notify(fail, e); + } + return p; + }, + + start: function (fn) { + p.resolve(); + return p.promise.then(fn); + }, + + promise: { + then: function (yes, no) { + var next = prim(); + + p.callback(function (v) { + try { + if (yes && typeof yes === 'function') { + v = yes(v); + } + + if (v && v.then) { + v.then(next.resolve, next.reject); + } else { + next.resolve(v); + } + } catch (e) { + next.reject(e); + } + }, function (e) { + var err; + + try { + if (!no || typeof no !== 'function') { + next.reject(e); + } else { + err = no(e); + + if (err && err.then) { + err.then(next.resolve, next.reject); + } else { + next.resolve(err); + } + } + } catch (e2) { + next.reject(e2); + } + }); + + return next.promise; + }, + + fail: function (no) { + return p.promise.then(null, no); + }, + + end: function () { + p.errback(function (e) { + throw e; + }); + } + } + }); + }; + + prim.serial = function (ary) { + var result = prim().resolve().promise; + each(ary, function (item) { + result = result.then(function () { + return item(); + }); + }); + return result; + }; + + prim.nextTick = typeof setImmediate === 'function' ? setImmediate : + (typeof process !== 'undefined' && process.nextTick ? + process.nextTick : (typeof setTimeout !== 'undefined' ? + function (fn) { + setTimeout(fn, 0); + } : function (fn) { + fn(); + })); + + if (typeof define === 'function' && define.amd) { + define('prim', function () { return prim; }); + } else if (typeof module !== 'undefined' && module.exports) { + module.exports = prim; + } +}()); +if(env === 'browser') { +/** + * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, load: false */ + +//Just a stub for use with uglify's consolidator.js +define('browser/assert', function () { + return {}; +}); + +} + +if(env === 'node') { +/** + * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, load: false */ + +//Needed so that rhino/assert can return a stub for uglify's consolidator.js +define('node/assert', ['assert'], function (assert) { + return assert; +}); + +} + +if(env === 'rhino') { +/** + * @license RequireJS Copyright (c) 2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, load: false */ + +//Just a stub for use with uglify's consolidator.js +define('rhino/assert', function () { + return {}; +}); + +} + +if(env === 'xpconnect') { +/** + * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, load: false */ + +//Just a stub for use with uglify's consolidator.js +define('xpconnect/assert', function () { + return {}; +}); + +} + +if(env === 'browser') { +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, process: false */ + +define('browser/args', function () { + //Always expect config via an API call + return []; +}); + +} + +if(env === 'node') { +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, process: false */ + +define('node/args', function () { + //Do not return the "node" or "r.js" arguments + var args = process.argv.slice(2); + + //Ignore any command option used for main x.js branching + if (args[0] && args[0].indexOf('-') === 0) { + args = args.slice(1); + } + + return args; +}); + +} + +if(env === 'rhino') { +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, process: false */ + +var jsLibRhinoArgs = (typeof rhinoArgs !== 'undefined' && rhinoArgs) || [].concat(Array.prototype.slice.call(arguments, 0)); + +define('rhino/args', function () { + var args = jsLibRhinoArgs; + + //Ignore any command option used for main x.js branching + if (args[0] && args[0].indexOf('-') === 0) { + args = args.slice(1); + } + + return args; +}); + +} + +if(env === 'xpconnect') { +/** + * @license Copyright (c) 2013, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define, xpconnectArgs */ + +var jsLibXpConnectArgs = (typeof xpconnectArgs !== 'undefined' && xpconnectArgs) || [].concat(Array.prototype.slice.call(arguments, 0)); + +define('xpconnect/args', function () { + var args = jsLibXpConnectArgs; + + //Ignore any command option used for main x.js branching + if (args[0] && args[0].indexOf('-') === 0) { + args = args.slice(1); + } + + return args; +}); + +} + +if(env === 'browser') { +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, console: false */ + +define('browser/load', ['./file'], function (file) { + function load(fileName) { + eval(file.readFile(fileName)); + } + + return load; +}); + +} + +if(env === 'node') { +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, console: false */ + +define('node/load', ['fs'], function (fs) { + function load(fileName) { + var contents = fs.readFileSync(fileName, 'utf8'); + process.compile(contents, fileName); + } + + return load; +}); + +} + +if(env === 'rhino') { +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, load: false */ + +define('rhino/load', function () { + return load; +}); + +} + +if(env === 'xpconnect') { +/** + * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, load: false */ + +define('xpconnect/load', function () { + return load; +}); + +} + +if(env === 'browser') { +/** + * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint sloppy: true, nomen: true */ +/*global require, define, console, XMLHttpRequest, requirejs, location */ + +define('browser/file', ['prim'], function (prim) { + + var file, + currDirRegExp = /^\.(\/|$)/; + + function frontSlash(path) { + return path.replace(/\\/g, '/'); + } + + function exists(path) { + var status, xhr = new XMLHttpRequest(); + + //Oh yeah, that is right SYNC IO. Behold its glory + //and horrible blocking behavior. + xhr.open('HEAD', path, false); + xhr.send(); + status = xhr.status; + + return status === 200 || status === 304; + } + + function mkDir(dir) { + console.log('mkDir is no-op in browser'); + } + + function mkFullDir(dir) { + console.log('mkFullDir is no-op in browser'); + } + + file = { + backSlashRegExp: /\\/g, + exclusionRegExp: /^\./, + getLineSeparator: function () { + return '/'; + }, + + exists: function (fileName) { + return exists(fileName); + }, + + parent: function (fileName) { + var parts = fileName.split('/'); + parts.pop(); + return parts.join('/'); + }, + + /** + * Gets the absolute file path as a string, normalized + * to using front slashes for path separators. + * @param {String} fileName + */ + absPath: function (fileName) { + var dir; + if (currDirRegExp.test(fileName)) { + dir = frontSlash(location.href); + if (dir.indexOf('/') !== -1) { + dir = dir.split('/'); + + //Pull off protocol and host, just want + //to allow paths (other build parts, like + //require._isSupportedBuildUrl do not support + //full URLs), but a full path from + //the root. + dir.splice(0, 3); + + dir.pop(); + dir = '/' + dir.join('/'); + } + + fileName = dir + fileName.substring(1); + } + + return fileName; + }, + + normalize: function (fileName) { + return fileName; + }, + + isFile: function (path) { + return true; + }, + + isDirectory: function (path) { + return false; + }, + + getFilteredFileList: function (startDir, regExpFilters, makeUnixPaths) { + console.log('file.getFilteredFileList is no-op in browser'); + }, + + copyDir: function (srcDir, destDir, regExpFilter, onlyCopyNew) { + console.log('file.copyDir is no-op in browser'); + + }, + + copyFile: function (srcFileName, destFileName, onlyCopyNew) { + console.log('file.copyFile is no-op in browser'); + }, + + /** + * Renames a file. May fail if "to" already exists or is on another drive. + */ + renameFile: function (from, to) { + console.log('file.renameFile is no-op in browser'); + }, + + /** + * Reads a *text* file. + */ + readFile: function (path, encoding) { + var xhr = new XMLHttpRequest(); + + //Oh yeah, that is right SYNC IO. Behold its glory + //and horrible blocking behavior. + xhr.open('GET', path, false); + xhr.send(); + + return xhr.responseText; + }, + + readFileAsync: function (path, encoding) { + var xhr = new XMLHttpRequest(), + d = prim(); + + xhr.open('GET', path, true); + xhr.send(); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if (xhr.status > 400) { + d.reject(new Error('Status: ' + xhr.status + ': ' + xhr.statusText)); + } else { + d.resolve(xhr.responseText); + } + } + }; + + return d.promise; + }, + + saveUtf8File: function (fileName, fileContents) { + //summary: saves a *text* file using UTF-8 encoding. + file.saveFile(fileName, fileContents, "utf8"); + }, + + saveFile: function (fileName, fileContents, encoding) { + requirejs.browser.saveFile(fileName, fileContents, encoding); + }, + + deleteFile: function (fileName) { + console.log('file.deleteFile is no-op in browser'); + }, + + /** + * Deletes any empty directories under the given directory. + */ + deleteEmptyDirs: function (startDir) { + console.log('file.deleteEmptyDirs is no-op in browser'); + } + }; + + return file; + +}); + +} + +if(env === 'node') { +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint plusplus: false, octal:false, strict: false */ +/*global define: false, process: false */ + +define('node/file', ['fs', 'path', 'prim'], function (fs, path, prim) { + + var isWindows = process.platform === 'win32', + windowsDriveRegExp = /^[a-zA-Z]\:\/$/, + file; + + function frontSlash(path) { + return path.replace(/\\/g, '/'); + } + + function exists(path) { + if (isWindows && path.charAt(path.length - 1) === '/' && + path.charAt(path.length - 2) !== ':') { + path = path.substring(0, path.length - 1); + } + + try { + fs.statSync(path); + return true; + } catch (e) { + return false; + } + } + + function mkDir(dir) { + if (!exists(dir) && (!isWindows || !windowsDriveRegExp.test(dir))) { + fs.mkdirSync(dir, 511); + } + } + + function mkFullDir(dir) { + var parts = dir.split('/'), + currDir = '', + first = true; + + parts.forEach(function (part) { + //First part may be empty string if path starts with a slash. + currDir += part + '/'; + first = false; + + if (part) { + mkDir(currDir); + } + }); + } + + file = { + backSlashRegExp: /\\/g, + exclusionRegExp: /^\./, + getLineSeparator: function () { + return '/'; + }, + + exists: function (fileName) { + return exists(fileName); + }, + + parent: function (fileName) { + var parts = fileName.split('/'); + parts.pop(); + return parts.join('/'); + }, + + /** + * Gets the absolute file path as a string, normalized + * to using front slashes for path separators. + * @param {String} fileName + */ + absPath: function (fileName) { + return frontSlash(path.normalize(frontSlash(fs.realpathSync(fileName)))); + }, + + normalize: function (fileName) { + return frontSlash(path.normalize(fileName)); + }, + + isFile: function (path) { + return fs.statSync(path).isFile(); + }, + + isDirectory: function (path) { + return fs.statSync(path).isDirectory(); + }, + + getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths) { + //summary: Recurses startDir and finds matches to the files that match regExpFilters.include + //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters, + //and it will be treated as the "include" case. + //Ignores files/directories that start with a period (.) unless exclusionRegExp + //is set to another value. + var files = [], topDir, regExpInclude, regExpExclude, dirFileArray, + i, stat, filePath, ok, dirFiles, fileName; + + topDir = startDir; + + regExpInclude = regExpFilters.include || regExpFilters; + regExpExclude = regExpFilters.exclude || null; + + if (file.exists(topDir)) { + dirFileArray = fs.readdirSync(topDir); + for (i = 0; i < dirFileArray.length; i++) { + fileName = dirFileArray[i]; + filePath = path.join(topDir, fileName); + stat = fs.statSync(filePath); + if (stat.isFile()) { + if (makeUnixPaths) { + //Make sure we have a JS string. + if (filePath.indexOf("/") === -1) { + filePath = frontSlash(filePath); + } + } + + ok = true; + if (regExpInclude) { + ok = filePath.match(regExpInclude); + } + if (ok && regExpExclude) { + ok = !filePath.match(regExpExclude); + } + + if (ok && (!file.exclusionRegExp || + !file.exclusionRegExp.test(fileName))) { + files.push(filePath); + } + } else if (stat.isDirectory() && + (!file.exclusionRegExp || !file.exclusionRegExp.test(fileName))) { + dirFiles = this.getFilteredFileList(filePath, regExpFilters, makeUnixPaths); + files.push.apply(files, dirFiles); + } + } + } + + return files; //Array + }, + + copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) { + //summary: copies files from srcDir to destDir using the regExpFilter to determine if the + //file should be copied. Returns a list file name strings of the destinations that were copied. + regExpFilter = regExpFilter || /\w/; + + //Normalize th directory names, but keep front slashes. + //path module on windows now returns backslashed paths. + srcDir = frontSlash(path.normalize(srcDir)); + destDir = frontSlash(path.normalize(destDir)); + + var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true), + copiedFiles = [], i, srcFileName, destFileName; + + for (i = 0; i < fileNames.length; i++) { + srcFileName = fileNames[i]; + destFileName = srcFileName.replace(srcDir, destDir); + + if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) { + copiedFiles.push(destFileName); + } + } + + return copiedFiles.length ? copiedFiles : null; //Array or null + }, + + copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) { + //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if + //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred. + var parentDir; + + //logger.trace("Src filename: " + srcFileName); + //logger.trace("Dest filename: " + destFileName); + + //If onlyCopyNew is true, then compare dates and only copy if the src is newer + //than dest. + if (onlyCopyNew) { + if (file.exists(destFileName) && fs.statSync(destFileName).mtime.getTime() >= fs.statSync(srcFileName).mtime.getTime()) { + return false; //Boolean + } + } + + //Make sure destination dir exists. + parentDir = path.dirname(destFileName); + if (!file.exists(parentDir)) { + mkFullDir(parentDir); + } + + fs.writeFileSync(destFileName, fs.readFileSync(srcFileName, 'binary'), 'binary'); + + return true; //Boolean + }, + + /** + * Renames a file. May fail if "to" already exists or is on another drive. + */ + renameFile: function (from, to) { + return fs.renameSync(from, to); + }, + + /** + * Reads a *text* file. + */ + readFile: function (/*String*/path, /*String?*/encoding) { + if (encoding === 'utf-8') { + encoding = 'utf8'; + } + if (!encoding) { + encoding = 'utf8'; + } + + var text = fs.readFileSync(path, encoding); + + //Hmm, would not expect to get A BOM, but it seems to happen, + //remove it just in case. + if (text.indexOf('\uFEFF') === 0) { + text = text.substring(1, text.length); + } + + return text; + }, + + readFileAsync: function (path, encoding) { + var d = prim(); + try { + d.resolve(file.readFile(path, encoding)); + } catch (e) { + d.reject(e); + } + return d.promise; + }, + + saveUtf8File: function (/*String*/fileName, /*String*/fileContents) { + //summary: saves a *text* file using UTF-8 encoding. + file.saveFile(fileName, fileContents, "utf8"); + }, + + saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) { + //summary: saves a *text* file. + var parentDir; + + if (encoding === 'utf-8') { + encoding = 'utf8'; + } + if (!encoding) { + encoding = 'utf8'; + } + + //Make sure destination directories exist. + parentDir = path.dirname(fileName); + if (!file.exists(parentDir)) { + mkFullDir(parentDir); + } + + fs.writeFileSync(fileName, fileContents, encoding); + }, + + deleteFile: function (/*String*/fileName) { + //summary: deletes a file or directory if it exists. + var files, i, stat; + if (file.exists(fileName)) { + stat = fs.statSync(fileName); + if (stat.isDirectory()) { + files = fs.readdirSync(fileName); + for (i = 0; i < files.length; i++) { + this.deleteFile(path.join(fileName, files[i])); + } + fs.rmdirSync(fileName); + } else { + fs.unlinkSync(fileName); + } + } + }, + + + /** + * Deletes any empty directories under the given directory. + */ + deleteEmptyDirs: function (startDir) { + var dirFileArray, i, fileName, filePath, stat; + + if (file.exists(startDir)) { + dirFileArray = fs.readdirSync(startDir); + for (i = 0; i < dirFileArray.length; i++) { + fileName = dirFileArray[i]; + filePath = path.join(startDir, fileName); + stat = fs.statSync(filePath); + if (stat.isDirectory()) { + file.deleteEmptyDirs(filePath); + } + } + + //If directory is now empty, remove it. + if (fs.readdirSync(startDir).length === 0) { + file.deleteFile(startDir); + } + } + } + }; + + return file; + +}); + +} + +if(env === 'rhino') { +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ +//Helper functions to deal with file I/O. + +/*jslint plusplus: false */ +/*global java: false, define: false */ + +define('rhino/file', ['prim'], function (prim) { + var file = { + backSlashRegExp: /\\/g, + + exclusionRegExp: /^\./, + + getLineSeparator: function () { + return file.lineSeparator; + }, + + lineSeparator: java.lang.System.getProperty("line.separator"), //Java String + + exists: function (fileName) { + return (new java.io.File(fileName)).exists(); + }, + + parent: function (fileName) { + return file.absPath((new java.io.File(fileName)).getParentFile()); + }, + + normalize: function (fileName) { + return file.absPath(fileName); + }, + + isFile: function (path) { + return (new java.io.File(path)).isFile(); + }, + + isDirectory: function (path) { + return (new java.io.File(path)).isDirectory(); + }, + + /** + * Gets the absolute file path as a string, normalized + * to using front slashes for path separators. + * @param {java.io.File||String} file + */ + absPath: function (fileObj) { + if (typeof fileObj === "string") { + fileObj = new java.io.File(fileObj); + } + return (fileObj.getCanonicalPath() + "").replace(file.backSlashRegExp, "/"); + }, + + getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) { + //summary: Recurses startDir and finds matches to the files that match regExpFilters.include + //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters, + //and it will be treated as the "include" case. + //Ignores files/directories that start with a period (.) unless exclusionRegExp + //is set to another value. + var files = [], topDir, regExpInclude, regExpExclude, dirFileArray, + i, fileObj, filePath, ok, dirFiles; + + topDir = startDir; + if (!startDirIsJavaObject) { + topDir = new java.io.File(startDir); + } + + regExpInclude = regExpFilters.include || regExpFilters; + regExpExclude = regExpFilters.exclude || null; + + if (topDir.exists()) { + dirFileArray = topDir.listFiles(); + for (i = 0; i < dirFileArray.length; i++) { + fileObj = dirFileArray[i]; + if (fileObj.isFile()) { + filePath = fileObj.getPath(); + if (makeUnixPaths) { + //Make sure we have a JS string. + filePath = String(filePath); + if (filePath.indexOf("/") === -1) { + filePath = filePath.replace(/\\/g, "/"); + } + } + + ok = true; + if (regExpInclude) { + ok = filePath.match(regExpInclude); + } + if (ok && regExpExclude) { + ok = !filePath.match(regExpExclude); + } + + if (ok && (!file.exclusionRegExp || + !file.exclusionRegExp.test(fileObj.getName()))) { + files.push(filePath); + } + } else if (fileObj.isDirectory() && + (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.getName()))) { + dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true); + files.push.apply(files, dirFiles); + } + } + } + + return files; //Array + }, + + copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) { + //summary: copies files from srcDir to destDir using the regExpFilter to determine if the + //file should be copied. Returns a list file name strings of the destinations that were copied. + regExpFilter = regExpFilter || /\w/; + + var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true), + copiedFiles = [], i, srcFileName, destFileName; + + for (i = 0; i < fileNames.length; i++) { + srcFileName = fileNames[i]; + destFileName = srcFileName.replace(srcDir, destDir); + + if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) { + copiedFiles.push(destFileName); + } + } + + return copiedFiles.length ? copiedFiles : null; //Array or null + }, + + copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) { + //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if + //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred. + var destFile = new java.io.File(destFileName), srcFile, parentDir, + srcChannel, destChannel; + + //logger.trace("Src filename: " + srcFileName); + //logger.trace("Dest filename: " + destFileName); + + //If onlyCopyNew is true, then compare dates and only copy if the src is newer + //than dest. + if (onlyCopyNew) { + srcFile = new java.io.File(srcFileName); + if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) { + return false; //Boolean + } + } + + //Make sure destination dir exists. + parentDir = destFile.getParentFile(); + if (!parentDir.exists()) { + if (!parentDir.mkdirs()) { + throw "Could not create directory: " + parentDir.getCanonicalPath(); + } + } + + //Java's version of copy file. + srcChannel = new java.io.FileInputStream(srcFileName).getChannel(); + destChannel = new java.io.FileOutputStream(destFileName).getChannel(); + destChannel.transferFrom(srcChannel, 0, srcChannel.size()); + srcChannel.close(); + destChannel.close(); + + return true; //Boolean + }, + + /** + * Renames a file. May fail if "to" already exists or is on another drive. + */ + renameFile: function (from, to) { + return (new java.io.File(from)).renameTo((new java.io.File(to))); + }, + + readFile: function (/*String*/path, /*String?*/encoding) { + //A file read function that can deal with BOMs + encoding = encoding || "utf-8"; + var fileObj = new java.io.File(path), + input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(fileObj), encoding)), + stringBuffer, line; + try { + stringBuffer = new java.lang.StringBuffer(); + line = input.readLine(); + + // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 + // http://www.unicode.org/faq/utf_bom.html + + // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 + if (line && line.length() && line.charAt(0) === 0xfeff) { + // Eat the BOM, since we've already found the encoding on this file, + // and we plan to concatenating this buffer with others; the BOM should + // only appear at the top of a file. + line = line.substring(1); + } + while (line !== null) { + stringBuffer.append(line); + stringBuffer.append(file.lineSeparator); + line = input.readLine(); + } + //Make sure we return a JavaScript string and not a Java string. + return String(stringBuffer.toString()); //String + } finally { + input.close(); + } + }, + + readFileAsync: function (path, encoding) { + var d = prim(); + try { + d.resolve(file.readFile(path, encoding)); + } catch (e) { + d.reject(e); + } + return d.promise; + }, + + saveUtf8File: function (/*String*/fileName, /*String*/fileContents) { + //summary: saves a file using UTF-8 encoding. + file.saveFile(fileName, fileContents, "utf-8"); + }, + + saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) { + //summary: saves a file. + var outFile = new java.io.File(fileName), outWriter, parentDir, os; + + parentDir = outFile.getAbsoluteFile().getParentFile(); + if (!parentDir.exists()) { + if (!parentDir.mkdirs()) { + throw "Could not create directory: " + parentDir.getAbsolutePath(); + } + } + + if (encoding) { + outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding); + } else { + outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile)); + } + + os = new java.io.BufferedWriter(outWriter); + try { + os.write(fileContents); + } finally { + os.close(); + } + }, + + deleteFile: function (/*String*/fileName) { + //summary: deletes a file or directory if it exists. + var fileObj = new java.io.File(fileName), files, i; + if (fileObj.exists()) { + if (fileObj.isDirectory()) { + files = fileObj.listFiles(); + for (i = 0; i < files.length; i++) { + this.deleteFile(files[i]); + } + } + fileObj["delete"](); + } + }, + + /** + * Deletes any empty directories under the given directory. + * The startDirIsJavaObject is private to this implementation's + * recursion needs. + */ + deleteEmptyDirs: function (startDir, startDirIsJavaObject) { + var topDir = startDir, + dirFileArray, i, fileObj; + + if (!startDirIsJavaObject) { + topDir = new java.io.File(startDir); + } + + if (topDir.exists()) { + dirFileArray = topDir.listFiles(); + for (i = 0; i < dirFileArray.length; i++) { + fileObj = dirFileArray[i]; + if (fileObj.isDirectory()) { + file.deleteEmptyDirs(fileObj, true); + } + } + + //If the directory is empty now, delete it. + if (topDir.listFiles().length === 0) { + file.deleteFile(String(topDir.getPath())); + } + } + } + }; + + return file; +}); + +} + +if(env === 'xpconnect') { +/** + * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ +//Helper functions to deal with file I/O. + +/*jslint plusplus: false */ +/*global define, Components, xpcUtil */ + +define('xpconnect/file', ['prim'], function (prim) { + var file, + Cc = Components.classes, + Ci = Components.interfaces, + //Depends on xpcUtil which is set up in x.js + xpfile = xpcUtil.xpfile; + + function mkFullDir(dirObj) { + //1 is DIRECTORY_TYPE, 511 is 0777 permissions + if (!dirObj.exists()) { + dirObj.create(1, 511); + } + } + + file = { + backSlashRegExp: /\\/g, + + exclusionRegExp: /^\./, + + getLineSeparator: function () { + return file.lineSeparator; + }, + + lineSeparator: ('@mozilla.org/windows-registry-key;1' in Cc) ? + '\r\n' : '\n', + + exists: function (fileName) { + return xpfile(fileName).exists(); + }, + + parent: function (fileName) { + return xpfile(fileName).parent; + }, + + normalize: function (fileName) { + return file.absPath(fileName); + }, + + isFile: function (path) { + return xpfile(path).isFile(); + }, + + isDirectory: function (path) { + return xpfile(path).isDirectory(); + }, + + /** + * Gets the absolute file path as a string, normalized + * to using front slashes for path separators. + * @param {java.io.File||String} file + */ + absPath: function (fileObj) { + if (typeof fileObj === "string") { + fileObj = xpfile(fileObj); + } + return fileObj.path; + }, + + getFilteredFileList: function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsObject) { + //summary: Recurses startDir and finds matches to the files that match regExpFilters.include + //and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters, + //and it will be treated as the "include" case. + //Ignores files/directories that start with a period (.) unless exclusionRegExp + //is set to another value. + var files = [], topDir, regExpInclude, regExpExclude, dirFileArray, + fileObj, filePath, ok, dirFiles; + + topDir = startDir; + if (!startDirIsObject) { + topDir = xpfile(startDir); + } + + regExpInclude = regExpFilters.include || regExpFilters; + regExpExclude = regExpFilters.exclude || null; + + if (topDir.exists()) { + dirFileArray = topDir.directoryEntries; + while (dirFileArray.hasMoreElements()) { + fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile); + if (fileObj.isFile()) { + filePath = fileObj.path; + if (makeUnixPaths) { + if (filePath.indexOf("/") === -1) { + filePath = filePath.replace(/\\/g, "/"); + } + } + + ok = true; + if (regExpInclude) { + ok = filePath.match(regExpInclude); + } + if (ok && regExpExclude) { + ok = !filePath.match(regExpExclude); + } + + if (ok && (!file.exclusionRegExp || + !file.exclusionRegExp.test(fileObj.leafName))) { + files.push(filePath); + } + } else if (fileObj.isDirectory() && + (!file.exclusionRegExp || !file.exclusionRegExp.test(fileObj.leafName))) { + dirFiles = this.getFilteredFileList(fileObj, regExpFilters, makeUnixPaths, true); + files.push.apply(files, dirFiles); + } + } + } + + return files; //Array + }, + + copyDir: function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) { + //summary: copies files from srcDir to destDir using the regExpFilter to determine if the + //file should be copied. Returns a list file name strings of the destinations that were copied. + regExpFilter = regExpFilter || /\w/; + + var fileNames = file.getFilteredFileList(srcDir, regExpFilter, true), + copiedFiles = [], i, srcFileName, destFileName; + + for (i = 0; i < fileNames.length; i += 1) { + srcFileName = fileNames[i]; + destFileName = srcFileName.replace(srcDir, destDir); + + if (file.copyFile(srcFileName, destFileName, onlyCopyNew)) { + copiedFiles.push(destFileName); + } + } + + return copiedFiles.length ? copiedFiles : null; //Array or null + }, + + copyFile: function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) { + //summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if + //srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred. + var destFile = xpfile(destFileName), + srcFile = xpfile(srcFileName); + + //logger.trace("Src filename: " + srcFileName); + //logger.trace("Dest filename: " + destFileName); + + //If onlyCopyNew is true, then compare dates and only copy if the src is newer + //than dest. + if (onlyCopyNew) { + if (destFile.exists() && destFile.lastModifiedTime >= srcFile.lastModifiedTime) { + return false; //Boolean + } + } + + srcFile.copyTo(destFile.parent, destFile.leafName); + + return true; //Boolean + }, + + /** + * Renames a file. May fail if "to" already exists or is on another drive. + */ + renameFile: function (from, to) { + var toFile = xpfile(to); + return xpfile(from).moveTo(toFile.parent, toFile.leafName); + }, + + readFile: xpcUtil.readFile, + + readFileAsync: function (path, encoding) { + var d = prim(); + try { + d.resolve(file.readFile(path, encoding)); + } catch (e) { + d.reject(e); + } + return d.promise; + }, + + saveUtf8File: function (/*String*/fileName, /*String*/fileContents) { + //summary: saves a file using UTF-8 encoding. + file.saveFile(fileName, fileContents, "utf-8"); + }, + + saveFile: function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) { + var outStream, convertStream, + fileObj = xpfile(fileName); + + mkFullDir(fileObj.parent); + + try { + outStream = Cc['@mozilla.org/network/file-output-stream;1'] + .createInstance(Ci.nsIFileOutputStream); + //438 is decimal for 0777 + outStream.init(fileObj, 0x02 | 0x08 | 0x20, 511, 0); + + convertStream = Cc['@mozilla.org/intl/converter-output-stream;1'] + .createInstance(Ci.nsIConverterOutputStream); + + convertStream.init(outStream, encoding, 0, 0); + convertStream.writeString(fileContents); + } catch (e) { + throw new Error((fileObj && fileObj.path || '') + ': ' + e); + } finally { + if (convertStream) { + convertStream.close(); + } + if (outStream) { + outStream.close(); + } + } + }, + + deleteFile: function (/*String*/fileName) { + //summary: deletes a file or directory if it exists. + var fileObj = xpfile(fileName); + if (fileObj.exists()) { + fileObj.remove(true); + } + }, + + /** + * Deletes any empty directories under the given directory. + * The startDirIsJavaObject is private to this implementation's + * recursion needs. + */ + deleteEmptyDirs: function (startDir, startDirIsObject) { + var topDir = startDir, + dirFileArray, fileObj; + + if (!startDirIsObject) { + topDir = xpfile(startDir); + } + + if (topDir.exists()) { + dirFileArray = topDir.directoryEntries; + while (dirFileArray.hasMoreElements()) { + fileObj = dirFileArray.getNext().QueryInterface(Ci.nsILocalFile); + + if (fileObj.isDirectory()) { + file.deleteEmptyDirs(fileObj, true); + } + } + + //If the directory is empty now, delete it. + dirFileArray = topDir.directoryEntries; + if (!dirFileArray.hasMoreElements()) { + file.deleteFile(topDir.path); + } + } + } + }; + + return file; +}); + +} + +if(env === 'browser') { +/*global process */ +define('browser/quit', function () { + 'use strict'; + return function (code) { + }; +}); +} + +if(env === 'node') { +/*global process */ +define('node/quit', function () { + 'use strict'; + return function (code) { + var draining = 0; + var exit = function () { + if (draining === 0) { + process.exit(code); + } else { + draining -= 1; + } + }; + if (process.stdout.bufferSize) { + draining += 1; + process.stdout.once('drain', exit); + } + if (process.stderr.bufferSize) { + draining += 1; + process.stderr.once('drain', exit); + } + exit(); + }; +}); + +} + +if(env === 'rhino') { +/*global quit */ +define('rhino/quit', function () { + 'use strict'; + return function (code) { + return quit(code); + }; +}); + +} + +if(env === 'xpconnect') { +/*global quit */ +define('xpconnect/quit', function () { + 'use strict'; + return function (code) { + return quit(code); + }; +}); + +} + +if(env === 'browser') { +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, console: false */ + +define('browser/print', function () { + function print(msg) { + console.log(msg); + } + + return print; +}); + +} + +if(env === 'node') { +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, console: false */ + +define('node/print', function () { + function print(msg) { + console.log(msg); + } + + return print; +}); + +} + +if(env === 'rhino') { +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, print: false */ + +define('rhino/print', function () { + return print; +}); + +} + +if(env === 'xpconnect') { +/** + * @license RequireJS Copyright (c) 2013, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false, print: false */ + +define('xpconnect/print', function () { + return print; +}); + +} +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint nomen: false, strict: false */ +/*global define: false */ + +define('logger', ['env!env/print'], function (print) { + var logger = { + TRACE: 0, + INFO: 1, + WARN: 2, + ERROR: 3, + SILENT: 4, + level: 0, + logPrefix: "", + + logLevel: function( level ) { + this.level = level; + }, + + trace: function (message) { + if (this.level <= this.TRACE) { + this._print(message); + } + }, + + info: function (message) { + if (this.level <= this.INFO) { + this._print(message); + } + }, + + warn: function (message) { + if (this.level <= this.WARN) { + this._print(message); + } + }, + + error: function (message) { + if (this.level <= this.ERROR) { + this._print(message); + } + }, + + _print: function (message) { + this._sysPrint((this.logPrefix ? (this.logPrefix + " ") : "") + message); + }, + + _sysPrint: function (message) { + print(message); + } + }; + + return logger; +}); +//Just a blank file to use when building the optimizer with the optimizer, +//so that the build does not attempt to inline some env modules, +//like Node's fs and path. + +/* + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Mathias Bynens + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Kris Kowal + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*jslint bitwise:true plusplus:true */ +/*global esprima:true, define:true, exports:true, window: true, +throwError: true, createLiteral: true, generateStatement: true, +parseAssignmentExpression: true, parseBlock: true, parseExpression: true, +parseFunctionDeclaration: true, parseFunctionExpression: true, +parseFunctionSourceElements: true, parseVariableIdentifier: true, +parseLeftHandSideExpression: true, +parseStatement: true, parseSourceElement: true */ + +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + if (typeof define === 'function' && define.amd) { + define('esprima', ['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.esprima = {})); + } +}(this, function (exports) { + 'use strict'; + + var Token, + TokenName, + Syntax, + PropertyKind, + Messages, + Regex, + source, + strict, + index, + lineNumber, + lineStart, + length, + buffer, + state, + extra; + + Token = { + BooleanLiteral: 1, + EOF: 2, + Identifier: 3, + Keyword: 4, + NullLiteral: 5, + NumericLiteral: 6, + Punctuator: 7, + StringLiteral: 8 + }; + + TokenName = {}; + TokenName[Token.BooleanLiteral] = 'Boolean'; + TokenName[Token.EOF] = ''; + TokenName[Token.Identifier] = 'Identifier'; + TokenName[Token.Keyword] = 'Keyword'; + TokenName[Token.NullLiteral] = 'Null'; + TokenName[Token.NumericLiteral] = 'Numeric'; + TokenName[Token.Punctuator] = 'Punctuator'; + TokenName[Token.StringLiteral] = 'String'; + + Syntax = { + AssignmentExpression: 'AssignmentExpression', + ArrayExpression: 'ArrayExpression', + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DoWhileStatement: 'DoWhileStatement', + DebuggerStatement: 'DebuggerStatement', + EmptyStatement: 'EmptyStatement', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForInStatement: 'ForInStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + Program: 'Program', + Property: 'Property', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SwitchStatement: 'SwitchStatement', + SwitchCase: 'SwitchCase', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement' + }; + + PropertyKind = { + Data: 1, + Get: 2, + Set: 4 + }; + + // Error messages should be identical to V8. + Messages = { + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', + InvalidRegExp: 'Invalid regular expression', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NoCatchOrFinally: 'Missing catch or finally after try', + UnknownLabel: 'Undefined label \'%0\'', + Redeclaration: '%0 \'%1\' has already been declared', + IllegalContinue: 'Illegal continue statement', + IllegalBreak: 'Illegal break statement', + IllegalReturn: 'Illegal return statement', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', + AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', + AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode' + }; + + // See also tools/generate-unicode-regex.py. + Regex = { + NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), + NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') + }; + + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + + function assert(condition, message) { + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + + function sliceSource(from, to) { + return source.slice(from, to); + } + + if (typeof 'esprima'[0] === 'undefined') { + sliceSource = function sliceArraySource(from, to) { + return source.slice(from, to).join(''); + }; + } + + function isDecimalDigit(ch) { + return '0123456789'.indexOf(ch) >= 0; + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + } + + function isOctalDigit(ch) { + return '01234567'.indexOf(ch) >= 0; + } + + + // 7.2 White Space + + function isWhiteSpace(ch) { + return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') || + (ch === '\u000C') || (ch === '\u00A0') || + (ch.charCodeAt(0) >= 0x1680 && + '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0); + } + + // 7.3 Line Terminators + + function isLineTerminator(ch) { + return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029'); + } + + // 7.6 Identifier Names and Identifiers + + function isIdentifierStart(ch) { + return (ch === '$') || (ch === '_') || (ch === '\\') || + (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || + ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch)); + } + + function isIdentifierPart(ch) { + return (ch === '$') || (ch === '_') || (ch === '\\') || + (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || + ((ch >= '0') && (ch <= '9')) || + ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch)); + } + + // 7.6.1.2 Future Reserved Words + + function isFutureReservedWord(id) { + switch (id) { + + // Future reserved words. + case 'class': + case 'enum': + case 'export': + case 'extends': + case 'import': + case 'super': + return true; + } + + return false; + } + + function isStrictModeReservedWord(id) { + switch (id) { + + // Strict Mode reserved words. + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'yield': + case 'let': + return true; + } + + return false; + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + // 7.6.1.1 Keywords + + function isKeyword(id) { + var keyword = false; + switch (id.length) { + case 2: + keyword = (id === 'if') || (id === 'in') || (id === 'do'); + break; + case 3: + keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try'); + break; + case 4: + keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with'); + break; + case 5: + keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw'); + break; + case 6: + keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch'); + break; + case 7: + keyword = (id === 'default') || (id === 'finally'); + break; + case 8: + keyword = (id === 'function') || (id === 'continue') || (id === 'debugger'); + break; + case 10: + keyword = (id === 'instanceof'); + break; + } + + if (keyword) { + return true; + } + + switch (id) { + // Future reserved words. + // 'const' is specialized as Keyword in V8. + case 'const': + return true; + + // For compatiblity to SpiderMonkey and ES.next + case 'yield': + case 'let': + return true; + } + + if (strict && isStrictModeReservedWord(id)) { + return true; + } + + return isFutureReservedWord(id); + } + + // 7.4 Comments + + function skipComment() { + var ch, blockComment, lineComment; + + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source[index]; + + if (lineComment) { + ch = source[index++]; + if (isLineTerminator(ch)) { + lineComment = false; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } + } else if (blockComment) { + if (isLineTerminator(ch)) { + if (ch === '\r' && source[index + 1] === '\n') { + ++index; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source[index++]; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + if (ch === '*') { + ch = source[index]; + if (ch === '/') { + ++index; + blockComment = false; + } + } + } + } else if (ch === '/') { + ch = source[index + 1]; + if (ch === '/') { + index += 2; + lineComment = true; + } else if (ch === '*') { + index += 2; + blockComment = true; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + ++index; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function scanHexEscape(prefix) { + var i, len, ch, code = 0; + + len = (prefix === 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source[index])) { + ch = source[index++]; + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } else { + return ''; + } + } + return String.fromCharCode(code); + } + + function scanIdentifier() { + var ch, start, id, restore; + + ch = source[index]; + if (!isIdentifierStart(ch)) { + return; + } + + start = index; + if (ch === '\\') { + ++index; + if (source[index] !== 'u') { + return; + } + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + if (ch === '\\' || !isIdentifierStart(ch)) { + return; + } + id = ch; + } else { + index = restore; + id = 'u'; + } + } else { + id = source[index++]; + } + + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch)) { + break; + } + if (ch === '\\') { + ++index; + if (source[index] !== 'u') { + return; + } + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + if (ch === '\\' || !isIdentifierPart(ch)) { + return; + } + id += ch; + } else { + index = restore; + id += 'u'; + } + } else { + id += source[index++]; + } + } + + // There is no keyword or literal with only one character. + // Thus, it must be an identifier. + if (id.length === 1) { + return { + type: Token.Identifier, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (isKeyword(id)) { + return { + type: Token.Keyword, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.1 Null Literals + + if (id === 'null') { + return { + type: Token.NullLiteral, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.2 Boolean Literals + + if (id === 'true' || id === 'false') { + return { + type: Token.BooleanLiteral, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + return { + type: Token.Identifier, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.7 Punctuators + + function scanPunctuator() { + var start = index, + ch1 = source[index], + ch2, + ch3, + ch4; + + // Check for most common single-character punctuators. + + if (ch1 === ';' || ch1 === '{' || ch1 === '}') { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === ',' || ch1 === '(' || ch1 === ')') { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // Dot (.) can also start a floating-point number, hence the need + // to check the next character. + + ch2 = source[index + 1]; + if (ch1 === '.' && !isDecimalDigit(ch2)) { + return { + type: Token.Punctuator, + value: source[index++], + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // Peek more characters. + + ch3 = source[index + 2]; + ch4 = source[index + 3]; + + // 4-character punctuator: >>>= + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + if (ch4 === '=') { + index += 4; + return { + type: Token.Punctuator, + value: '>>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // 3-character punctuators: === !== >>> <<= >>= + + if (ch1 === '=' && ch2 === '=' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '===', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '!' && ch2 === '=' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '!==', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + index += 3; + return { + type: Token.Punctuator, + value: '>>>', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '<' && ch2 === '<' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '<<=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '>' && ch2 === '>' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 2-character punctuators: <= >= == != ++ -- << >> && || + // += -= *= %= &= |= ^= /= + + if (ch2 === '=') { + if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { + index += 2; + return { + type: Token.Punctuator, + value: ch1 + ch2, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { + if ('+-<>&|'.indexOf(ch2) >= 0) { + index += 2; + return { + type: Token.Punctuator, + value: ch1 + ch2, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // The remaining 1-character punctuators. + + if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) { + return { + type: Token.Punctuator, + value: source[index++], + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // 7.8.3 Numeric Literals + + function scanNumericLiteral() { + var number, start, ch; + + ch = source[index]; + assert(isDecimalDigit(ch) || (ch === '.'), + 'Numeric literal must start with a decimal digit or a decimal point'); + + start = index; + number = ''; + if (ch !== '.') { + number = source[index++]; + ch = source[index]; + + // Hex number starts with '0x'. + // Octal number starts with '0'. + if (number === '0') { + if (ch === 'x' || ch === 'X') { + number += source[index++]; + while (index < length) { + ch = source[index]; + if (!isHexDigit(ch)) { + break; + } + number += source[index++]; + } + + if (number.length <= 2) { + // only 0x + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (index < length) { + ch = source[index]; + if (isIdentifierStart(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + return { + type: Token.NumericLiteral, + value: parseInt(number, 16), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } else if (isOctalDigit(ch)) { + number += source[index++]; + while (index < length) { + ch = source[index]; + if (!isOctalDigit(ch)) { + break; + } + number += source[index++]; + } + + if (index < length) { + ch = source[index]; + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + return { + type: Token.NumericLiteral, + value: parseInt(number, 8), + octal: true, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // decimal number starts with '0' such as '09' is illegal. + if (isDecimalDigit(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + while (index < length) { + ch = source[index]; + if (!isDecimalDigit(ch)) { + break; + } + number += source[index++]; + } + } + + if (ch === '.') { + number += source[index++]; + while (index < length) { + ch = source[index]; + if (!isDecimalDigit(ch)) { + break; + } + number += source[index++]; + } + } + + if (ch === 'e' || ch === 'E') { + number += source[index++]; + + ch = source[index]; + if (ch === '+' || ch === '-') { + number += source[index++]; + } + + ch = source[index]; + if (isDecimalDigit(ch)) { + number += source[index++]; + while (index < length) { + ch = source[index]; + if (!isDecimalDigit(ch)) { + break; + } + number += source[index++]; + } + } else { + ch = 'character ' + ch; + if (index >= length) { + ch = ''; + } + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + if (index < length) { + ch = source[index]; + if (isIdentifierStart(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + return { + type: Token.NumericLiteral, + value: parseFloat(number), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.4 String Literals + + function scanStringLiteral() { + var str = '', quote, start, ch, code, unescaped, restore, octal = false; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + while (index < length) { + ch = source[index++]; + + if (ch === quote) { + quote = ''; + break; + } else if (ch === '\\') { + ch = source[index++]; + if (!isLineTerminator(ch)) { + switch (ch) { + case 'n': + str += '\n'; + break; + case 'r': + str += '\r'; + break; + case 't': + str += '\t'; + break; + case 'u': + case 'x': + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + str += unescaped; + } else { + index = restore; + str += ch; + } + break; + case 'b': + str += '\b'; + break; + case 'f': + str += '\f'; + break; + case 'v': + str += '\x0B'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + str += String.fromCharCode(code); + } else { + str += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } + } else if (isLineTerminator(ch)) { + break; + } else { + str += ch; + } + } + + if (quote !== '') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.StringLiteral, + value: str, + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanRegExp() { + var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; + + buffer = null; + skipComment(); + + start = index; + ch = source[index]; + assert(ch === '/', 'Regular expression literal must start with a slash'); + str = source[index++]; + + while (index < length) { + ch = source[index++]; + str += ch; + if (ch === '\\') { + ch = source[index++]; + // ECMA-262 7.8.5 + if (isLineTerminator(ch)) { + throwError({}, Messages.UnterminatedRegExp); + } + str += ch; + } else if (classMarker) { + if (ch === ']') { + classMarker = false; + } + } else { + if (ch === '/') { + terminated = true; + break; + } else if (ch === '[') { + classMarker = true; + } else if (isLineTerminator(ch)) { + throwError({}, Messages.UnterminatedRegExp); + } + } + } + + if (!terminated) { + throwError({}, Messages.UnterminatedRegExp); + } + + // Exclude leading and trailing slash. + pattern = str.substr(1, str.length - 2); + + flags = ''; + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch)) { + break; + } + + ++index; + if (ch === '\\' && index < length) { + ch = source[index]; + if (ch === 'u') { + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + flags += ch; + str += '\\u'; + for (; restore < index; ++restore) { + str += source[restore]; + } + } else { + index = restore; + flags += 'u'; + str += '\\u'; + } + } else { + str += '\\'; + } + } else { + flags += ch; + str += ch; + } + } + + try { + value = new RegExp(pattern, flags); + } catch (e) { + throwError({}, Messages.InvalidRegExp); + } + + return { + literal: str, + value: value, + range: [start, index] + }; + } + + function isIdentifierName(token) { + return token.type === Token.Identifier || + token.type === Token.Keyword || + token.type === Token.BooleanLiteral || + token.type === Token.NullLiteral; + } + + function advance() { + var ch, token; + + skipComment(); + + if (index >= length) { + return { + type: Token.EOF, + lineNumber: lineNumber, + lineStart: lineStart, + range: [index, index] + }; + } + + token = scanPunctuator(); + if (typeof token !== 'undefined') { + return token; + } + + ch = source[index]; + + if (ch === '\'' || ch === '"') { + return scanStringLiteral(); + } + + if (ch === '.' || isDecimalDigit(ch)) { + return scanNumericLiteral(); + } + + token = scanIdentifier(); + if (typeof token !== 'undefined') { + return token; + } + + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + function lex() { + var token; + + if (buffer) { + index = buffer.range[1]; + lineNumber = buffer.lineNumber; + lineStart = buffer.lineStart; + token = buffer; + buffer = null; + return token; + } + + buffer = null; + return advance(); + } + + function lookahead() { + var pos, line, start; + + if (buffer !== null) { + return buffer; + } + + pos = index; + line = lineNumber; + start = lineStart; + buffer = advance(); + index = pos; + lineNumber = line; + lineStart = start; + + return buffer; + } + + // Return true if there is a line terminator before the next token. + + function peekLineTerminator() { + var pos, line, start, found; + + pos = index; + line = lineNumber; + start = lineStart; + skipComment(); + found = lineNumber !== line; + index = pos; + lineNumber = line; + lineStart = start; + + return found; + } + + // Throw an exception + + function throwError(token, messageFormat) { + var error, + args = Array.prototype.slice.call(arguments, 2), + msg = messageFormat.replace( + /%(\d)/g, + function (whole, index) { + return args[index] || ''; + } + ); + + if (typeof token.lineNumber === 'number') { + error = new Error('Line ' + token.lineNumber + ': ' + msg); + error.index = token.range[0]; + error.lineNumber = token.lineNumber; + error.column = token.range[0] - lineStart + 1; + } else { + error = new Error('Line ' + lineNumber + ': ' + msg); + error.index = index; + error.lineNumber = lineNumber; + error.column = index - lineStart + 1; + } + + throw error; + } + + function throwErrorTolerant() { + try { + throwError.apply(null, arguments); + } catch (e) { + if (extra.errors) { + extra.errors.push(e); + } else { + throw e; + } + } + } + + + // Throw an exception because of the token. + + function throwUnexpected(token) { + if (token.type === Token.EOF) { + throwError(token, Messages.UnexpectedEOS); + } + + if (token.type === Token.NumericLiteral) { + throwError(token, Messages.UnexpectedNumber); + } + + if (token.type === Token.StringLiteral) { + throwError(token, Messages.UnexpectedString); + } + + if (token.type === Token.Identifier) { + throwError(token, Messages.UnexpectedIdentifier); + } + + if (token.type === Token.Keyword) { + if (isFutureReservedWord(token.value)) { + throwError(token, Messages.UnexpectedReserved); + } else if (strict && isStrictModeReservedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictReservedWord); + return; + } + throwError(token, Messages.UnexpectedToken, token.value); + } + + // BooleanLiteral, NullLiteral, or Punctuator. + throwError(token, Messages.UnexpectedToken, token.value); + } + + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + + function expect(value) { + var token = lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + throwUnexpected(token); + } + } + + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + + function expectKeyword(keyword) { + var token = lex(); + if (token.type !== Token.Keyword || token.value !== keyword) { + throwUnexpected(token); + } + } + + // Return true if the next token matches the specified punctuator. + + function match(value) { + var token = lookahead(); + return token.type === Token.Punctuator && token.value === value; + } + + // Return true if the next token matches the specified keyword + + function matchKeyword(keyword) { + var token = lookahead(); + return token.type === Token.Keyword && token.value === keyword; + } + + // Return true if the next token is an assignment operator + + function matchAssign() { + var token = lookahead(), + op = token.value; + + if (token.type !== Token.Punctuator) { + return false; + } + return op === '=' || + op === '*=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + } + + function consumeSemicolon() { + var token, line; + + // Catch the very common case first. + if (source[index] === ';') { + lex(); + return; + } + + line = lineNumber; + skipComment(); + if (lineNumber !== line) { + return; + } + + if (match(';')) { + lex(); + return; + } + + token = lookahead(); + if (token.type !== Token.EOF && !match('}')) { + throwUnexpected(token); + } + } + + // Return true if provided expression is LeftHandSideExpression + + function isLeftHandSide(expr) { + return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; + } + + // 11.1.4 Array Initialiser + + function parseArrayInitialiser() { + var elements = []; + + expect('['); + + while (!match(']')) { + if (match(',')) { + lex(); + elements.push(null); + } else { + elements.push(parseAssignmentExpression()); + + if (!match(']')) { + expect(','); + } + } + } + + expect(']'); + + return { + type: Syntax.ArrayExpression, + elements: elements + }; + } + + // 11.1.5 Object Initialiser + + function parsePropertyFunction(param, first) { + var previousStrict, body; + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (first && strict && isRestrictedWord(param[0].name)) { + throwErrorTolerant(first, Messages.StrictParamName); + } + strict = previousStrict; + + return { + type: Syntax.FunctionExpression, + id: null, + params: param, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }; + } + + function parseObjectPropertyKey() { + var token = lex(); + + // Note: This function is called only from parseObjectProperty(), where + // EOF and Punctuator tokens are already filtered out. + + if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { + if (strict && token.octal) { + throwErrorTolerant(token, Messages.StrictOctalLiteral); + } + return createLiteral(token); + } + + return { + type: Syntax.Identifier, + name: token.value + }; + } + + function parseObjectProperty() { + var token, key, id, param; + + token = lookahead(); + + if (token.type === Token.Identifier) { + + id = parseObjectPropertyKey(); + + // Property Assignment: Getter and Setter. + + if (token.value === 'get' && !match(':')) { + key = parseObjectPropertyKey(); + expect('('); + expect(')'); + return { + type: Syntax.Property, + key: key, + value: parsePropertyFunction([]), + kind: 'get' + }; + } else if (token.value === 'set' && !match(':')) { + key = parseObjectPropertyKey(); + expect('('); + token = lookahead(); + if (token.type !== Token.Identifier) { + expect(')'); + throwErrorTolerant(token, Messages.UnexpectedToken, token.value); + return { + type: Syntax.Property, + key: key, + value: parsePropertyFunction([]), + kind: 'set' + }; + } else { + param = [ parseVariableIdentifier() ]; + expect(')'); + return { + type: Syntax.Property, + key: key, + value: parsePropertyFunction(param, token), + kind: 'set' + }; + } + } else { + expect(':'); + return { + type: Syntax.Property, + key: id, + value: parseAssignmentExpression(), + kind: 'init' + }; + } + } else if (token.type === Token.EOF || token.type === Token.Punctuator) { + throwUnexpected(token); + } else { + key = parseObjectPropertyKey(); + expect(':'); + return { + type: Syntax.Property, + key: key, + value: parseAssignmentExpression(), + kind: 'init' + }; + } + } + + function parseObjectInitialiser() { + var properties = [], property, name, kind, map = {}, toString = String; + + expect('{'); + + while (!match('}')) { + property = parseObjectProperty(); + + if (property.key.type === Syntax.Identifier) { + name = property.key.name; + } else { + name = toString(property.key.value); + } + kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; + if (Object.prototype.hasOwnProperty.call(map, name)) { + if (map[name] === PropertyKind.Data) { + if (strict && kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.StrictDuplicateProperty); + } else if (kind !== PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } + } else { + if (kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } else if (map[name] & kind) { + throwErrorTolerant({}, Messages.AccessorGetSet); + } + } + map[name] |= kind; + } else { + map[name] = kind; + } + + properties.push(property); + + if (!match('}')) { + expect(','); + } + } + + expect('}'); + + return { + type: Syntax.ObjectExpression, + properties: properties + }; + } + + // 11.1.6 The Grouping Operator + + function parseGroupExpression() { + var expr; + + expect('('); + + expr = parseExpression(); + + expect(')'); + + return expr; + } + + + // 11.1 Primary Expressions + + function parsePrimaryExpression() { + var token = lookahead(), + type = token.type; + + if (type === Token.Identifier) { + return { + type: Syntax.Identifier, + name: lex().value + }; + } + + if (type === Token.StringLiteral || type === Token.NumericLiteral) { + if (strict && token.octal) { + throwErrorTolerant(token, Messages.StrictOctalLiteral); + } + return createLiteral(lex()); + } + + if (type === Token.Keyword) { + if (matchKeyword('this')) { + lex(); + return { + type: Syntax.ThisExpression + }; + } + + if (matchKeyword('function')) { + return parseFunctionExpression(); + } + } + + if (type === Token.BooleanLiteral) { + lex(); + token.value = (token.value === 'true'); + return createLiteral(token); + } + + if (type === Token.NullLiteral) { + lex(); + token.value = null; + return createLiteral(token); + } + + if (match('[')) { + return parseArrayInitialiser(); + } + + if (match('{')) { + return parseObjectInitialiser(); + } + + if (match('(')) { + return parseGroupExpression(); + } + + if (match('/') || match('/=')) { + return createLiteral(scanRegExp()); + } + + return throwUnexpected(lex()); + } + + // 11.2 Left-Hand-Side Expressions + + function parseArguments() { + var args = []; + + expect('('); + + if (!match(')')) { + while (index < length) { + args.push(parseAssignmentExpression()); + if (match(')')) { + break; + } + expect(','); + } + } + + expect(')'); + + return args; + } + + function parseNonComputedProperty() { + var token = lex(); + + if (!isIdentifierName(token)) { + throwUnexpected(token); + } + + return { + type: Syntax.Identifier, + name: token.value + }; + } + + function parseNonComputedMember() { + expect('.'); + + return parseNonComputedProperty(); + } + + function parseComputedMember() { + var expr; + + expect('['); + + expr = parseExpression(); + + expect(']'); + + return expr; + } + + function parseNewExpression() { + var expr; + + expectKeyword('new'); + + expr = { + type: Syntax.NewExpression, + callee: parseLeftHandSideExpression(), + 'arguments': [] + }; + + if (match('(')) { + expr['arguments'] = parseArguments(); + } + + return expr; + } + + function parseLeftHandSideExpressionAllowCall() { + var expr; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(')) { + if (match('(')) { + expr = { + type: Syntax.CallExpression, + callee: expr, + 'arguments': parseArguments() + }; + } else if (match('[')) { + expr = { + type: Syntax.MemberExpression, + computed: true, + object: expr, + property: parseComputedMember() + }; + } else { + expr = { + type: Syntax.MemberExpression, + computed: false, + object: expr, + property: parseNonComputedMember() + }; + } + } + + return expr; + } + + + function parseLeftHandSideExpression() { + var expr; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[')) { + if (match('[')) { + expr = { + type: Syntax.MemberExpression, + computed: true, + object: expr, + property: parseComputedMember() + }; + } else { + expr = { + type: Syntax.MemberExpression, + computed: false, + object: expr, + property: parseNonComputedMember() + }; + } + } + + return expr; + } + + // 11.3 Postfix Expressions + + function parsePostfixExpression() { + var expr = parseLeftHandSideExpressionAllowCall(), token; + + token = lookahead(); + if (token.type !== Token.Punctuator) { + return expr; + } + + if ((match('++') || match('--')) && !peekLineTerminator()) { + // 11.3.1, 11.3.2 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPostfix); + } + if (!isLeftHandSide(expr)) { + throwErrorTolerant({}, Messages.InvalidLHSInAssignment); + } + + expr = { + type: Syntax.UpdateExpression, + operator: lex().value, + argument: expr, + prefix: false + }; + } + + return expr; + } + + // 11.4 Unary Operators + + function parseUnaryExpression() { + var token, expr; + + token = lookahead(); + if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { + return parsePostfixExpression(); + } + + if (match('++') || match('--')) { + token = lex(); + expr = parseUnaryExpression(); + // 11.4.4, 11.4.5 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPrefix); + } + + if (!isLeftHandSide(expr)) { + throwErrorTolerant({}, Messages.InvalidLHSInAssignment); + } + + expr = { + type: Syntax.UpdateExpression, + operator: token.value, + argument: expr, + prefix: true + }; + return expr; + } + + if (match('+') || match('-') || match('~') || match('!')) { + expr = { + type: Syntax.UnaryExpression, + operator: lex().value, + argument: parseUnaryExpression(), + prefix: true + }; + return expr; + } + + if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { + expr = { + type: Syntax.UnaryExpression, + operator: lex().value, + argument: parseUnaryExpression(), + prefix: true + }; + if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { + throwErrorTolerant({}, Messages.StrictDelete); + } + return expr; + } + + return parsePostfixExpression(); + } + + // 11.5 Multiplicative Operators + + function parseMultiplicativeExpression() { + var expr = parseUnaryExpression(); + + while (match('*') || match('/') || match('%')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseUnaryExpression() + }; + } + + return expr; + } + + // 11.6 Additive Operators + + function parseAdditiveExpression() { + var expr = parseMultiplicativeExpression(); + + while (match('+') || match('-')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseMultiplicativeExpression() + }; + } + + return expr; + } + + // 11.7 Bitwise Shift Operators + + function parseShiftExpression() { + var expr = parseAdditiveExpression(); + + while (match('<<') || match('>>') || match('>>>')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseAdditiveExpression() + }; + } + + return expr; + } + // 11.8 Relational Operators + + function parseRelationalExpression() { + var expr, previousAllowIn; + + previousAllowIn = state.allowIn; + state.allowIn = true; + + expr = parseShiftExpression(); + + while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseShiftExpression() + }; + } + + state.allowIn = previousAllowIn; + return expr; + } + + // 11.9 Equality Operators + + function parseEqualityExpression() { + var expr = parseRelationalExpression(); + + while (match('==') || match('!=') || match('===') || match('!==')) { + expr = { + type: Syntax.BinaryExpression, + operator: lex().value, + left: expr, + right: parseRelationalExpression() + }; + } + + return expr; + } + + // 11.10 Binary Bitwise Operators + + function parseBitwiseANDExpression() { + var expr = parseEqualityExpression(); + + while (match('&')) { + lex(); + expr = { + type: Syntax.BinaryExpression, + operator: '&', + left: expr, + right: parseEqualityExpression() + }; + } + + return expr; + } + + function parseBitwiseXORExpression() { + var expr = parseBitwiseANDExpression(); + + while (match('^')) { + lex(); + expr = { + type: Syntax.BinaryExpression, + operator: '^', + left: expr, + right: parseBitwiseANDExpression() + }; + } + + return expr; + } + + function parseBitwiseORExpression() { + var expr = parseBitwiseXORExpression(); + + while (match('|')) { + lex(); + expr = { + type: Syntax.BinaryExpression, + operator: '|', + left: expr, + right: parseBitwiseXORExpression() + }; + } + + return expr; + } + + // 11.11 Binary Logical Operators + + function parseLogicalANDExpression() { + var expr = parseBitwiseORExpression(); + + while (match('&&')) { + lex(); + expr = { + type: Syntax.LogicalExpression, + operator: '&&', + left: expr, + right: parseBitwiseORExpression() + }; + } + + return expr; + } + + function parseLogicalORExpression() { + var expr = parseLogicalANDExpression(); + + while (match('||')) { + lex(); + expr = { + type: Syntax.LogicalExpression, + operator: '||', + left: expr, + right: parseLogicalANDExpression() + }; + } + + return expr; + } + + // 11.12 Conditional Operator + + function parseConditionalExpression() { + var expr, previousAllowIn, consequent; + + expr = parseLogicalORExpression(); + + if (match('?')) { + lex(); + previousAllowIn = state.allowIn; + state.allowIn = true; + consequent = parseAssignmentExpression(); + state.allowIn = previousAllowIn; + expect(':'); + + expr = { + type: Syntax.ConditionalExpression, + test: expr, + consequent: consequent, + alternate: parseAssignmentExpression() + }; + } + + return expr; + } + + // 11.13 Assignment Operators + + function parseAssignmentExpression() { + var token, expr; + + token = lookahead(); + expr = parseConditionalExpression(); + + if (matchAssign()) { + // LeftHandSideExpression + if (!isLeftHandSide(expr)) { + throwErrorTolerant({}, Messages.InvalidLHSInAssignment); + } + + // 11.13.1 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant(token, Messages.StrictLHSAssignment); + } + + expr = { + type: Syntax.AssignmentExpression, + operator: lex().value, + left: expr, + right: parseAssignmentExpression() + }; + } + + return expr; + } + + // 11.14 Comma Operator + + function parseExpression() { + var expr = parseAssignmentExpression(); + + if (match(',')) { + expr = { + type: Syntax.SequenceExpression, + expressions: [ expr ] + }; + + while (index < length) { + if (!match(',')) { + break; + } + lex(); + expr.expressions.push(parseAssignmentExpression()); + } + + } + return expr; + } + + // 12.1 Block + + function parseStatementList() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseSourceElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseBlock() { + var block; + + expect('{'); + + block = parseStatementList(); + + expect('}'); + + return { + type: Syntax.BlockStatement, + body: block + }; + } + + // 12.2 Variable Statement + + function parseVariableIdentifier() { + var token = lex(); + + if (token.type !== Token.Identifier) { + throwUnexpected(token); + } + + return { + type: Syntax.Identifier, + name: token.value + }; + } + + function parseVariableDeclaration(kind) { + var id = parseVariableIdentifier(), + init = null; + + // 12.2.1 + if (strict && isRestrictedWord(id.name)) { + throwErrorTolerant({}, Messages.StrictVarName); + } + + if (kind === 'const') { + expect('='); + init = parseAssignmentExpression(); + } else if (match('=')) { + lex(); + init = parseAssignmentExpression(); + } + + return { + type: Syntax.VariableDeclarator, + id: id, + init: init + }; + } + + function parseVariableDeclarationList(kind) { + var list = []; + + do { + list.push(parseVariableDeclaration(kind)); + if (!match(',')) { + break; + } + lex(); + } while (index < length); + + return list; + } + + function parseVariableStatement() { + var declarations; + + expectKeyword('var'); + + declarations = parseVariableDeclarationList(); + + consumeSemicolon(); + + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: 'var' + }; + } + + // kind may be `const` or `let` + // Both are experimental and not in the specification yet. + // see http://wiki.ecmascript.org/doku.php?id=harmony:const + // and http://wiki.ecmascript.org/doku.php?id=harmony:let + function parseConstLetDeclaration(kind) { + var declarations; + + expectKeyword(kind); + + declarations = parseVariableDeclarationList(kind); + + consumeSemicolon(); + + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: kind + }; + } + + // 12.3 Empty Statement + + function parseEmptyStatement() { + expect(';'); + + return { + type: Syntax.EmptyStatement + }; + } + + // 12.4 Expression Statement + + function parseExpressionStatement() { + var expr = parseExpression(); + + consumeSemicolon(); + + return { + type: Syntax.ExpressionStatement, + expression: expr + }; + } + + // 12.5 If statement + + function parseIfStatement() { + var test, consequent, alternate; + + expectKeyword('if'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + consequent = parseStatement(); + + if (matchKeyword('else')) { + lex(); + alternate = parseStatement(); + } else { + alternate = null; + } + + return { + type: Syntax.IfStatement, + test: test, + consequent: consequent, + alternate: alternate + }; + } + + // 12.6 Iteration Statements + + function parseDoWhileStatement() { + var body, test, oldInIteration; + + expectKeyword('do'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + if (match(';')) { + lex(); + } + + return { + type: Syntax.DoWhileStatement, + body: body, + test: test + }; + } + + function parseWhileStatement() { + var test, body, oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return { + type: Syntax.WhileStatement, + test: test, + body: body + }; + } + + function parseForVariableDeclaration() { + var token = lex(); + + return { + type: Syntax.VariableDeclaration, + declarations: parseVariableDeclarationList(), + kind: token.value + }; + } + + function parseForStatement() { + var init, test, update, left, right, body, oldInIteration; + + init = test = update = null; + + expectKeyword('for'); + + expect('('); + + if (match(';')) { + lex(); + } else { + if (matchKeyword('var') || matchKeyword('let')) { + state.allowIn = false; + init = parseForVariableDeclaration(); + state.allowIn = true; + + if (init.declarations.length === 1 && matchKeyword('in')) { + lex(); + left = init; + right = parseExpression(); + init = null; + } + } else { + state.allowIn = false; + init = parseExpression(); + state.allowIn = true; + + if (matchKeyword('in')) { + // LeftHandSideExpression + if (!isLeftHandSide(init)) { + throwErrorTolerant({}, Messages.InvalidLHSInForIn); + } + + lex(); + left = init; + right = parseExpression(); + init = null; + } + } + + if (typeof left === 'undefined') { + expect(';'); + } + } + + if (typeof left === 'undefined') { + + if (!match(';')) { + test = parseExpression(); + } + expect(';'); + + if (!match(')')) { + update = parseExpression(); + } + } + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + if (typeof left === 'undefined') { + return { + type: Syntax.ForStatement, + init: init, + test: test, + update: update, + body: body + }; + } + + return { + type: Syntax.ForInStatement, + left: left, + right: right, + body: body, + each: false + }; + } + + // 12.7 The continue statement + + function parseContinueStatement() { + var token, label = null; + + expectKeyword('continue'); + + // Optimize the most common form: 'continue;'. + if (source[index] === ';') { + lex(); + + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return { + type: Syntax.ContinueStatement, + label: null + }; + } + + if (peekLineTerminator()) { + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return { + type: Syntax.ContinueStatement, + label: null + }; + } + + token = lookahead(); + if (token.type === Token.Identifier) { + label = parseVariableIdentifier(); + + if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return { + type: Syntax.ContinueStatement, + label: label + }; + } + + // 12.8 The break statement + + function parseBreakStatement() { + var token, label = null; + + expectKeyword('break'); + + // Optimize the most common form: 'break;'. + if (source[index] === ';') { + lex(); + + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return { + type: Syntax.BreakStatement, + label: null + }; + } + + if (peekLineTerminator()) { + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return { + type: Syntax.BreakStatement, + label: null + }; + } + + token = lookahead(); + if (token.type === Token.Identifier) { + label = parseVariableIdentifier(); + + if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return { + type: Syntax.BreakStatement, + label: label + }; + } + + // 12.9 The return statement + + function parseReturnStatement() { + var token, argument = null; + + expectKeyword('return'); + + if (!state.inFunctionBody) { + throwErrorTolerant({}, Messages.IllegalReturn); + } + + // 'return' followed by a space and an identifier is very common. + if (source[index] === ' ') { + if (isIdentifierStart(source[index + 1])) { + argument = parseExpression(); + consumeSemicolon(); + return { + type: Syntax.ReturnStatement, + argument: argument + }; + } + } + + if (peekLineTerminator()) { + return { + type: Syntax.ReturnStatement, + argument: null + }; + } + + if (!match(';')) { + token = lookahead(); + if (!match('}') && token.type !== Token.EOF) { + argument = parseExpression(); + } + } + + consumeSemicolon(); + + return { + type: Syntax.ReturnStatement, + argument: argument + }; + } + + // 12.10 The with statement + + function parseWithStatement() { + var object, body; + + if (strict) { + throwErrorTolerant({}, Messages.StrictModeWith); + } + + expectKeyword('with'); + + expect('('); + + object = parseExpression(); + + expect(')'); + + body = parseStatement(); + + return { + type: Syntax.WithStatement, + object: object, + body: body + }; + } + + // 12.10 The swith statement + + function parseSwitchCase() { + var test, + consequent = [], + statement; + + if (matchKeyword('default')) { + lex(); + test = null; + } else { + expectKeyword('case'); + test = parseExpression(); + } + expect(':'); + + while (index < length) { + if (match('}') || matchKeyword('default') || matchKeyword('case')) { + break; + } + statement = parseStatement(); + if (typeof statement === 'undefined') { + break; + } + consequent.push(statement); + } + + return { + type: Syntax.SwitchCase, + test: test, + consequent: consequent + }; + } + + function parseSwitchStatement() { + var discriminant, cases, clause, oldInSwitch, defaultFound; + + expectKeyword('switch'); + + expect('('); + + discriminant = parseExpression(); + + expect(')'); + + expect('{'); + + cases = []; + + if (match('}')) { + lex(); + return { + type: Syntax.SwitchStatement, + discriminant: discriminant, + cases: cases + }; + } + + oldInSwitch = state.inSwitch; + state.inSwitch = true; + defaultFound = false; + + while (index < length) { + if (match('}')) { + break; + } + clause = parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + throwError({}, Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + + state.inSwitch = oldInSwitch; + + expect('}'); + + return { + type: Syntax.SwitchStatement, + discriminant: discriminant, + cases: cases + }; + } + + // 12.13 The throw statement + + function parseThrowStatement() { + var argument; + + expectKeyword('throw'); + + if (peekLineTerminator()) { + throwError({}, Messages.NewlineAfterThrow); + } + + argument = parseExpression(); + + consumeSemicolon(); + + return { + type: Syntax.ThrowStatement, + argument: argument + }; + } + + // 12.14 The try statement + + function parseCatchClause() { + var param; + + expectKeyword('catch'); + + expect('('); + if (match(')')) { + throwUnexpected(lookahead()); + } + + param = parseVariableIdentifier(); + // 12.14.1 + if (strict && isRestrictedWord(param.name)) { + throwErrorTolerant({}, Messages.StrictCatchVariable); + } + + expect(')'); + + return { + type: Syntax.CatchClause, + param: param, + body: parseBlock() + }; + } + + function parseTryStatement() { + var block, handlers = [], finalizer = null; + + expectKeyword('try'); + + block = parseBlock(); + + if (matchKeyword('catch')) { + handlers.push(parseCatchClause()); + } + + if (matchKeyword('finally')) { + lex(); + finalizer = parseBlock(); + } + + if (handlers.length === 0 && !finalizer) { + throwError({}, Messages.NoCatchOrFinally); + } + + return { + type: Syntax.TryStatement, + block: block, + guardedHandlers: [], + handlers: handlers, + finalizer: finalizer + }; + } + + // 12.15 The debugger statement + + function parseDebuggerStatement() { + expectKeyword('debugger'); + + consumeSemicolon(); + + return { + type: Syntax.DebuggerStatement + }; + } + + // 12 Statements + + function parseStatement() { + var token = lookahead(), + expr, + labeledBody; + + if (token.type === Token.EOF) { + throwUnexpected(token); + } + + if (token.type === Token.Punctuator) { + switch (token.value) { + case ';': + return parseEmptyStatement(); + case '{': + return parseBlock(); + case '(': + return parseExpressionStatement(); + default: + break; + } + } + + if (token.type === Token.Keyword) { + switch (token.value) { + case 'break': + return parseBreakStatement(); + case 'continue': + return parseContinueStatement(); + case 'debugger': + return parseDebuggerStatement(); + case 'do': + return parseDoWhileStatement(); + case 'for': + return parseForStatement(); + case 'function': + return parseFunctionDeclaration(); + case 'if': + return parseIfStatement(); + case 'return': + return parseReturnStatement(); + case 'switch': + return parseSwitchStatement(); + case 'throw': + return parseThrowStatement(); + case 'try': + return parseTryStatement(); + case 'var': + return parseVariableStatement(); + case 'while': + return parseWhileStatement(); + case 'with': + return parseWithStatement(); + default: + break; + } + } + + expr = parseExpression(); + + // 12.12 Labelled Statements + if ((expr.type === Syntax.Identifier) && match(':')) { + lex(); + + if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) { + throwError({}, Messages.Redeclaration, 'Label', expr.name); + } + + state.labelSet[expr.name] = true; + labeledBody = parseStatement(); + delete state.labelSet[expr.name]; + + return { + type: Syntax.LabeledStatement, + label: expr, + body: labeledBody + }; + } + + consumeSemicolon(); + + return { + type: Syntax.ExpressionStatement, + expression: expr + }; + } + + // 13 Function Definition + + function parseFunctionSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted, + oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody; + + expect('{'); + + while (index < length) { + token = lookahead(); + if (token.type !== Token.StringLiteral) { + break; + } + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = sliceSource(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + oldLabelSet = state.labelSet; + oldInIteration = state.inIteration; + oldInSwitch = state.inSwitch; + oldInFunctionBody = state.inFunctionBody; + + state.labelSet = {}; + state.inIteration = false; + state.inSwitch = false; + state.inFunctionBody = true; + + while (index < length) { + if (match('}')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + + expect('}'); + + state.labelSet = oldLabelSet; + state.inIteration = oldInIteration; + state.inSwitch = oldInSwitch; + state.inFunctionBody = oldInFunctionBody; + + return { + type: Syntax.BlockStatement, + body: sourceElements + }; + } + + function parseFunctionDeclaration() { + var id, param, params = [], body, token, stricted, firstRestricted, message, previousStrict, paramSet; + + expectKeyword('function'); + token = lookahead(); + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + + expect('('); + + if (!match(')')) { + paramSet = {}; + while (index < length) { + token = lookahead(); + param = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + stricted = token; + message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { + stricted = token; + message = Messages.StrictParamDupe; + } + } else if (!firstRestricted) { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { + firstRestricted = token; + message = Messages.StrictParamDupe; + } + } + params.push(param); + paramSet[param.name] = true; + if (match(')')) { + break; + } + expect(','); + } + } + + expect(')'); + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && stricted) { + throwErrorTolerant(stricted, message); + } + strict = previousStrict; + + return { + type: Syntax.FunctionDeclaration, + id: id, + params: params, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }; + } + + function parseFunctionExpression() { + var token, id = null, stricted, firstRestricted, message, param, params = [], body, previousStrict, paramSet; + + expectKeyword('function'); + + if (!match('(')) { + token = lookahead(); + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + expect('('); + + if (!match(')')) { + paramSet = {}; + while (index < length) { + token = lookahead(); + param = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + stricted = token; + message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { + stricted = token; + message = Messages.StrictParamDupe; + } + } else if (!firstRestricted) { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) { + firstRestricted = token; + message = Messages.StrictParamDupe; + } + } + params.push(param); + paramSet[param.name] = true; + if (match(')')) { + break; + } + expect(','); + } + } + + expect(')'); + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && stricted) { + throwErrorTolerant(stricted, message); + } + strict = previousStrict; + + return { + type: Syntax.FunctionExpression, + id: id, + params: params, + defaults: [], + body: body, + rest: null, + generator: false, + expression: false + }; + } + + // 14 Program + + function parseSourceElement() { + var token = lookahead(); + + if (token.type === Token.Keyword) { + switch (token.value) { + case 'const': + case 'let': + return parseConstLetDeclaration(token.value); + case 'function': + return parseFunctionDeclaration(); + default: + return parseStatement(); + } + } + + if (token.type !== Token.EOF) { + return parseStatement(); + } + } + + function parseSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted; + + while (index < length) { + token = lookahead(); + if (token.type !== Token.StringLiteral) { + break; + } + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = sliceSource(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + while (index < length) { + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + return sourceElements; + } + + function parseProgram() { + var program; + strict = false; + program = { + type: Syntax.Program, + body: parseSourceElements() + }; + return program; + } + + // The following functions are needed only when the option to preserve + // the comments is active. + + function addComment(type, value, start, end, loc) { + assert(typeof start === 'number', 'Comment must have valid position'); + + // Because the way the actual token is scanned, often the comments + // (if any) are skipped twice during the lexical analysis. + // Thus, we need to skip adding a comment if the comment array already + // handled it. + if (extra.comments.length > 0) { + if (extra.comments[extra.comments.length - 1].range[1] > start) { + return; + } + } + + extra.comments.push({ + type: type, + value: value, + range: [start, end], + loc: loc + }); + } + + function scanComment() { + var comment, ch, loc, start, blockComment, lineComment; + + comment = ''; + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source[index]; + + if (lineComment) { + ch = source[index++]; + if (isLineTerminator(ch)) { + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + lineComment = false; + addComment('Line', comment, start, index - 1, loc); + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + comment = ''; + } else if (index >= length) { + lineComment = false; + comment += ch; + loc.end = { + line: lineNumber, + column: length - lineStart + }; + addComment('Line', comment, start, length, loc); + } else { + comment += ch; + } + } else if (blockComment) { + if (isLineTerminator(ch)) { + if (ch === '\r' && source[index + 1] === '\n') { + ++index; + comment += '\r\n'; + } else { + comment += ch; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source[index++]; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + comment += ch; + if (ch === '*') { + ch = source[index]; + if (ch === '/') { + comment = comment.substr(0, comment.length - 1); + blockComment = false; + ++index; + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); + comment = ''; + } + } + } + } else if (ch === '/') { + ch = source[index + 1]; + if (ch === '/') { + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + start = index; + index += 2; + lineComment = true; + if (index >= length) { + loc.end = { + line: lineNumber, + column: index - lineStart + }; + lineComment = false; + addComment('Line', comment, start, index, loc); + } + } else if (ch === '*') { + start = index; + index += 2; + blockComment = true; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + ++index; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function filterCommentLocation() { + var i, entry, comment, comments = []; + + for (i = 0; i < extra.comments.length; ++i) { + entry = extra.comments[i]; + comment = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + comment.range = entry.range; + } + if (extra.loc) { + comment.loc = entry.loc; + } + comments.push(comment); + } + + extra.comments = comments; + } + + function collectToken() { + var start, loc, token, range, value; + + skipComment(); + start = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + token = extra.advance(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + if (token.type !== Token.EOF) { + range = [token.range[0], token.range[1]]; + value = sliceSource(token.range[0], token.range[1]); + extra.tokens.push({ + type: TokenName[token.type], + value: value, + range: range, + loc: loc + }); + } + + return token; + } + + function collectRegex() { + var pos, loc, regex, token; + + skipComment(); + + pos = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + regex = extra.scanRegExp(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + // Pop the previous token, which is likely '/' or '/=' + if (extra.tokens.length > 0) { + token = extra.tokens[extra.tokens.length - 1]; + if (token.range[0] === pos && token.type === 'Punctuator') { + if (token.value === '/' || token.value === '/=') { + extra.tokens.pop(); + } + } + } + + extra.tokens.push({ + type: 'RegularExpression', + value: regex.literal, + range: [pos, index], + loc: loc + }); + + return regex; + } + + function filterTokenLocation() { + var i, entry, token, tokens = []; + + for (i = 0; i < extra.tokens.length; ++i) { + entry = extra.tokens[i]; + token = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + token.range = entry.range; + } + if (extra.loc) { + token.loc = entry.loc; + } + tokens.push(token); + } + + extra.tokens = tokens; + } + + function createLiteral(token) { + return { + type: Syntax.Literal, + value: token.value + }; + } + + function createRawLiteral(token) { + return { + type: Syntax.Literal, + value: token.value, + raw: sliceSource(token.range[0], token.range[1]) + }; + } + + function createLocationMarker() { + var marker = {}; + + marker.range = [index, index]; + marker.loc = { + start: { + line: lineNumber, + column: index - lineStart + }, + end: { + line: lineNumber, + column: index - lineStart + } + }; + + marker.end = function () { + this.range[1] = index; + this.loc.end.line = lineNumber; + this.loc.end.column = index - lineStart; + }; + + marker.applyGroup = function (node) { + if (extra.range) { + node.groupRange = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.groupLoc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + } + }; + + marker.apply = function (node) { + if (extra.range) { + node.range = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.loc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + } + }; + + return marker; + } + + function trackGroupExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + expect('('); + + expr = parseExpression(); + + expect(')'); + + marker.end(); + marker.applyGroup(expr); + + return expr; + } + + function trackLeftHandSideExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[')) { + if (match('[')) { + expr = { + type: Syntax.MemberExpression, + computed: true, + object: expr, + property: parseComputedMember() + }; + marker.end(); + marker.apply(expr); + } else { + expr = { + type: Syntax.MemberExpression, + computed: false, + object: expr, + property: parseNonComputedMember() + }; + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function trackLeftHandSideExpressionAllowCall() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(')) { + if (match('(')) { + expr = { + type: Syntax.CallExpression, + callee: expr, + 'arguments': parseArguments() + }; + marker.end(); + marker.apply(expr); + } else if (match('[')) { + expr = { + type: Syntax.MemberExpression, + computed: true, + object: expr, + property: parseComputedMember() + }; + marker.end(); + marker.apply(expr); + } else { + expr = { + type: Syntax.MemberExpression, + computed: false, + object: expr, + property: parseNonComputedMember() + }; + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function filterGroup(node) { + var n, i, entry; + + n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {}; + for (i in node) { + if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') { + entry = node[i]; + if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) { + n[i] = entry; + } else { + n[i] = filterGroup(entry); + } + } + } + return n; + } + + function wrapTrackingFunction(range, loc) { + + return function (parseFunction) { + + function isBinary(node) { + return node.type === Syntax.LogicalExpression || + node.type === Syntax.BinaryExpression; + } + + function visit(node) { + var start, end; + + if (isBinary(node.left)) { + visit(node.left); + } + if (isBinary(node.right)) { + visit(node.right); + } + + if (range) { + if (node.left.groupRange || node.right.groupRange) { + start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0]; + end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1]; + node.range = [start, end]; + } else if (typeof node.range === 'undefined') { + start = node.left.range[0]; + end = node.right.range[1]; + node.range = [start, end]; + } + } + if (loc) { + if (node.left.groupLoc || node.right.groupLoc) { + start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start; + end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end; + node.loc = { + start: start, + end: end + }; + } else if (typeof node.loc === 'undefined') { + node.loc = { + start: node.left.loc.start, + end: node.right.loc.end + }; + } + } + } + + return function () { + var marker, node; + + skipComment(); + + marker = createLocationMarker(); + node = parseFunction.apply(null, arguments); + marker.end(); + + if (range && typeof node.range === 'undefined') { + marker.apply(node); + } + + if (loc && typeof node.loc === 'undefined') { + marker.apply(node); + } + + if (isBinary(node)) { + visit(node); + } + + return node; + }; + }; + } + + function patch() { + + var wrapTracking; + + if (extra.comments) { + extra.skipComment = skipComment; + skipComment = scanComment; + } + + if (extra.raw) { + extra.createLiteral = createLiteral; + createLiteral = createRawLiteral; + } + + if (extra.range || extra.loc) { + + extra.parseGroupExpression = parseGroupExpression; + extra.parseLeftHandSideExpression = parseLeftHandSideExpression; + extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall; + parseGroupExpression = trackGroupExpression; + parseLeftHandSideExpression = trackLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall; + + wrapTracking = wrapTrackingFunction(extra.range, extra.loc); + + extra.parseAdditiveExpression = parseAdditiveExpression; + extra.parseAssignmentExpression = parseAssignmentExpression; + extra.parseBitwiseANDExpression = parseBitwiseANDExpression; + extra.parseBitwiseORExpression = parseBitwiseORExpression; + extra.parseBitwiseXORExpression = parseBitwiseXORExpression; + extra.parseBlock = parseBlock; + extra.parseFunctionSourceElements = parseFunctionSourceElements; + extra.parseCatchClause = parseCatchClause; + extra.parseComputedMember = parseComputedMember; + extra.parseConditionalExpression = parseConditionalExpression; + extra.parseConstLetDeclaration = parseConstLetDeclaration; + extra.parseEqualityExpression = parseEqualityExpression; + extra.parseExpression = parseExpression; + extra.parseForVariableDeclaration = parseForVariableDeclaration; + extra.parseFunctionDeclaration = parseFunctionDeclaration; + extra.parseFunctionExpression = parseFunctionExpression; + extra.parseLogicalANDExpression = parseLogicalANDExpression; + extra.parseLogicalORExpression = parseLogicalORExpression; + extra.parseMultiplicativeExpression = parseMultiplicativeExpression; + extra.parseNewExpression = parseNewExpression; + extra.parseNonComputedProperty = parseNonComputedProperty; + extra.parseObjectProperty = parseObjectProperty; + extra.parseObjectPropertyKey = parseObjectPropertyKey; + extra.parsePostfixExpression = parsePostfixExpression; + extra.parsePrimaryExpression = parsePrimaryExpression; + extra.parseProgram = parseProgram; + extra.parsePropertyFunction = parsePropertyFunction; + extra.parseRelationalExpression = parseRelationalExpression; + extra.parseStatement = parseStatement; + extra.parseShiftExpression = parseShiftExpression; + extra.parseSwitchCase = parseSwitchCase; + extra.parseUnaryExpression = parseUnaryExpression; + extra.parseVariableDeclaration = parseVariableDeclaration; + extra.parseVariableIdentifier = parseVariableIdentifier; + + parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression); + parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); + parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression); + parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression); + parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression); + parseBlock = wrapTracking(extra.parseBlock); + parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements); + parseCatchClause = wrapTracking(extra.parseCatchClause); + parseComputedMember = wrapTracking(extra.parseComputedMember); + parseConditionalExpression = wrapTracking(extra.parseConditionalExpression); + parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration); + parseEqualityExpression = wrapTracking(extra.parseEqualityExpression); + parseExpression = wrapTracking(extra.parseExpression); + parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration); + parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration); + parseFunctionExpression = wrapTracking(extra.parseFunctionExpression); + parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression); + parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression); + parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression); + parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression); + parseNewExpression = wrapTracking(extra.parseNewExpression); + parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty); + parseObjectProperty = wrapTracking(extra.parseObjectProperty); + parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey); + parsePostfixExpression = wrapTracking(extra.parsePostfixExpression); + parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression); + parseProgram = wrapTracking(extra.parseProgram); + parsePropertyFunction = wrapTracking(extra.parsePropertyFunction); + parseRelationalExpression = wrapTracking(extra.parseRelationalExpression); + parseStatement = wrapTracking(extra.parseStatement); + parseShiftExpression = wrapTracking(extra.parseShiftExpression); + parseSwitchCase = wrapTracking(extra.parseSwitchCase); + parseUnaryExpression = wrapTracking(extra.parseUnaryExpression); + parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration); + parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier); + } + + if (typeof extra.tokens !== 'undefined') { + extra.advance = advance; + extra.scanRegExp = scanRegExp; + + advance = collectToken; + scanRegExp = collectRegex; + } + } + + function unpatch() { + if (typeof extra.skipComment === 'function') { + skipComment = extra.skipComment; + } + + if (extra.raw) { + createLiteral = extra.createLiteral; + } + + if (extra.range || extra.loc) { + parseAdditiveExpression = extra.parseAdditiveExpression; + parseAssignmentExpression = extra.parseAssignmentExpression; + parseBitwiseANDExpression = extra.parseBitwiseANDExpression; + parseBitwiseORExpression = extra.parseBitwiseORExpression; + parseBitwiseXORExpression = extra.parseBitwiseXORExpression; + parseBlock = extra.parseBlock; + parseFunctionSourceElements = extra.parseFunctionSourceElements; + parseCatchClause = extra.parseCatchClause; + parseComputedMember = extra.parseComputedMember; + parseConditionalExpression = extra.parseConditionalExpression; + parseConstLetDeclaration = extra.parseConstLetDeclaration; + parseEqualityExpression = extra.parseEqualityExpression; + parseExpression = extra.parseExpression; + parseForVariableDeclaration = extra.parseForVariableDeclaration; + parseFunctionDeclaration = extra.parseFunctionDeclaration; + parseFunctionExpression = extra.parseFunctionExpression; + parseGroupExpression = extra.parseGroupExpression; + parseLeftHandSideExpression = extra.parseLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall; + parseLogicalANDExpression = extra.parseLogicalANDExpression; + parseLogicalORExpression = extra.parseLogicalORExpression; + parseMultiplicativeExpression = extra.parseMultiplicativeExpression; + parseNewExpression = extra.parseNewExpression; + parseNonComputedProperty = extra.parseNonComputedProperty; + parseObjectProperty = extra.parseObjectProperty; + parseObjectPropertyKey = extra.parseObjectPropertyKey; + parsePrimaryExpression = extra.parsePrimaryExpression; + parsePostfixExpression = extra.parsePostfixExpression; + parseProgram = extra.parseProgram; + parsePropertyFunction = extra.parsePropertyFunction; + parseRelationalExpression = extra.parseRelationalExpression; + parseStatement = extra.parseStatement; + parseShiftExpression = extra.parseShiftExpression; + parseSwitchCase = extra.parseSwitchCase; + parseUnaryExpression = extra.parseUnaryExpression; + parseVariableDeclaration = extra.parseVariableDeclaration; + parseVariableIdentifier = extra.parseVariableIdentifier; + } + + if (typeof extra.scanRegExp === 'function') { + advance = extra.advance; + scanRegExp = extra.scanRegExp; + } + } + + function stringToArray(str) { + var length = str.length, + result = [], + i; + for (i = 0; i < length; ++i) { + result[i] = str.charAt(i); + } + return result; + } + + function parse(code, options) { + var program, toString; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + buffer = null; + state = { + allowIn: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false + }; + + extra = {}; + if (typeof options !== 'undefined') { + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + extra.raw = (typeof options.raw === 'boolean') && options.raw; + if (typeof options.tokens === 'boolean' && options.tokens) { + extra.tokens = []; + } + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + } + + if (length > 0) { + if (typeof source[0] === 'undefined') { + // Try first to convert to a string. This is good as fast path + // for old IE which understands string indexing for string + // literals only and not for string object. + if (code instanceof String) { + source = code.valueOf(); + } + + // Force accessing the characters via an array. + if (typeof source[0] === 'undefined') { + source = stringToArray(code); + } + } + } + + patch(); + try { + program = parseProgram(); + if (typeof extra.comments !== 'undefined') { + filterCommentLocation(); + program.comments = extra.comments; + } + if (typeof extra.tokens !== 'undefined') { + filterTokenLocation(); + program.tokens = extra.tokens; + } + if (typeof extra.errors !== 'undefined') { + program.errors = extra.errors; + } + if (extra.range || extra.loc) { + program.body = filterGroup(program.body); + } + } catch (e) { + throw e; + } finally { + unpatch(); + extra = {}; + } + + return program; + } + + // Sync with package.json. + exports.version = '1.0.4'; + + exports.parse = parse; + + // Deep copy. + exports.Syntax = (function () { + var name, types = {}; + + if (typeof Object.create === 'function') { + types = Object.create(null); + } + + for (name in Syntax) { + if (Syntax.hasOwnProperty(name)) { + types[name] = Syntax[name]; + } + } + + if (typeof Object.freeze === 'function') { + Object.freeze(types); + } + + return types; + }()); + +})); +/* vim: set sw=4 ts=4 et tw=80 : */ +/** + * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*global define, Reflect */ + +/* + * xpcshell has a smaller stack on linux and windows (1MB vs 9MB on mac), + * and the recursive nature of esprima can cause it to overflow pretty + * quickly. So favor it built in Reflect parser: + * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API + */ +define('esprimaAdapter', ['./esprima', 'env'], function (esprima, env) { + if (env.get() === 'xpconnect' && typeof Reflect !== 'undefined') { + return Reflect; + } else { + return esprima; + } +}); +define('uglifyjs/consolidator', ["require", "exports", "module", "./parse-js", "./process"], function(require, exports, module) { +/** + * @preserve Copyright 2012 Robert Gust-Bardon . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * @fileoverview Enhances UglifyJS with consolidation of null, Boolean, and String values. + *

    Also known as aliasing, this feature has been deprecated in the Closure Compiler since its + * initial release, where it is unavailable from the CLI. The Closure Compiler allows one to log and + * influence this process. In contrast, this implementation does not introduce + * any variable declarations in global code and derives String values from + * identifier names used as property accessors.

    + *

    Consolidating literals may worsen the data compression ratio when an encoding + * transformation is applied. For instance, jQuery 1.7.1 takes 248235 bytes. + * Building it with + * UglifyJS v1.2.5 results in 93647 bytes (37.73% of the original) which are + * then compressed to 33154 bytes (13.36% of the original) using gzip(1). Building it with the same + * version of UglifyJS 1.2.5 patched with the implementation of consolidation + * results in 80784 bytes (a decrease of 12863 bytes, i.e. 13.74%, in comparison + * to the aforementioned 93647 bytes) which are then compressed to 34013 bytes + * (an increase of 859 bytes, i.e. 2.59%, in comparison to the aforementioned + * 33154 bytes).

    + *

    Written in the strict variant + * of ECMA-262 5.1 Edition. Encoded in UTF-8. Follows Revision 2.28 of the Google JavaScript Style Guide (except for the + * discouraged use of the {@code function} tag and the {@code namespace} tag). + * 100% typed for the Closure Compiler Version 1741.

    + *

    Should you find this software useful, please consider a donation.

    + * @author follow.me@RGustBardon (Robert Gust-Bardon) + * @supported Tested with: + * + */ + +/*global console:false, exports:true, module:false, require:false */ +/*jshint sub:true */ +/** + * Consolidates null, Boolean, and String values found inside an AST. + * @param {!TSyntacticCodeUnit} oAbstractSyntaxTree An array-like object + * representing an AST. + * @return {!TSyntacticCodeUnit} An array-like object representing an AST with its null, Boolean, and + * String values consolidated. + */ +// TODO(user) Consolidation of mathematical values found in numeric literals. +// TODO(user) Unconsolidation. +// TODO(user) Consolidation of ECMA-262 6th Edition programs. +// TODO(user) Rewrite in ECMA-262 6th Edition. +exports['ast_consolidate'] = function(oAbstractSyntaxTree) { + 'use strict'; + /*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true, + latedef:true, newcap:true, noarge:true, noempty:true, nonew:true, + onevar:true, plusplus:true, regexp:true, undef:true, strict:true, + sub:false, trailing:true */ + + var _, + /** + * A record consisting of data about one or more source elements. + * @constructor + * @nosideeffects + */ + TSourceElementsData = function() { + /** + * The category of the elements. + * @type {number} + * @see ESourceElementCategories + */ + this.nCategory = ESourceElementCategories.N_OTHER; + /** + * The number of occurrences (within the elements) of each primitive + * value that could be consolidated. + * @type {!Array.>} + */ + this.aCount = []; + this.aCount[EPrimaryExpressionCategories.N_IDENTIFIER_NAMES] = {}; + this.aCount[EPrimaryExpressionCategories.N_STRING_LITERALS] = {}; + this.aCount[EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS] = + {}; + /** + * Identifier names found within the elements. + * @type {!Array.} + */ + this.aIdentifiers = []; + /** + * Prefixed representation Strings of each primitive value that could be + * consolidated within the elements. + * @type {!Array.} + */ + this.aPrimitiveValues = []; + }, + /** + * A record consisting of data about a primitive value that could be + * consolidated. + * @constructor + * @nosideeffects + */ + TPrimitiveValue = function() { + /** + * The difference in the number of terminal symbols between the original + * source text and the one with the primitive value consolidated. If the + * difference is positive, the primitive value is considered worthwhile. + * @type {number} + */ + this.nSaving = 0; + /** + * An identifier name of the variable that will be declared and assigned + * the primitive value if the primitive value is consolidated. + * @type {string} + */ + this.sName = ''; + }, + /** + * A record consisting of data on what to consolidate within the range of + * source elements that is currently being considered. + * @constructor + * @nosideeffects + */ + TSolution = function() { + /** + * An object whose keys are prefixed representation Strings of each + * primitive value that could be consolidated within the elements and + * whose values are corresponding data about those primitive values. + * @type {!Object.} + * @see TPrimitiveValue + */ + this.oPrimitiveValues = {}; + /** + * The difference in the number of terminal symbols between the original + * source text and the one with all the worthwhile primitive values + * consolidated. + * @type {number} + * @see TPrimitiveValue#nSaving + */ + this.nSavings = 0; + }, + /** + * The processor of ASTs found + * in UglifyJS. + * @namespace + * @type {!TProcessor} + */ + oProcessor = (/** @type {!TProcessor} */ require('./process')), + /** + * A record consisting of a number of constants that represent the + * difference in the number of terminal symbols between a source text with + * a modified syntactic code unit and the original one. + * @namespace + * @type {!Object.} + */ + oWeights = { + /** + * The difference in the number of punctuators required by the bracket + * notation and the dot notation. + *

    '[]'.length - '.'.length

    + * @const + * @type {number} + */ + N_PROPERTY_ACCESSOR: 1, + /** + * The number of punctuators required by a variable declaration with an + * initialiser. + *

    ':'.length + ';'.length

    + * @const + * @type {number} + */ + N_VARIABLE_DECLARATION: 2, + /** + * The number of terminal symbols required to introduce a variable + * statement (excluding its variable declaration list). + *

    'var '.length

    + * @const + * @type {number} + */ + N_VARIABLE_STATEMENT_AFFIXATION: 4, + /** + * The number of terminal symbols needed to enclose source elements + * within a function call with no argument values to a function with an + * empty parameter list. + *

    '(function(){}());'.length

    + * @const + * @type {number} + */ + N_CLOSURE: 17 + }, + /** + * Categories of primary expressions from which primitive values that + * could be consolidated are derivable. + * @namespace + * @enum {number} + */ + EPrimaryExpressionCategories = { + /** + * Identifier names used as property accessors. + * @type {number} + */ + N_IDENTIFIER_NAMES: 0, + /** + * String literals. + * @type {number} + */ + N_STRING_LITERALS: 1, + /** + * Null and Boolean literals. + * @type {number} + */ + N_NULL_AND_BOOLEAN_LITERALS: 2 + }, + /** + * Prefixes of primitive values that could be consolidated. + * The String values of the prefixes must have same number of characters. + * The prefixes must not be used in any properties defined in any version + * of ECMA-262. + * @namespace + * @enum {string} + */ + EValuePrefixes = { + /** + * Identifies String values. + * @type {string} + */ + S_STRING: '#S', + /** + * Identifies null and Boolean values. + * @type {string} + */ + S_SYMBOLIC: '#O' + }, + /** + * Categories of source elements in terms of their appropriateness of + * having their primitive values consolidated. + * @namespace + * @enum {number} + */ + ESourceElementCategories = { + /** + * Identifies a source element that includes the {@code with} statement. + * @type {number} + */ + N_WITH: 0, + /** + * Identifies a source element that includes the {@code eval} identifier name. + * @type {number} + */ + N_EVAL: 1, + /** + * Identifies a source element that must be excluded from the process + * unless its whole scope is examined. + * @type {number} + */ + N_EXCLUDABLE: 2, + /** + * Identifies source elements not posing any problems. + * @type {number} + */ + N_OTHER: 3 + }, + /** + * The list of literals (other than the String ones) whose primitive + * values can be consolidated. + * @const + * @type {!Array.} + */ + A_OTHER_SUBSTITUTABLE_LITERALS = [ + 'null', // The null literal. + 'false', // The Boolean literal {@code false}. + 'true' // The Boolean literal {@code true}. + ]; + + (/** + * Consolidates all worthwhile primitive values in a syntactic code unit. + * @param {!TSyntacticCodeUnit} oSyntacticCodeUnit An array-like object + * representing the branch of the abstract syntax tree representing the + * syntactic code unit along with its scope. + * @see TPrimitiveValue#nSaving + */ + function fExamineSyntacticCodeUnit(oSyntacticCodeUnit) { + var _, + /** + * Indicates whether the syntactic code unit represents global code. + * @type {boolean} + */ + bIsGlobal = 'toplevel' === oSyntacticCodeUnit[0], + /** + * Indicates whether the whole scope is being examined. + * @type {boolean} + */ + bIsWhollyExaminable = !bIsGlobal, + /** + * An array-like object representing source elements that constitute a + * syntactic code unit. + * @type {!TSyntacticCodeUnit} + */ + oSourceElements, + /** + * A record consisting of data about the source element that is + * currently being examined. + * @type {!TSourceElementsData} + */ + oSourceElementData, + /** + * The scope of the syntactic code unit. + * @type {!TScope} + */ + oScope, + /** + * An instance of an object that allows the traversal of an AST. + * @type {!TWalker} + */ + oWalker, + /** + * An object encompassing collections of functions used during the + * traversal of an AST. + * @namespace + * @type {!Object.>} + */ + oWalkers = { + /** + * A collection of functions used during the surveyance of source + * elements. + * @namespace + * @type {!Object.} + */ + oSurveySourceElement: { + /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys. + /** + * Classifies the source element as excludable if it does not + * contain a {@code with} statement or the {@code eval} identifier + * name. Adds the identifier of the function and its formal + * parameters to the list of identifier names found. + * @param {string} sIdentifier The identifier of the function. + * @param {!Array.} aFormalParameterList Formal parameters. + * @param {!TSyntacticCodeUnit} oFunctionBody Function code. + */ + 'defun': function( + sIdentifier, + aFormalParameterList, + oFunctionBody) { + fClassifyAsExcludable(); + fAddIdentifier(sIdentifier); + aFormalParameterList.forEach(fAddIdentifier); + }, + /** + * Increments the count of the number of occurrences of the String + * value that is equivalent to the sequence of terminal symbols + * that constitute the encountered identifier name. + * @param {!TSyntacticCodeUnit} oExpression The nonterminal + * MemberExpression. + * @param {string} sIdentifierName The identifier name used as the + * property accessor. + * @return {!Array} The encountered branch of an AST with its nonterminal + * MemberExpression traversed. + */ + 'dot': function(oExpression, sIdentifierName) { + fCountPrimaryExpression( + EPrimaryExpressionCategories.N_IDENTIFIER_NAMES, + EValuePrefixes.S_STRING + sIdentifierName); + return ['dot', oWalker.walk(oExpression), sIdentifierName]; + }, + /** + * Adds the optional identifier of the function and its formal + * parameters to the list of identifier names found. + * @param {?string} sIdentifier The optional identifier of the + * function. + * @param {!Array.} aFormalParameterList Formal parameters. + * @param {!TSyntacticCodeUnit} oFunctionBody Function code. + */ + 'function': function( + sIdentifier, + aFormalParameterList, + oFunctionBody) { + if ('string' === typeof sIdentifier) { + fAddIdentifier(sIdentifier); + } + aFormalParameterList.forEach(fAddIdentifier); + }, + /** + * Either increments the count of the number of occurrences of the + * encountered null or Boolean value or classifies a source element + * as containing the {@code eval} identifier name. + * @param {string} sIdentifier The identifier encountered. + */ + 'name': function(sIdentifier) { + if (-1 !== A_OTHER_SUBSTITUTABLE_LITERALS.indexOf(sIdentifier)) { + fCountPrimaryExpression( + EPrimaryExpressionCategories.N_NULL_AND_BOOLEAN_LITERALS, + EValuePrefixes.S_SYMBOLIC + sIdentifier); + } else { + if ('eval' === sIdentifier) { + oSourceElementData.nCategory = + ESourceElementCategories.N_EVAL; + } + fAddIdentifier(sIdentifier); + } + }, + /** + * Classifies the source element as excludable if it does not + * contain a {@code with} statement or the {@code eval} identifier + * name. + * @param {TSyntacticCodeUnit} oExpression The expression whose + * value is to be returned. + */ + 'return': function(oExpression) { + fClassifyAsExcludable(); + }, + /** + * Increments the count of the number of occurrences of the + * encountered String value. + * @param {string} sStringValue The String value of the string + * literal encountered. + */ + 'string': function(sStringValue) { + if (sStringValue.length > 0) { + fCountPrimaryExpression( + EPrimaryExpressionCategories.N_STRING_LITERALS, + EValuePrefixes.S_STRING + sStringValue); + } + }, + /** + * Adds the identifier reserved for an exception to the list of + * identifier names found. + * @param {!TSyntacticCodeUnit} oTry A block of code in which an + * exception can occur. + * @param {Array} aCatch The identifier reserved for an exception + * and a block of code to handle the exception. + * @param {TSyntacticCodeUnit} oFinally An optional block of code + * to be evaluated regardless of whether an exception occurs. + */ + 'try': function(oTry, aCatch, oFinally) { + if (Array.isArray(aCatch)) { + fAddIdentifier(aCatch[0]); + } + }, + /** + * Classifies the source element as excludable if it does not + * contain a {@code with} statement or the {@code eval} identifier + * name. Adds the identifier of each declared variable to the list + * of identifier names found. + * @param {!Array.} aVariableDeclarationList Variable + * declarations. + */ + 'var': function(aVariableDeclarationList) { + fClassifyAsExcludable(); + aVariableDeclarationList.forEach(fAddVariable); + }, + /** + * Classifies a source element as containing the {@code with} + * statement. + * @param {!TSyntacticCodeUnit} oExpression An expression whose + * value is to be converted to a value of type Object and + * become the binding object of a new object environment + * record of a new lexical environment in which the statement + * is to be executed. + * @param {!TSyntacticCodeUnit} oStatement The statement to be + * executed in the augmented lexical environment. + * @return {!Array} An empty array to stop the traversal. + */ + 'with': function(oExpression, oStatement) { + oSourceElementData.nCategory = ESourceElementCategories.N_WITH; + return []; + } + /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys. + }, + /** + * A collection of functions used while looking for nested functions. + * @namespace + * @type {!Object.} + */ + oExamineFunctions: { + /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys. + /** + * Orders an examination of a nested function declaration. + * @this {!TSyntacticCodeUnit} An array-like object representing + * the branch of an AST representing the syntactic code unit along with + * its scope. + * @return {!Array} An empty array to stop the traversal. + */ + 'defun': function() { + fExamineSyntacticCodeUnit(this); + return []; + }, + /** + * Orders an examination of a nested function expression. + * @this {!TSyntacticCodeUnit} An array-like object representing + * the branch of an AST representing the syntactic code unit along with + * its scope. + * @return {!Array} An empty array to stop the traversal. + */ + 'function': function() { + fExamineSyntacticCodeUnit(this); + return []; + } + /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys. + } + }, + /** + * Records containing data about source elements. + * @type {Array.} + */ + aSourceElementsData = [], + /** + * The index (in the source text order) of the source element + * immediately following a Directive Prologue. + * @type {number} + */ + nAfterDirectivePrologue = 0, + /** + * The index (in the source text order) of the source element that is + * currently being considered. + * @type {number} + */ + nPosition, + /** + * The index (in the source text order) of the source element that is + * the last element of the range of source elements that is currently + * being considered. + * @type {(undefined|number)} + */ + nTo, + /** + * Initiates the traversal of a source element. + * @param {!TWalker} oWalker An instance of an object that allows the + * traversal of an abstract syntax tree. + * @param {!TSyntacticCodeUnit} oSourceElement A source element from + * which the traversal should commence. + * @return {function(): !TSyntacticCodeUnit} A function that is able to + * initiate the traversal from a given source element. + */ + cContext = function(oWalker, oSourceElement) { + /** + * @return {!TSyntacticCodeUnit} A function that is able to + * initiate the traversal from a given source element. + */ + var fLambda = function() { + return oWalker.walk(oSourceElement); + }; + + return fLambda; + }, + /** + * Classifies the source element as excludable if it does not + * contain a {@code with} statement or the {@code eval} identifier + * name. + */ + fClassifyAsExcludable = function() { + if (oSourceElementData.nCategory === + ESourceElementCategories.N_OTHER) { + oSourceElementData.nCategory = + ESourceElementCategories.N_EXCLUDABLE; + } + }, + /** + * Adds an identifier to the list of identifier names found. + * @param {string} sIdentifier The identifier to be added. + */ + fAddIdentifier = function(sIdentifier) { + if (-1 === oSourceElementData.aIdentifiers.indexOf(sIdentifier)) { + oSourceElementData.aIdentifiers.push(sIdentifier); + } + }, + /** + * Adds the identifier of a variable to the list of identifier names + * found. + * @param {!Array} aVariableDeclaration A variable declaration. + */ + fAddVariable = function(aVariableDeclaration) { + fAddIdentifier(/** @type {string} */ aVariableDeclaration[0]); + }, + /** + * Increments the count of the number of occurrences of the prefixed + * String representation attributed to the primary expression. + * @param {number} nCategory The category of the primary expression. + * @param {string} sName The prefixed String representation attributed + * to the primary expression. + */ + fCountPrimaryExpression = function(nCategory, sName) { + if (!oSourceElementData.aCount[nCategory].hasOwnProperty(sName)) { + oSourceElementData.aCount[nCategory][sName] = 0; + if (-1 === oSourceElementData.aPrimitiveValues.indexOf(sName)) { + oSourceElementData.aPrimitiveValues.push(sName); + } + } + oSourceElementData.aCount[nCategory][sName] += 1; + }, + /** + * Consolidates all worthwhile primitive values in a range of source + * elements. + * @param {number} nFrom The index (in the source text order) of the + * source element that is the first element of the range. + * @param {number} nTo The index (in the source text order) of the + * source element that is the last element of the range. + * @param {boolean} bEnclose Indicates whether the range should be + * enclosed within a function call with no argument values to a + * function with an empty parameter list if any primitive values + * are consolidated. + * @see TPrimitiveValue#nSaving + */ + fExamineSourceElements = function(nFrom, nTo, bEnclose) { + var _, + /** + * The index of the last mangled name. + * @type {number} + */ + nIndex = oScope.cname, + /** + * The index of the source element that is currently being + * considered. + * @type {number} + */ + nPosition, + /** + * A collection of functions used during the consolidation of + * primitive values and identifier names used as property + * accessors. + * @namespace + * @type {!Object.} + */ + oWalkersTransformers = { + /** + * If the String value that is equivalent to the sequence of + * terminal symbols that constitute the encountered identifier + * name is worthwhile, a syntactic conversion from the dot + * notation to the bracket notation ensues with that sequence + * being substituted by an identifier name to which the value + * is assigned. + * Applies to property accessors that use the dot notation. + * @param {!TSyntacticCodeUnit} oExpression The nonterminal + * MemberExpression. + * @param {string} sIdentifierName The identifier name used as + * the property accessor. + * @return {!Array} A syntactic code unit that is equivalent to + * the one encountered. + * @see TPrimitiveValue#nSaving + */ + 'dot': function(oExpression, sIdentifierName) { + /** + * The prefixed String value that is equivalent to the + * sequence of terminal symbols that constitute the + * encountered identifier name. + * @type {string} + */ + var sPrefixed = EValuePrefixes.S_STRING + sIdentifierName; + + return oSolutionBest.oPrimitiveValues.hasOwnProperty( + sPrefixed) && + oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? + ['sub', + oWalker.walk(oExpression), + ['name', + oSolutionBest.oPrimitiveValues[sPrefixed].sName]] : + ['dot', oWalker.walk(oExpression), sIdentifierName]; + }, + /** + * If the encountered identifier is a null or Boolean literal + * and its value is worthwhile, the identifier is substituted + * by an identifier name to which that value is assigned. + * Applies to identifier names. + * @param {string} sIdentifier The identifier encountered. + * @return {!Array} A syntactic code unit that is equivalent to + * the one encountered. + * @see TPrimitiveValue#nSaving + */ + 'name': function(sIdentifier) { + /** + * The prefixed representation String of the identifier. + * @type {string} + */ + var sPrefixed = EValuePrefixes.S_SYMBOLIC + sIdentifier; + + return [ + 'name', + oSolutionBest.oPrimitiveValues.hasOwnProperty(sPrefixed) && + oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? + oSolutionBest.oPrimitiveValues[sPrefixed].sName : + sIdentifier + ]; + }, + /** + * If the encountered String value is worthwhile, it is + * substituted by an identifier name to which that value is + * assigned. + * Applies to String values. + * @param {string} sStringValue The String value of the string + * literal encountered. + * @return {!Array} A syntactic code unit that is equivalent to + * the one encountered. + * @see TPrimitiveValue#nSaving + */ + 'string': function(sStringValue) { + /** + * The prefixed representation String of the primitive value + * of the literal. + * @type {string} + */ + var sPrefixed = + EValuePrefixes.S_STRING + sStringValue; + + return oSolutionBest.oPrimitiveValues.hasOwnProperty( + sPrefixed) && + oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0 ? + ['name', + oSolutionBest.oPrimitiveValues[sPrefixed].sName] : + ['string', sStringValue]; + } + }, + /** + * Such data on what to consolidate within the range of source + * elements that is currently being considered that lead to the + * greatest known reduction of the number of the terminal symbols + * in comparison to the original source text. + * @type {!TSolution} + */ + oSolutionBest = new TSolution(), + /** + * Data representing an ongoing attempt to find a better + * reduction of the number of the terminal symbols in comparison + * to the original source text than the best one that is + * currently known. + * @type {!TSolution} + * @see oSolutionBest + */ + oSolutionCandidate = new TSolution(), + /** + * A record consisting of data about the range of source elements + * that is currently being examined. + * @type {!TSourceElementsData} + */ + oSourceElementsData = new TSourceElementsData(), + /** + * Variable declarations for each primitive value that is to be + * consolidated within the elements. + * @type {!Array.} + */ + aVariableDeclarations = [], + /** + * Augments a list with a prefixed representation String. + * @param {!Array.} aList A list that is to be augmented. + * @return {function(string)} A function that augments a list + * with a prefixed representation String. + */ + cAugmentList = function(aList) { + /** + * @param {string} sPrefixed Prefixed representation String of + * a primitive value that could be consolidated within the + * elements. + */ + var fLambda = function(sPrefixed) { + if (-1 === aList.indexOf(sPrefixed)) { + aList.push(sPrefixed); + } + }; + + return fLambda; + }, + /** + * Adds the number of occurrences of a primitive value of a given + * category that could be consolidated in the source element with + * a given index to the count of occurrences of that primitive + * value within the range of source elements that is currently + * being considered. + * @param {number} nPosition The index (in the source text order) + * of a source element. + * @param {number} nCategory The category of the primary + * expression from which the primitive value is derived. + * @return {function(string)} A function that performs the + * addition. + * @see cAddOccurrencesInCategory + */ + cAddOccurrences = function(nPosition, nCategory) { + /** + * @param {string} sPrefixed The prefixed representation String + * of a primitive value. + */ + var fLambda = function(sPrefixed) { + if (!oSourceElementsData.aCount[nCategory].hasOwnProperty( + sPrefixed)) { + oSourceElementsData.aCount[nCategory][sPrefixed] = 0; + } + oSourceElementsData.aCount[nCategory][sPrefixed] += + aSourceElementsData[nPosition].aCount[nCategory][ + sPrefixed]; + }; + + return fLambda; + }, + /** + * Adds the number of occurrences of each primitive value of a + * given category that could be consolidated in the source + * element with a given index to the count of occurrences of that + * primitive values within the range of source elements that is + * currently being considered. + * @param {number} nPosition The index (in the source text order) + * of a source element. + * @return {function(number)} A function that performs the + * addition. + * @see fAddOccurrences + */ + cAddOccurrencesInCategory = function(nPosition) { + /** + * @param {number} nCategory The category of the primary + * expression from which the primitive value is derived. + */ + var fLambda = function(nCategory) { + Object.keys( + aSourceElementsData[nPosition].aCount[nCategory] + ).forEach(cAddOccurrences(nPosition, nCategory)); + }; + + return fLambda; + }, + /** + * Adds the number of occurrences of each primitive value that + * could be consolidated in the source element with a given index + * to the count of occurrences of that primitive values within + * the range of source elements that is currently being + * considered. + * @param {number} nPosition The index (in the source text order) + * of a source element. + */ + fAddOccurrences = function(nPosition) { + Object.keys(aSourceElementsData[nPosition].aCount).forEach( + cAddOccurrencesInCategory(nPosition)); + }, + /** + * Creates a variable declaration for a primitive value if that + * primitive value is to be consolidated within the elements. + * @param {string} sPrefixed Prefixed representation String of a + * primitive value that could be consolidated within the + * elements. + * @see aVariableDeclarations + */ + cAugmentVariableDeclarations = function(sPrefixed) { + if (oSolutionBest.oPrimitiveValues[sPrefixed].nSaving > 0) { + aVariableDeclarations.push([ + oSolutionBest.oPrimitiveValues[sPrefixed].sName, + [0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC) ? + 'name' : 'string', + sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length)] + ]); + } + }, + /** + * Sorts primitive values with regard to the difference in the + * number of terminal symbols between the original source text + * and the one with those primitive values consolidated. + * @param {string} sPrefixed0 The prefixed representation String + * of the first of the two primitive values that are being + * compared. + * @param {string} sPrefixed1 The prefixed representation String + * of the second of the two primitive values that are being + * compared. + * @return {number} + *
    + *
    -1
    + *
    if the first primitive value must be placed before + * the other one,
    + *
    0
    + *
    if the first primitive value may be placed before + * the other one,
    + *
    1
    + *
    if the first primitive value must not be placed + * before the other one.
    + *
    + * @see TSolution.oPrimitiveValues + */ + cSortPrimitiveValues = function(sPrefixed0, sPrefixed1) { + /** + * The difference between: + *
      + *
    1. the difference in the number of terminal symbols + * between the original source text and the one with the + * first primitive value consolidated, and
    2. + *
    3. the difference in the number of terminal symbols + * between the original source text and the one with the + * second primitive value consolidated.
    4. + *
    + * @type {number} + */ + var nDifference = + oSolutionCandidate.oPrimitiveValues[sPrefixed0].nSaving - + oSolutionCandidate.oPrimitiveValues[sPrefixed1].nSaving; + + return nDifference > 0 ? -1 : nDifference < 0 ? 1 : 0; + }, + /** + * Assigns an identifier name to a primitive value and calculates + * whether instances of that primitive value are worth + * consolidating. + * @param {string} sPrefixed The prefixed representation String + * of a primitive value that is being evaluated. + */ + fEvaluatePrimitiveValue = function(sPrefixed) { + var _, + /** + * The index of the last mangled name. + * @type {number} + */ + nIndex, + /** + * The representation String of the primitive value that is + * being evaluated. + * @type {string} + */ + sName = + sPrefixed.substring(EValuePrefixes.S_SYMBOLIC.length), + /** + * The number of source characters taken up by the + * representation String of the primitive value that is + * being evaluated. + * @type {number} + */ + nLengthOriginal = sName.length, + /** + * The number of source characters taken up by the + * identifier name that could substitute the primitive + * value that is being evaluated. + * substituted. + * @type {number} + */ + nLengthSubstitution, + /** + * The number of source characters taken up by by the + * representation String of the primitive value that is + * being evaluated when it is represented by a string + * literal. + * @type {number} + */ + nLengthString = oProcessor.make_string(sName).length; + + oSolutionCandidate.oPrimitiveValues[sPrefixed] = + new TPrimitiveValue(); + do { // Find an identifier unused in this or any nested scope. + nIndex = oScope.cname; + oSolutionCandidate.oPrimitiveValues[sPrefixed].sName = + oScope.next_mangled(); + } while (-1 !== oSourceElementsData.aIdentifiers.indexOf( + oSolutionCandidate.oPrimitiveValues[sPrefixed].sName)); + nLengthSubstitution = oSolutionCandidate.oPrimitiveValues[ + sPrefixed].sName.length; + if (0 === sPrefixed.indexOf(EValuePrefixes.S_SYMBOLIC)) { + // foo:null, or foo:null; + oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -= + nLengthSubstitution + nLengthOriginal + + oWeights.N_VARIABLE_DECLARATION; + // null vs foo + oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += + oSourceElementsData.aCount[ + EPrimaryExpressionCategories. + N_NULL_AND_BOOLEAN_LITERALS][sPrefixed] * + (nLengthOriginal - nLengthSubstitution); + } else { + // foo:'fromCharCode'; + oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving -= + nLengthSubstitution + nLengthString + + oWeights.N_VARIABLE_DECLARATION; + // .fromCharCode vs [foo] + if (oSourceElementsData.aCount[ + EPrimaryExpressionCategories.N_IDENTIFIER_NAMES + ].hasOwnProperty(sPrefixed)) { + oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += + oSourceElementsData.aCount[ + EPrimaryExpressionCategories.N_IDENTIFIER_NAMES + ][sPrefixed] * + (nLengthOriginal - nLengthSubstitution - + oWeights.N_PROPERTY_ACCESSOR); + } + // 'fromCharCode' vs foo + if (oSourceElementsData.aCount[ + EPrimaryExpressionCategories.N_STRING_LITERALS + ].hasOwnProperty(sPrefixed)) { + oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving += + oSourceElementsData.aCount[ + EPrimaryExpressionCategories.N_STRING_LITERALS + ][sPrefixed] * + (nLengthString - nLengthSubstitution); + } + } + if (oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving > + 0) { + oSolutionCandidate.nSavings += + oSolutionCandidate.oPrimitiveValues[sPrefixed].nSaving; + } else { + oScope.cname = nIndex; // Free the identifier name. + } + }, + /** + * Adds a variable declaration to an existing variable statement. + * @param {!Array} aVariableDeclaration A variable declaration + * with an initialiser. + */ + cAddVariableDeclaration = function(aVariableDeclaration) { + (/** @type {!Array} */ oSourceElements[nFrom][1]).unshift( + aVariableDeclaration); + }; + + if (nFrom > nTo) { + return; + } + // If the range is a closure, reuse the closure. + if (nFrom === nTo && + 'stat' === oSourceElements[nFrom][0] && + 'call' === oSourceElements[nFrom][1][0] && + 'function' === oSourceElements[nFrom][1][1][0]) { + fExamineSyntacticCodeUnit(oSourceElements[nFrom][1][1]); + return; + } + // Create a list of all derived primitive values within the range. + for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { + aSourceElementsData[nPosition].aPrimitiveValues.forEach( + cAugmentList(oSourceElementsData.aPrimitiveValues)); + } + if (0 === oSourceElementsData.aPrimitiveValues.length) { + return; + } + for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { + // Add the number of occurrences to the total count. + fAddOccurrences(nPosition); + // Add identifiers of this or any nested scope to the list. + aSourceElementsData[nPosition].aIdentifiers.forEach( + cAugmentList(oSourceElementsData.aIdentifiers)); + } + // Distribute identifier names among derived primitive values. + do { // If there was any progress, find a better distribution. + oSolutionBest = oSolutionCandidate; + if (Object.keys(oSolutionCandidate.oPrimitiveValues).length > 0) { + // Sort primitive values descending by their worthwhileness. + oSourceElementsData.aPrimitiveValues.sort(cSortPrimitiveValues); + } + oSolutionCandidate = new TSolution(); + oSourceElementsData.aPrimitiveValues.forEach( + fEvaluatePrimitiveValue); + oScope.cname = nIndex; + } while (oSolutionCandidate.nSavings > oSolutionBest.nSavings); + // Take the necessity of adding a variable statement into account. + if ('var' !== oSourceElements[nFrom][0]) { + oSolutionBest.nSavings -= oWeights.N_VARIABLE_STATEMENT_AFFIXATION; + } + if (bEnclose) { + // Take the necessity of forming a closure into account. + oSolutionBest.nSavings -= oWeights.N_CLOSURE; + } + if (oSolutionBest.nSavings > 0) { + // Create variable declarations suitable for UglifyJS. + Object.keys(oSolutionBest.oPrimitiveValues).forEach( + cAugmentVariableDeclarations); + // Rewrite expressions that contain worthwhile primitive values. + for (nPosition = nFrom; nPosition <= nTo; nPosition += 1) { + oWalker = oProcessor.ast_walker(); + oSourceElements[nPosition] = + oWalker.with_walkers( + oWalkersTransformers, + cContext(oWalker, oSourceElements[nPosition])); + } + if ('var' === oSourceElements[nFrom][0]) { // Reuse the statement. + (/** @type {!Array.} */ aVariableDeclarations.reverse( + )).forEach(cAddVariableDeclaration); + } else { // Add a variable statement. + Array.prototype.splice.call( + oSourceElements, + nFrom, + 0, + ['var', aVariableDeclarations]); + nTo += 1; + } + if (bEnclose) { + // Add a closure. + Array.prototype.splice.call( + oSourceElements, + nFrom, + 0, + ['stat', ['call', ['function', null, [], []], []]]); + // Copy source elements into the closure. + for (nPosition = nTo + 1; nPosition > nFrom; nPosition -= 1) { + Array.prototype.unshift.call( + oSourceElements[nFrom][1][1][3], + oSourceElements[nPosition]); + } + // Remove source elements outside the closure. + Array.prototype.splice.call( + oSourceElements, + nFrom + 1, + nTo - nFrom + 1); + } + } + if (bEnclose) { + // Restore the availability of identifier names. + oScope.cname = nIndex; + } + }; + + oSourceElements = (/** @type {!TSyntacticCodeUnit} */ + oSyntacticCodeUnit[bIsGlobal ? 1 : 3]); + if (0 === oSourceElements.length) { + return; + } + oScope = bIsGlobal ? oSyntacticCodeUnit.scope : oSourceElements.scope; + // Skip a Directive Prologue. + while (nAfterDirectivePrologue < oSourceElements.length && + 'directive' === oSourceElements[nAfterDirectivePrologue][0]) { + nAfterDirectivePrologue += 1; + aSourceElementsData.push(null); + } + if (oSourceElements.length === nAfterDirectivePrologue) { + return; + } + for (nPosition = nAfterDirectivePrologue; + nPosition < oSourceElements.length; + nPosition += 1) { + oSourceElementData = new TSourceElementsData(); + oWalker = oProcessor.ast_walker(); + // Classify a source element. + // Find its derived primitive values and count their occurrences. + // Find all identifiers used (including nested scopes). + oWalker.with_walkers( + oWalkers.oSurveySourceElement, + cContext(oWalker, oSourceElements[nPosition])); + // Establish whether the scope is still wholly examinable. + bIsWhollyExaminable = bIsWhollyExaminable && + ESourceElementCategories.N_WITH !== oSourceElementData.nCategory && + ESourceElementCategories.N_EVAL !== oSourceElementData.nCategory; + aSourceElementsData.push(oSourceElementData); + } + if (bIsWhollyExaminable) { // Examine the whole scope. + fExamineSourceElements( + nAfterDirectivePrologue, + oSourceElements.length - 1, + false); + } else { // Examine unexcluded ranges of source elements. + for (nPosition = oSourceElements.length - 1; + nPosition >= nAfterDirectivePrologue; + nPosition -= 1) { + oSourceElementData = (/** @type {!TSourceElementsData} */ + aSourceElementsData[nPosition]); + if (ESourceElementCategories.N_OTHER === + oSourceElementData.nCategory) { + if ('undefined' === typeof nTo) { + nTo = nPosition; // Indicate the end of a range. + } + // Examine the range if it immediately follows a Directive Prologue. + if (nPosition === nAfterDirectivePrologue) { + fExamineSourceElements(nPosition, nTo, true); + } + } else { + if ('undefined' !== typeof nTo) { + // Examine the range that immediately follows this source element. + fExamineSourceElements(nPosition + 1, nTo, true); + nTo = void 0; // Obliterate the range. + } + // Examine nested functions. + oWalker = oProcessor.ast_walker(); + oWalker.with_walkers( + oWalkers.oExamineFunctions, + cContext(oWalker, oSourceElements[nPosition])); + } + } + } + }(oAbstractSyntaxTree = oProcessor.ast_add_scope(oAbstractSyntaxTree))); + return oAbstractSyntaxTree; +}; +/*jshint sub:false */ + +/* Local Variables: */ +/* mode: js */ +/* coding: utf-8 */ +/* indent-tabs-mode: nil */ +/* tab-width: 2 */ +/* End: */ +/* vim: set ft=javascript fenc=utf-8 et ts=2 sts=2 sw=2: */ +/* :mode=javascript:noTabs=true:tabSize=2:indentSize=2:deepIndent=true: */ +}); +define('uglifyjs/parse-js', ["exports"], function(exports) { +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + + This version is suitable for Node.js. With minimal changes (the + exports stuff) it should work on any JS platform. + + This file contains the tokenizer/parser. It is a port to JavaScript + of parse-js [1], a JavaScript parser library written in Common Lisp + by Marijn Haverbeke. Thank you Marijn! + + [1] http://marijn.haverbeke.nl/parse-js/ + + Exported functions: + + - tokenizer(code) -- returns a function. Call the returned + function to fetch the next token. + + - parse(code) -- returns an AST of the given JavaScript code. + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2010 (c) Mihai Bazon + Based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +/* -----[ Tokenizer (constants) ]----- */ + +var KEYWORDS = array_to_hash([ + "break", + "case", + "catch", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "else", + "finally", + "for", + "function", + "if", + "in", + "instanceof", + "new", + "return", + "switch", + "throw", + "try", + "typeof", + "var", + "void", + "while", + "with" +]); + +var RESERVED_WORDS = array_to_hash([ + "abstract", + "boolean", + "byte", + "char", + "class", + "double", + "enum", + "export", + "extends", + "final", + "float", + "goto", + "implements", + "import", + "int", + "interface", + "long", + "native", + "package", + "private", + "protected", + "public", + "short", + "static", + "super", + "synchronized", + "throws", + "transient", + "volatile" +]); + +var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([ + "return", + "new", + "delete", + "throw", + "else", + "case" +]); + +var KEYWORDS_ATOM = array_to_hash([ + "false", + "null", + "true", + "undefined" +]); + +var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +var RE_OCT_NUMBER = /^0[0-7]+$/; +var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + +var OPERATORS = array_to_hash([ + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\uFEFF")); + +var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{(,.;:")); + +var PUNC_CHARS = array_to_hash(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +var UNICODE = { // Unicode 6.1 + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), + combining_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0859-\\u085B\\u08E4-\\u08FE\\u0900-\\u0903\\u093A-\\u093C\\u093E-\\u094F\\u0951-\\u0957\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A01-\\u0A03\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AE2\\u0AE3\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B62\\u0B63\\u0B82\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0C82\\u0C83\\u0CBC\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CE2\\u0CE3\\u0D02\\u0D03\\u0D3E-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0D62\\u0D63\\u0D82\\u0D83\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86\\u0F87\\u0F8D-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102B-\\u103E\\u1056-\\u1059\\u105E-\\u1060\\u1062-\\u1064\\u1067-\\u106D\\u1071-\\u1074\\u1082-\\u108D\\u108F\\u109A-\\u109D\\u135D-\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B4-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u192B\\u1930-\\u193B\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A17-\\u1A1B\\u1A55-\\u1A5E\\u1A60-\\u1A7C\\u1A7F\\u1B00-\\u1B04\\u1B34-\\u1B44\\u1B6B-\\u1B73\\u1B80-\\u1B82\\u1BA1-\\u1BAD\\u1BE6-\\u1BF3\\u1C24-\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE8\\u1CED\\u1CF2-\\u1CF4\\u1DC0-\\u1DE6\\u1DFC-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2D7F\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA674-\\uA67D\\uA69F\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA823-\\uA827\\uA880\\uA881\\uA8B4-\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA953\\uA980-\\uA983\\uA9B3-\\uA9C0\\uAA29-\\uAA36\\uAA43\\uAA4C\\uAA4D\\uAA7B\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uAAEB-\\uAAEF\\uAAF5\\uAAF6\\uABE3-\\uABEA\\uABEC\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]"), + digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]") +}; + +function is_letter(ch) { + return UNICODE.letter.test(ch); +}; + +function is_digit(ch) { + ch = ch.charCodeAt(0); + return ch >= 48 && ch <= 57; +}; + +function is_unicode_digit(ch) { + return UNICODE.digit.test(ch); +} + +function is_alphanumeric_char(ch) { + return is_digit(ch) || is_letter(ch); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier_start(ch) { + return ch == "$" || ch == "_" || is_letter(ch); +}; + +function is_identifier_char(ch) { + return is_identifier_start(ch) + || is_unicode_combining_mark(ch) + || is_unicode_digit(ch) + || is_unicode_connector_punctuation(ch) + || ch == "\u200c" // zero-width non-joiner + || ch == "\u200d" // zero-width joiner (in my ECMA-262 PDF, this is also 200c) + ; +}; + +function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line + 1; + this.col = col + 1; + this.pos = pos + 1; + this.stack = new Error().stack; +}; + +JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; +}; + +function js_error(message, line, col, pos) { + throw new JS_Parse_Error(message, line, col, pos); +}; + +function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); +}; + +var EX_EOF = {}; + +function tokenizer($TEXT) { + + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''), + pos : 0, + tokpos : 0, + line : 0, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof, in_string) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = S.newline_before || !in_string; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function eof() { + return !S.peek(); + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || + (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || + (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + endpos : S.pos, + nlb : S.newline_before + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + // make note of any newlines in the comments that came before + for (var i = 0, len = ret.comments_before.length; i < len; i++) { + ret.nlb = ret.nlb || ret.comments_before[i].nlb; + } + } + S.newline_before = false; + return ret; + }; + + function skip_whitespace() { + while (HOP(WHITESPACE_CHARS, peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch = peek(), i = 0; + while (ch && pred(ch, i++)) { + ret += next(); + ch = peek(); + } + return ret; + }; + + function parse_error(err) { + js_error(err, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + if (ch == "x" || ch == "X") { + if (has_x) return false; + return has_x = true; + } + if (!has_x && (ch == "E" || ch == "e")) { + if (has_e) return false; + return has_e = after_e = true; + } + if (ch == "-") { + if (after_e || (i == 0 && !prefix)) return true; + return false; + } + if (ch == "+") return after_e; + after_e = false; + if (ch == ".") { + if (!has_dot && !has_x && !has_e) + return has_dot = true; + return false; + } + return is_alphanumeric_char(ch); + }); + if (prefix) + num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char(in_string) { + var ch = next(true, in_string); + switch (ch) { + case "n" : return "\n"; + case "r" : return "\r"; + case "t" : return "\t"; + case "b" : return "\b"; + case "v" : return "\u000b"; + case "f" : return "\f"; + case "0" : return "\0"; + case "x" : return String.fromCharCode(hex_bytes(2)); + case "u" : return String.fromCharCode(hex_bytes(4)); + case "\n": return ""; + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + function read_string() { + return with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = read_escaped_char(true); + } + else if (ch == quote) break; + else if (ch == "\n") throw EX_EOF; + ret += ch; + } + return token("string", ret); + }); + }; + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + function read_multiline_comment() { + next(); + return with_eof_error("Unterminated multiline comment", function(){ + var i = find("*/", true), + text = S.text.substring(S.pos, i); + S.pos = i + 2; + S.line += text.split("\n").length - 1; + S.newline_before = S.newline_before || text.indexOf("\n") >= 0; + + // https://github.com/mishoo/UglifyJS/issues/#issue/100 + if (/^@cc_on/i.test(text)) { + warn("WARNING: at line " + S.line); + warn("*** Found \"conditional comment\": " + text); + warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer."); + } + + return token("comment2", text, true); + }); + }; + + function read_name() { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (HOP(KEYWORDS, name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + return name; + }; + + function read_regexp(regexp) { + return with_eof_error("Unterminated regular expression", function(){ + var prev_backslash = false, ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", [ regexp, mods ]); + }); + }; + + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (HOP(OPERATORS, bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp("") : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek()) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return !HOP(KEYWORDS, word) + ? token("name", word) + : HOP(OPERATORS, word) + ? token("operator", word) + : HOP(KEYWORDS_ATOM, word) + ? token("atom", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + try { + return cont(); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + + function next_token(force_regexp) { + if (force_regexp != null) + return read_regexp(force_regexp); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + if (is_digit(ch)) return read_num(); + if (ch == '"' || ch == "'") return read_string(); + if (HOP(PUNC_CHARS, ch)) return token("punc", next()); + if (ch == ".") return handle_dot(); + if (ch == "/") return handle_slash(); + if (HOP(OPERATOR_CHARS, ch)) return read_operator(); + if (ch == "\\" || is_identifier_start(ch)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = array_to_hash([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = array_to_hash([ "--", "++" ]); + +var ASSIGNMENT = (function(a, ret, i){ + while (i < a.length) { + ret[a[i]] = a[i].substr(0, a[i].length - 1); + i++; + } + return ret; +})( + ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], + { "=": true }, + 0 +); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function NodeWithToken(str, start, end) { + this.name = str; + this.start = start; + this.end = end; +}; + +NodeWithToken.prototype.toString = function() { return this.name; }; + +function parse($TEXT, exigent_mode, embed_tokens) { + + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && ( + S.token.type == "string" || is("punc", ";") + ); + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !exigent_mode && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function as() { + return slice(arguments); + }; + + function parenthesised() { + expect("("); + var ex = expression(); + expect(")"); + return ex; + }; + + function add_tokens(str, start, end) { + return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end); + }; + + function maybe_embed_tokens(parser) { + if (embed_tokens) return function() { + var start = S.token; + var ast = parser.apply(this, arguments); + ast[0] = add_tokens(ast[0], start, prev()); + return ast; + }; + else return parser; + }; + + var statement = maybe_embed_tokens(function() { + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); // force regexp + } + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + if (dir && stat[1][0] == "string" && !is("punc", ",")) + return as("directive", stat[1][1]); + return stat; + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement(prog1(S.token.value, next, next)) + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return as("block", block_()); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return as("block"); + default: + unexpected(); + } + + case "keyword": + switch (prog1(S.token.value, next)) { + case "break": + return break_cont("break"); + + case "continue": + return break_cont("continue"); + + case "debugger": + semicolon(); + return as("debugger"); + + case "do": + return (function(body){ + expect_token("keyword", "while"); + return as("do", prog1(parenthesised, semicolon), body); + })(in_loop(statement)); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return as("return", + is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : prog1(expression, semicolon)); + + case "switch": + return as("switch", parenthesised(), switch_block_()); + + case "throw": + if (S.token.nlb) + croak("Illegal newline after 'throw'"); + return as("throw", prog1(expression, semicolon)); + + case "try": + return try_(); + + case "var": + return prog1(var_, semicolon); + + case "const": + return prog1(const_, semicolon); + + case "while": + return as("while", parenthesised(), in_loop(statement)); + + case "with": + return as("with", parenthesised(), statement()); + + default: + unexpected(); + } + } + }); + + function labeled_statement(label) { + S.labels.push(label); + var start = S.token, stat = statement(); + if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0])) + unexpected(start); + S.labels.pop(); + return as("label", label, stat); + }; + + function simple_statement() { + return as("stat", prog1(expression, semicolon)); + }; + + function break_cont(type) { + var name; + if (!can_insert_semicolon()) { + name = is("name") ? S.token.value : null; + } + if (name != null) { + next(); + if (!member(name, S.labels)) + croak("Label " + name + " without matching loop or statement"); + } + else if (S.in_loop == 0) + croak(type + " not inside a loop or switch"); + semicolon(); + return as(type, name); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) { + if (init[0] == "var" && init[1].length > 1) + croak("Only one variable declaration allowed in for..in loop"); + return for_in(init); + } + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(); + expect(";"); + var step = is("punc", ")") ? null : expression(); + expect(")"); + return as("for", init, test, step, in_loop(statement)); + }; + + function for_in(init) { + var lhs = init[0] == "var" ? as("name", init[1][0]) : init; + next(); + var obj = expression(); + expect(")"); + return as("for-in", init, lhs, obj, in_loop(statement)); + }; + + var function_ = function(in_statement) { + var name = is("name") ? prog1(S.token.value, next) : null; + if (in_statement && !name) + unexpected(); + expect("("); + return as(in_statement ? "defun" : "function", + name, + // arguments + (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + if (!is("name")) unexpected(); + a.push(S.token.value); + next(); + } + next(); + return a; + })(true, []), + // body + (function(){ + ++S.in_function; + var loop = S.in_loop; + S.in_directives = true; + S.in_loop = 0; + var a = block_(); + --S.in_function; + S.in_loop = loop; + return a; + })()); + }; + + function if_() { + var cond = parenthesised(), body = statement(), belse; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return as("if", cond, body, belse); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + var switch_block_ = curry(in_loop, function(){ + expect("{"); + var a = [], cur = null; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + next(); + cur = []; + a.push([ expression(), cur ]); + expect(":"); + } + else if (is("keyword", "default")) { + next(); + expect(":"); + cur = []; + a.push([ null, cur ]); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + next(); + return a; + }); + + function try_() { + var body = block_(), bcatch, bfinally; + if (is("keyword", "catch")) { + next(); + expect("("); + if (!is("name")) + croak("Name expected"); + var name = S.token.value; + next(); + expect(")"); + bcatch = [ name, block_() ]; + } + if (is("keyword", "finally")) { + next(); + bfinally = block_(); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return as("try", body, bcatch, bfinally); + }; + + function vardefs(no_in) { + var a = []; + for (;;) { + if (!is("name")) + unexpected(); + var name = S.token.value; + next(); + if (is("operator", "=")) { + next(); + a.push([ name, expression(false, no_in) ]); + } else { + a.push([ name ]); + } + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + function var_(no_in) { + return as("var", vardefs(no_in)); + }; + + function const_() { + return as("const", vardefs()); + }; + + function new_() { + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(as("new", newexp, args), true); + }; + + var expr_atom = maybe_embed_tokens(function(allow_calls) { + if (is("operator", "new")) { + next(); + return new_(); + } + if (is("punc")) { + switch (S.token.value) { + case "(": + next(); + return subscripts(prog1(expression, curry(expect, ")")), allow_calls); + case "[": + next(); + return subscripts(array_(), allow_calls); + case "{": + next(); + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + return subscripts(function_(false), allow_calls); + } + if (HOP(ATOMIC_START_TOKEN, S.token.type)) { + var atom = S.token.type == "regexp" + ? as("regexp", S.token.value[0], S.token.value[1]) + : as(S.token.type, S.token.value); + return subscripts(prog1(atom, next), allow_calls); + } + unexpected(); + }); + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push([ "atom", "undefined" ]); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + function array_() { + return as("array", expr_list("]", !exigent_mode, true)); + }; + + function object_() { + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!exigent_mode && is("punc", "}")) + // allow trailing comma + break; + var type = S.token.type; + var name = as_property_name(); + if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) { + a.push([ as_name(), function_(false), name ]); + } else { + expect(":"); + a.push([ name, expression(false) ]); + } + } + next(); + return as("object", a); + }; + + function as_property_name() { + switch (S.token.type) { + case "num": + case "string": + return prog1(S.token.value, next); + } + return as_name(); + }; + + function as_name() { + switch (S.token.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return prog1(S.token.value, next); + default: + unexpected(); + } + }; + + function subscripts(expr, allow_calls) { + if (is("punc", ".")) { + next(); + return subscripts(as("dot", expr, as_name()), allow_calls); + } + if (is("punc", "[")) { + next(); + return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(as("call", expr, expr_list(")")), true); + } + return expr; + }; + + function maybe_unary(allow_calls) { + if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) { + return make_unary("unary-prefix", + prog1(S.token.value, next), + maybe_unary(allow_calls)); + } + var val = expr_atom(allow_calls); + while (is("operator") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) { + val = make_unary("unary-postfix", S.token.value, val); + next(); + } + return val; + }; + + function make_unary(tag, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return as(tag, op, expr); + }; + + function expr_op(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op && op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(as("binary", op, left, right), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + }; + + function maybe_conditional(no_in) { + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return as("conditional", expr, yes, expression(false, no_in)); + } + return expr; + }; + + function is_assignable(expr) { + if (!exigent_mode) return true; + switch (expr[0]+"") { + case "dot": + case "sub": + case "new": + case "call": + return true; + case "name": + return expr[1] != "this"; + } + }; + + function maybe_assign(no_in) { + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && HOP(ASSIGNMENT, val)) { + if (is_assignable(left)) { + next(); + return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in)); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = maybe_embed_tokens(function(commas, no_in) { + if (arguments.length == 0) + commas = true; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return as("seq", expr, expression(true, no_in)); + } + return expr; + }); + + function in_loop(cont) { + try { + ++S.in_loop; + return cont(); + } finally { + --S.in_loop; + } + }; + + return as("toplevel", (function(a){ + while (!is("eof")) + a.push(statement()); + return a; + })([])); + +}; + +/* -----[ Utilities ]----- */ + +function curry(f) { + var args = slice(arguments, 1); + return function() { return f.apply(this, args.concat(slice(arguments))); }; +}; + +function prog1(ret) { + if (ret instanceof Function) + ret = ret(); + for (var i = 1, n = arguments.length; --n > 0; ++i) + arguments[i](); + return ret; +}; + +function array_to_hash(a) { + var ret = {}; + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] == name) + return true; + return false; +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +var warn = function() {}; + +/* -----[ Exports ]----- */ + +exports.tokenizer = tokenizer; +exports.parse = parse; +exports.slice = slice; +exports.curry = curry; +exports.member = member; +exports.array_to_hash = array_to_hash; +exports.PRECEDENCE = PRECEDENCE; +exports.KEYWORDS_ATOM = KEYWORDS_ATOM; +exports.RESERVED_WORDS = RESERVED_WORDS; +exports.KEYWORDS = KEYWORDS; +exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN; +exports.OPERATORS = OPERATORS; +exports.is_alphanumeric_char = is_alphanumeric_char; +exports.is_identifier_start = is_identifier_start; +exports.is_identifier_char = is_identifier_char; +exports.set_logger = function(logger) { + warn = logger; +}; + +// Local variables: +// js-indent-level: 4 +// End: +});define('uglifyjs/squeeze-more', ["require", "exports", "module", "./parse-js", "./squeeze-more"], function(require, exports, module) { +var jsp = require("./parse-js"), + pro = require("./process"), + slice = jsp.slice, + member = jsp.member, + curry = jsp.curry, + MAP = pro.MAP, + PRECEDENCE = jsp.PRECEDENCE, + OPERATORS = jsp.OPERATORS; + +function ast_squeeze_more(ast) { + var w = pro.ast_walker(), walk = w.walk, scope; + function with_scope(s, cont) { + var save = scope, ret; + scope = s; + ret = cont(); + scope = save; + return ret; + }; + function _lambda(name, args, body) { + return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; + }; + return w.with_walkers({ + "toplevel": function(body) { + return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; + }, + "function": _lambda, + "defun": _lambda, + "new": function(ctor, args) { + if (ctor[0] == "name") { + if (ctor[1] == "Array" && !scope.has("Array")) { + if (args.length != 1) { + return [ "array", args ]; + } else { + return walk([ "call", [ "name", "Array" ], args ]); + } + } else if (ctor[1] == "Object" && !scope.has("Object")) { + if (!args.length) { + return [ "object", [] ]; + } else { + return walk([ "call", [ "name", "Object" ], args ]); + } + } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) { + return walk([ "call", [ "name", ctor[1] ], args]); + } + } + }, + "call": function(expr, args) { + if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1 + && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) { + return [ "call", [ "dot", expr[1], "slice"], args]; + } + if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) { + // foo.toString() ==> foo+"" + if (expr[1][0] == "string") return expr[1]; + return [ "binary", "+", expr[1], [ "string", "" ]]; + } + if (expr[0] == "name") { + if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) { + return [ "array", args ]; + } + if (expr[1] == "Object" && !args.length && !scope.has("Object")) { + return [ "object", [] ]; + } + if (expr[1] == "String" && !scope.has("String")) { + return [ "binary", "+", args[0], [ "string", "" ]]; + } + } + } + }, function() { + return walk(pro.ast_add_scope(ast)); + }); +}; + +exports.ast_squeeze_more = ast_squeeze_more; + +// Local variables: +// js-indent-level: 4 +// End: +}); +define('uglifyjs/process', ["require", "exports", "module", "./parse-js", "./squeeze-more"], function(require, exports, module) { +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + + This version is suitable for Node.js. With minimal changes (the + exports stuff) it should work on any JS platform. + + This file implements some AST processors. They work on data built + by parse-js. + + Exported functions: + + - ast_mangle(ast, options) -- mangles the variable/function names + in the AST. Returns an AST. + + - ast_squeeze(ast) -- employs various optimizations to make the + final generated code even smaller. Returns an AST. + + - gen_code(ast, options) -- generates JS code from the AST. Pass + true (or an object, see the code for some options) as second + argument to get "pretty" (indented) code. + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2010 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +var jsp = require("./parse-js"), + curry = jsp.curry, + slice = jsp.slice, + member = jsp.member, + is_identifier_char = jsp.is_identifier_char, + PRECEDENCE = jsp.PRECEDENCE, + OPERATORS = jsp.OPERATORS; + +/* -----[ helper for AST traversal ]----- */ + +function ast_walker() { + function _vardefs(defs) { + return [ this[0], MAP(defs, function(def){ + var a = [ def[0] ]; + if (def.length > 1) + a[1] = walk(def[1]); + return a; + }) ]; + }; + function _block(statements) { + var out = [ this[0] ]; + if (statements != null) + out.push(MAP(statements, walk)); + return out; + }; + var walkers = { + "string": function(str) { + return [ this[0], str ]; + }, + "num": function(num) { + return [ this[0], num ]; + }, + "name": function(name) { + return [ this[0], name ]; + }, + "toplevel": function(statements) { + return [ this[0], MAP(statements, walk) ]; + }, + "block": _block, + "splice": _block, + "var": _vardefs, + "const": _vardefs, + "try": function(t, c, f) { + return [ + this[0], + MAP(t, walk), + c != null ? [ c[0], MAP(c[1], walk) ] : null, + f != null ? MAP(f, walk) : null + ]; + }, + "throw": function(expr) { + return [ this[0], walk(expr) ]; + }, + "new": function(ctor, args) { + return [ this[0], walk(ctor), MAP(args, walk) ]; + }, + "switch": function(expr, body) { + return [ this[0], walk(expr), MAP(body, function(branch){ + return [ branch[0] ? walk(branch[0]) : null, + MAP(branch[1], walk) ]; + }) ]; + }, + "break": function(label) { + return [ this[0], label ]; + }, + "continue": function(label) { + return [ this[0], label ]; + }, + "conditional": function(cond, t, e) { + return [ this[0], walk(cond), walk(t), walk(e) ]; + }, + "assign": function(op, lvalue, rvalue) { + return [ this[0], op, walk(lvalue), walk(rvalue) ]; + }, + "dot": function(expr) { + return [ this[0], walk(expr) ].concat(slice(arguments, 1)); + }, + "call": function(expr, args) { + return [ this[0], walk(expr), MAP(args, walk) ]; + }, + "function": function(name, args, body) { + return [ this[0], name, args.slice(), MAP(body, walk) ]; + }, + "debugger": function() { + return [ this[0] ]; + }, + "defun": function(name, args, body) { + return [ this[0], name, args.slice(), MAP(body, walk) ]; + }, + "if": function(conditional, t, e) { + return [ this[0], walk(conditional), walk(t), walk(e) ]; + }, + "for": function(init, cond, step, block) { + return [ this[0], walk(init), walk(cond), walk(step), walk(block) ]; + }, + "for-in": function(vvar, key, hash, block) { + return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ]; + }, + "while": function(cond, block) { + return [ this[0], walk(cond), walk(block) ]; + }, + "do": function(cond, block) { + return [ this[0], walk(cond), walk(block) ]; + }, + "return": function(expr) { + return [ this[0], walk(expr) ]; + }, + "binary": function(op, left, right) { + return [ this[0], op, walk(left), walk(right) ]; + }, + "unary-prefix": function(op, expr) { + return [ this[0], op, walk(expr) ]; + }, + "unary-postfix": function(op, expr) { + return [ this[0], op, walk(expr) ]; + }, + "sub": function(expr, subscript) { + return [ this[0], walk(expr), walk(subscript) ]; + }, + "object": function(props) { + return [ this[0], MAP(props, function(p){ + return p.length == 2 + ? [ p[0], walk(p[1]) ] + : [ p[0], walk(p[1]), p[2] ]; // get/set-ter + }) ]; + }, + "regexp": function(rx, mods) { + return [ this[0], rx, mods ]; + }, + "array": function(elements) { + return [ this[0], MAP(elements, walk) ]; + }, + "stat": function(stat) { + return [ this[0], walk(stat) ]; + }, + "seq": function() { + return [ this[0] ].concat(MAP(slice(arguments), walk)); + }, + "label": function(name, block) { + return [ this[0], name, walk(block) ]; + }, + "with": function(expr, block) { + return [ this[0], walk(expr), walk(block) ]; + }, + "atom": function(name) { + return [ this[0], name ]; + }, + "directive": function(dir) { + return [ this[0], dir ]; + } + }; + + var user = {}; + var stack = []; + function walk(ast) { + if (ast == null) + return null; + try { + stack.push(ast); + var type = ast[0]; + var gen = user[type]; + if (gen) { + var ret = gen.apply(ast, ast.slice(1)); + if (ret != null) + return ret; + } + gen = walkers[type]; + return gen.apply(ast, ast.slice(1)); + } finally { + stack.pop(); + } + }; + + function dive(ast) { + if (ast == null) + return null; + try { + stack.push(ast); + return walkers[ast[0]].apply(ast, ast.slice(1)); + } finally { + stack.pop(); + } + }; + + function with_walkers(walkers, cont){ + var save = {}, i; + for (i in walkers) if (HOP(walkers, i)) { + save[i] = user[i]; + user[i] = walkers[i]; + } + var ret = cont(); + for (i in save) if (HOP(save, i)) { + if (!save[i]) delete user[i]; + else user[i] = save[i]; + } + return ret; + }; + + return { + walk: walk, + dive: dive, + with_walkers: with_walkers, + parent: function() { + return stack[stack.length - 2]; // last one is current node + }, + stack: function() { + return stack; + } + }; +}; + +/* -----[ Scope and mangling ]----- */ + +function Scope(parent) { + this.names = {}; // names defined in this scope + this.mangled = {}; // mangled names (orig.name => mangled) + this.rev_mangled = {}; // reverse lookup (mangled => orig.name) + this.cname = -1; // current mangled name + this.refs = {}; // names referenced from this scope + this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes + this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes + this.directives = []; // directives activated from this scope + this.parent = parent; // parent scope + this.children = []; // sub-scopes + if (parent) { + this.level = parent.level + 1; + parent.children.push(this); + } else { + this.level = 0; + } +}; + +function base54_digits() { + if (typeof DIGITS_OVERRIDE_FOR_TESTING != "undefined") + return DIGITS_OVERRIDE_FOR_TESTING; + else + return "etnrisouaflchpdvmgybwESxTNCkLAOM_DPHBjFIqRUzWXV$JKQGYZ0516372984"; +} + +var base54 = (function(){ + var DIGITS = base54_digits(); + return function(num) { + var ret = "", base = 54; + do { + ret += DIGITS.charAt(num % base); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + }; +})(); + +Scope.prototype = { + has: function(name) { + for (var s = this; s; s = s.parent) + if (HOP(s.names, name)) + return s; + }, + has_mangled: function(mname) { + for (var s = this; s; s = s.parent) + if (HOP(s.rev_mangled, mname)) + return s; + }, + toJSON: function() { + return { + names: this.names, + uses_eval: this.uses_eval, + uses_with: this.uses_with + }; + }, + + next_mangled: function() { + // we must be careful that the new mangled name: + // + // 1. doesn't shadow a mangled name from a parent + // scope, unless we don't reference the original + // name from this scope OR from any sub-scopes! + // This will get slow. + // + // 2. doesn't shadow an original name from a parent + // scope, in the event that the name is not mangled + // in the parent scope and we reference that name + // here OR IN ANY SUBSCOPES! + // + // 3. doesn't shadow a name that is referenced but not + // defined (possibly global defined elsewhere). + for (;;) { + var m = base54(++this.cname), prior; + + // case 1. + prior = this.has_mangled(m); + if (prior && this.refs[prior.rev_mangled[m]] === prior) + continue; + + // case 2. + prior = this.has(m); + if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m)) + continue; + + // case 3. + if (HOP(this.refs, m) && this.refs[m] == null) + continue; + + // I got "do" once. :-/ + if (!is_identifier(m)) + continue; + + return m; + } + }, + set_mangle: function(name, m) { + this.rev_mangled[m] = name; + return this.mangled[name] = m; + }, + get_mangled: function(name, newMangle) { + if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use + var s = this.has(name); + if (!s) return name; // not in visible scope, no mangle + if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope + if (!newMangle) return name; // not found and no mangling requested + return s.set_mangle(name, s.next_mangled()); + }, + references: function(name) { + return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name]; + }, + define: function(name, type) { + if (name != null) { + if (type == "var" || !HOP(this.names, name)) + this.names[name] = type || "var"; + return name; + } + }, + active_directive: function(dir) { + return member(dir, this.directives) || this.parent && this.parent.active_directive(dir); + } +}; + +function ast_add_scope(ast) { + + var current_scope = null; + var w = ast_walker(), walk = w.walk; + var having_eval = []; + + function with_new_scope(cont) { + current_scope = new Scope(current_scope); + current_scope.labels = new Scope(); + var ret = current_scope.body = cont(); + ret.scope = current_scope; + current_scope = current_scope.parent; + return ret; + }; + + function define(name, type) { + return current_scope.define(name, type); + }; + + function reference(name) { + current_scope.refs[name] = true; + }; + + function _lambda(name, args, body) { + var is_defun = this[0] == "defun"; + return [ this[0], is_defun ? define(name, "defun") : name, args, with_new_scope(function(){ + if (!is_defun) define(name, "lambda"); + MAP(args, function(name){ define(name, "arg") }); + return MAP(body, walk); + })]; + }; + + function _vardefs(type) { + return function(defs) { + MAP(defs, function(d){ + define(d[0], type); + if (d[1]) reference(d[0]); + }); + }; + }; + + function _breacont(label) { + if (label) + current_scope.labels.refs[label] = true; + }; + + return with_new_scope(function(){ + // process AST + var ret = w.with_walkers({ + "function": _lambda, + "defun": _lambda, + "label": function(name, stat) { current_scope.labels.define(name) }, + "break": _breacont, + "continue": _breacont, + "with": function(expr, block) { + for (var s = current_scope; s; s = s.parent) + s.uses_with = true; + }, + "var": _vardefs("var"), + "const": _vardefs("const"), + "try": function(t, c, f) { + if (c != null) return [ + this[0], + MAP(t, walk), + [ define(c[0], "catch"), MAP(c[1], walk) ], + f != null ? MAP(f, walk) : null + ]; + }, + "name": function(name) { + if (name == "eval") + having_eval.push(current_scope); + reference(name); + } + }, function(){ + return walk(ast); + }); + + // the reason why we need an additional pass here is + // that names can be used prior to their definition. + + // scopes where eval was detected and their parents + // are marked with uses_eval, unless they define the + // "eval" name. + MAP(having_eval, function(scope){ + if (!scope.has("eval")) while (scope) { + scope.uses_eval = true; + scope = scope.parent; + } + }); + + // for referenced names it might be useful to know + // their origin scope. current_scope here is the + // toplevel one. + function fixrefs(scope, i) { + // do children first; order shouldn't matter + for (i = scope.children.length; --i >= 0;) + fixrefs(scope.children[i]); + for (i in scope.refs) if (HOP(scope.refs, i)) { + // find origin scope and propagate the reference to origin + for (var origin = scope.has(i), s = scope; s; s = s.parent) { + s.refs[i] = origin; + if (s === origin) break; + } + } + }; + fixrefs(current_scope); + + return ret; + }); + +}; + +/* -----[ mangle names ]----- */ + +function ast_mangle(ast, options) { + var w = ast_walker(), walk = w.walk, scope; + options = defaults(options, { + mangle : true, + toplevel : false, + defines : null, + except : null, + no_functions : false + }); + + function get_mangled(name, newMangle) { + if (!options.mangle) return name; + if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel + if (options.except && member(name, options.except)) + return name; + if (options.no_functions && HOP(scope.names, name) && + (scope.names[name] == 'defun' || scope.names[name] == 'lambda')) + return name; + return scope.get_mangled(name, newMangle); + }; + + function get_define(name) { + if (options.defines) { + // we always lookup a defined symbol for the current scope FIRST, so declared + // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value + if (!scope.has(name)) { + if (HOP(options.defines, name)) { + return options.defines[name]; + } + } + return null; + } + }; + + function _lambda(name, args, body) { + if (!options.no_functions && options.mangle) { + var is_defun = this[0] == "defun", extra; + if (name) { + if (is_defun) name = get_mangled(name); + else if (body.scope.references(name)) { + extra = {}; + if (!(scope.uses_eval || scope.uses_with)) + name = extra[name] = scope.next_mangled(); + else + extra[name] = name; + } + else name = null; + } + } + body = with_scope(body.scope, function(){ + args = MAP(args, function(name){ return get_mangled(name) }); + return MAP(body, walk); + }, extra); + return [ this[0], name, args, body ]; + }; + + function with_scope(s, cont, extra) { + var _scope = scope; + scope = s; + if (extra) for (var i in extra) if (HOP(extra, i)) { + s.set_mangle(i, extra[i]); + } + for (var i in s.names) if (HOP(s.names, i)) { + get_mangled(i, true); + } + var ret = cont(); + ret.scope = s; + scope = _scope; + return ret; + }; + + function _vardefs(defs) { + return [ this[0], MAP(defs, function(d){ + return [ get_mangled(d[0]), walk(d[1]) ]; + }) ]; + }; + + function _breacont(label) { + if (label) return [ this[0], scope.labels.get_mangled(label) ]; + }; + + return w.with_walkers({ + "function": _lambda, + "defun": function() { + // move function declarations to the top when + // they are not in some block. + var ast = _lambda.apply(this, arguments); + switch (w.parent()[0]) { + case "toplevel": + case "function": + case "defun": + return MAP.at_top(ast); + } + return ast; + }, + "label": function(label, stat) { + if (scope.labels.refs[label]) return [ + this[0], + scope.labels.get_mangled(label, true), + walk(stat) + ]; + return walk(stat); + }, + "break": _breacont, + "continue": _breacont, + "var": _vardefs, + "const": _vardefs, + "name": function(name) { + return get_define(name) || [ this[0], get_mangled(name) ]; + }, + "try": function(t, c, f) { + return [ this[0], + MAP(t, walk), + c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null, + f != null ? MAP(f, walk) : null ]; + }, + "toplevel": function(body) { + var self = this; + return with_scope(self.scope, function(){ + return [ self[0], MAP(body, walk) ]; + }); + }, + "directive": function() { + return MAP.at_top(this); + } + }, function() { + return walk(ast_add_scope(ast)); + }); +}; + +/* -----[ + - compress foo["bar"] into foo.bar, + - remove block brackets {} where possible + - join consecutive var declarations + - various optimizations for IFs: + - if (cond) foo(); else bar(); ==> cond?foo():bar(); + - if (cond) foo(); ==> cond&&foo(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + ]----- */ + +var warn = function(){}; + +function best_of(ast1, ast2) { + return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1; +}; + +function last_stat(b) { + if (b[0] == "block" && b[1] && b[1].length > 0) + return b[1][b[1].length - 1]; + return b; +} + +function aborts(t) { + if (t) switch (last_stat(t)[0]) { + case "return": + case "break": + case "continue": + case "throw": + return true; + } +}; + +function boolean_expr(expr) { + return ( (expr[0] == "unary-prefix" + && member(expr[1], [ "!", "delete" ])) || + + (expr[0] == "binary" + && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) || + + (expr[0] == "binary" + && member(expr[1], [ "&&", "||" ]) + && boolean_expr(expr[2]) + && boolean_expr(expr[3])) || + + (expr[0] == "conditional" + && boolean_expr(expr[2]) + && boolean_expr(expr[3])) || + + (expr[0] == "assign" + && expr[1] === true + && boolean_expr(expr[3])) || + + (expr[0] == "seq" + && boolean_expr(expr[expr.length - 1])) + ); +}; + +function empty(b) { + return !b || (b[0] == "block" && (!b[1] || b[1].length == 0)); +}; + +function is_string(node) { + return (node[0] == "string" || + node[0] == "unary-prefix" && node[1] == "typeof" || + node[0] == "binary" && node[1] == "+" && + (is_string(node[2]) || is_string(node[3]))); +}; + +var when_constant = (function(){ + + var $NOT_CONSTANT = {}; + + // this can only evaluate constant expressions. If it finds anything + // not constant, it throws $NOT_CONSTANT. + function evaluate(expr) { + switch (expr[0]) { + case "string": + case "num": + return expr[1]; + case "name": + case "atom": + switch (expr[1]) { + case "true": return true; + case "false": return false; + case "null": return null; + } + break; + case "unary-prefix": + switch (expr[1]) { + case "!": return !evaluate(expr[2]); + case "typeof": return typeof evaluate(expr[2]); + case "~": return ~evaluate(expr[2]); + case "-": return -evaluate(expr[2]); + case "+": return +evaluate(expr[2]); + } + break; + case "binary": + var left = expr[2], right = expr[3]; + switch (expr[1]) { + case "&&" : return evaluate(left) && evaluate(right); + case "||" : return evaluate(left) || evaluate(right); + case "|" : return evaluate(left) | evaluate(right); + case "&" : return evaluate(left) & evaluate(right); + case "^" : return evaluate(left) ^ evaluate(right); + case "+" : return evaluate(left) + evaluate(right); + case "*" : return evaluate(left) * evaluate(right); + case "/" : return evaluate(left) / evaluate(right); + case "%" : return evaluate(left) % evaluate(right); + case "-" : return evaluate(left) - evaluate(right); + case "<<" : return evaluate(left) << evaluate(right); + case ">>" : return evaluate(left) >> evaluate(right); + case ">>>" : return evaluate(left) >>> evaluate(right); + case "==" : return evaluate(left) == evaluate(right); + case "===" : return evaluate(left) === evaluate(right); + case "!=" : return evaluate(left) != evaluate(right); + case "!==" : return evaluate(left) !== evaluate(right); + case "<" : return evaluate(left) < evaluate(right); + case "<=" : return evaluate(left) <= evaluate(right); + case ">" : return evaluate(left) > evaluate(right); + case ">=" : return evaluate(left) >= evaluate(right); + case "in" : return evaluate(left) in evaluate(right); + case "instanceof" : return evaluate(left) instanceof evaluate(right); + } + } + throw $NOT_CONSTANT; + }; + + return function(expr, yes, no) { + try { + var val = evaluate(expr), ast; + switch (typeof val) { + case "string": ast = [ "string", val ]; break; + case "number": ast = [ "num", val ]; break; + case "boolean": ast = [ "name", String(val) ]; break; + default: + if (val === null) { ast = [ "atom", "null" ]; break; } + throw new Error("Can't handle constant of type: " + (typeof val)); + } + return yes.call(expr, ast, val); + } catch(ex) { + if (ex === $NOT_CONSTANT) { + if (expr[0] == "binary" + && (expr[1] == "===" || expr[1] == "!==") + && ((is_string(expr[2]) && is_string(expr[3])) + || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) { + expr[1] = expr[1].substr(0, 2); + } + else if (no && expr[0] == "binary" + && (expr[1] == "||" || expr[1] == "&&")) { + // the whole expression is not constant but the lval may be... + try { + var lval = evaluate(expr[2]); + expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) || + (expr[1] == "||" && (lval ? lval : expr[3])) || + expr); + } catch(ex2) { + // IGNORE... lval is not constant + } + } + return no ? no.call(expr, expr) : null; + } + else throw ex; + } + }; + +})(); + +function warn_unreachable(ast) { + if (!empty(ast)) + warn("Dropping unreachable code: " + gen_code(ast, true)); +}; + +function prepare_ifs(ast) { + var w = ast_walker(), walk = w.walk; + // In this first pass, we rewrite ifs which abort with no else with an + // if-else. For example: + // + // if (x) { + // blah(); + // return y; + // } + // foobar(); + // + // is rewritten into: + // + // if (x) { + // blah(); + // return y; + // } else { + // foobar(); + // } + function redo_if(statements) { + statements = MAP(statements, walk); + + for (var i = 0; i < statements.length; ++i) { + var fi = statements[i]; + if (fi[0] != "if") continue; + + if (fi[3]) continue; + + var t = fi[2]; + if (!aborts(t)) continue; + + var conditional = walk(fi[1]); + + var e_body = redo_if(statements.slice(i + 1)); + var e = e_body.length == 1 ? e_body[0] : [ "block", e_body ]; + + return statements.slice(0, i).concat([ [ + fi[0], // "if" + conditional, // conditional + t, // then + e // else + ] ]); + } + + return statements; + }; + + function redo_if_lambda(name, args, body) { + body = redo_if(body); + return [ this[0], name, args, body ]; + }; + + function redo_if_block(statements) { + return [ this[0], statements != null ? redo_if(statements) : null ]; + }; + + return w.with_walkers({ + "defun": redo_if_lambda, + "function": redo_if_lambda, + "block": redo_if_block, + "splice": redo_if_block, + "toplevel": function(statements) { + return [ this[0], redo_if(statements) ]; + }, + "try": function(t, c, f) { + return [ + this[0], + redo_if(t), + c != null ? [ c[0], redo_if(c[1]) ] : null, + f != null ? redo_if(f) : null + ]; + } + }, function() { + return walk(ast); + }); +}; + +function for_side_effects(ast, handler) { + var w = ast_walker(), walk = w.walk; + var $stop = {}, $restart = {}; + function stop() { throw $stop }; + function restart() { throw $restart }; + function found(){ return handler.call(this, this, w, stop, restart) }; + function unary(op) { + if (op == "++" || op == "--") + return found.apply(this, arguments); + }; + function binary(op) { + if (op == "&&" || op == "||") + return found.apply(this, arguments); + }; + return w.with_walkers({ + "try": found, + "throw": found, + "return": found, + "new": found, + "switch": found, + "break": found, + "continue": found, + "assign": found, + "call": found, + "if": found, + "for": found, + "for-in": found, + "while": found, + "do": found, + "return": found, + "unary-prefix": unary, + "unary-postfix": unary, + "conditional": found, + "binary": binary, + "defun": found + }, function(){ + while (true) try { + walk(ast); + break; + } catch(ex) { + if (ex === $stop) break; + if (ex === $restart) continue; + throw ex; + } + }); +}; + +function ast_lift_variables(ast) { + var w = ast_walker(), walk = w.walk, scope; + function do_body(body, env) { + var _scope = scope; + scope = env; + body = MAP(body, walk); + var hash = {}, names = MAP(env.names, function(type, name){ + if (type != "var") return MAP.skip; + if (!env.references(name)) return MAP.skip; + hash[name] = true; + return [ name ]; + }); + if (names.length > 0) { + // looking for assignments to any of these variables. + // we can save considerable space by moving the definitions + // in the var declaration. + for_side_effects([ "block", body ], function(ast, walker, stop, restart) { + if (ast[0] == "assign" + && ast[1] === true + && ast[2][0] == "name" + && HOP(hash, ast[2][1])) { + // insert the definition into the var declaration + for (var i = names.length; --i >= 0;) { + if (names[i][0] == ast[2][1]) { + if (names[i][1]) // this name already defined, we must stop + stop(); + names[i][1] = ast[3]; // definition + names.push(names.splice(i, 1)[0]); + break; + } + } + // remove this assignment from the AST. + var p = walker.parent(); + if (p[0] == "seq") { + var a = p[2]; + a.unshift(0, p.length); + p.splice.apply(p, a); + } + else if (p[0] == "stat") { + p.splice(0, p.length, "block"); // empty statement + } + else { + stop(); + } + restart(); + } + stop(); + }); + body.unshift([ "var", names ]); + } + scope = _scope; + return body; + }; + function _vardefs(defs) { + var ret = null; + for (var i = defs.length; --i >= 0;) { + var d = defs[i]; + if (!d[1]) continue; + d = [ "assign", true, [ "name", d[0] ], d[1] ]; + if (ret == null) ret = d; + else ret = [ "seq", d, ret ]; + } + if (ret == null && w.parent()[0] != "for") { + if (w.parent()[0] == "for-in") + return [ "name", defs[0][0] ]; + return MAP.skip; + } + return [ "stat", ret ]; + }; + function _toplevel(body) { + return [ this[0], do_body(body, this.scope) ]; + }; + return w.with_walkers({ + "function": function(name, args, body){ + for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) + args.pop(); + if (!body.scope.references(name)) name = null; + return [ this[0], name, args, do_body(body, body.scope) ]; + }, + "defun": function(name, args, body){ + if (!scope.references(name)) return MAP.skip; + for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);) + args.pop(); + return [ this[0], name, args, do_body(body, body.scope) ]; + }, + "var": _vardefs, + "toplevel": _toplevel + }, function(){ + return walk(ast_add_scope(ast)); + }); +}; + +function ast_squeeze(ast, options) { + ast = squeeze_1(ast, options); + ast = squeeze_2(ast, options); + return ast; +}; + +function squeeze_1(ast, options) { + options = defaults(options, { + make_seqs : true, + dead_code : true, + no_warnings : false, + keep_comps : true, + unsafe : false + }); + + var w = ast_walker(), walk = w.walk, scope; + + function negate(c) { + var not_c = [ "unary-prefix", "!", c ]; + switch (c[0]) { + case "unary-prefix": + return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c; + case "seq": + c = slice(c); + c[c.length - 1] = negate(c[c.length - 1]); + return c; + case "conditional": + return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]); + case "binary": + var op = c[1], left = c[2], right = c[3]; + if (!options.keep_comps) switch (op) { + case "<=" : return [ "binary", ">", left, right ]; + case "<" : return [ "binary", ">=", left, right ]; + case ">=" : return [ "binary", "<", left, right ]; + case ">" : return [ "binary", "<=", left, right ]; + } + switch (op) { + case "==" : return [ "binary", "!=", left, right ]; + case "!=" : return [ "binary", "==", left, right ]; + case "===" : return [ "binary", "!==", left, right ]; + case "!==" : return [ "binary", "===", left, right ]; + case "&&" : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]); + case "||" : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]); + } + break; + } + return not_c; + }; + + function make_conditional(c, t, e) { + var make_real_conditional = function() { + if (c[0] == "unary-prefix" && c[1] == "!") { + return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ]; + } else { + return e ? best_of( + [ "conditional", c, t, e ], + [ "conditional", negate(c), e, t ] + ) : [ "binary", "&&", c, t ]; + } + }; + // shortcut the conditional if the expression has a constant value + return when_constant(c, function(ast, val){ + warn_unreachable(val ? e : t); + return (val ? t : e); + }, make_real_conditional); + }; + + function rmblock(block) { + if (block != null && block[0] == "block" && block[1]) { + if (block[1].length == 1) + block = block[1][0]; + else if (block[1].length == 0) + block = [ "block" ]; + } + return block; + }; + + function _lambda(name, args, body) { + return [ this[0], name, args, tighten(body, "lambda") ]; + }; + + // this function does a few things: + // 1. discard useless blocks + // 2. join consecutive var declarations + // 3. remove obviously dead code + // 4. transform consecutive statements using the comma operator + // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... } + function tighten(statements, block_type) { + statements = MAP(statements, walk); + + statements = statements.reduce(function(a, stat){ + if (stat[0] == "block") { + if (stat[1]) { + a.push.apply(a, stat[1]); + } + } else { + a.push(stat); + } + return a; + }, []); + + statements = (function(a, prev){ + statements.forEach(function(cur){ + if (prev && ((cur[0] == "var" && prev[0] == "var") || + (cur[0] == "const" && prev[0] == "const"))) { + prev[1] = prev[1].concat(cur[1]); + } else { + a.push(cur); + prev = cur; + } + }); + return a; + })([]); + + if (options.dead_code) statements = (function(a, has_quit){ + statements.forEach(function(st){ + if (has_quit) { + if (st[0] == "function" || st[0] == "defun") { + a.push(st); + } + else if (st[0] == "var" || st[0] == "const") { + if (!options.no_warnings) + warn("Variables declared in unreachable code"); + st[1] = MAP(st[1], function(def){ + if (def[1] && !options.no_warnings) + warn_unreachable([ "assign", true, [ "name", def[0] ], def[1] ]); + return [ def[0] ]; + }); + a.push(st); + } + else if (!options.no_warnings) + warn_unreachable(st); + } + else { + a.push(st); + if (member(st[0], [ "return", "throw", "break", "continue" ])) + has_quit = true; + } + }); + return a; + })([]); + + if (options.make_seqs) statements = (function(a, prev) { + statements.forEach(function(cur){ + if (prev && prev[0] == "stat" && cur[0] == "stat") { + prev[1] = [ "seq", prev[1], cur[1] ]; + } else { + a.push(cur); + prev = cur; + } + }); + if (a.length >= 2 + && a[a.length-2][0] == "stat" + && (a[a.length-1][0] == "return" || a[a.length-1][0] == "throw") + && a[a.length-1][1]) + { + a.splice(a.length - 2, 2, + [ a[a.length-1][0], + [ "seq", a[a.length-2][1], a[a.length-1][1] ]]); + } + return a; + })([]); + + // this increases jQuery by 1K. Probably not such a good idea after all.. + // part of this is done in prepare_ifs anyway. + // if (block_type == "lambda") statements = (function(i, a, stat){ + // while (i < statements.length) { + // stat = statements[i++]; + // if (stat[0] == "if" && !stat[3]) { + // if (stat[2][0] == "return" && stat[2][1] == null) { + // a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ])); + // break; + // } + // var last = last_stat(stat[2]); + // if (last[0] == "return" && last[1] == null) { + // a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ])); + // break; + // } + // } + // a.push(stat); + // } + // return a; + // })(0, []); + + return statements; + }; + + function make_if(c, t, e) { + return when_constant(c, function(ast, val){ + if (val) { + t = walk(t); + warn_unreachable(e); + return t || [ "block" ]; + } else { + e = walk(e); + warn_unreachable(t); + return e || [ "block" ]; + } + }, function() { + return make_real_if(c, t, e); + }); + }; + + function abort_else(c, t, e) { + var ret = [ [ "if", negate(c), e ] ]; + if (t[0] == "block") { + if (t[1]) ret = ret.concat(t[1]); + } else { + ret.push(t); + } + return walk([ "block", ret ]); + }; + + function make_real_if(c, t, e) { + c = walk(c); + t = walk(t); + e = walk(e); + + if (empty(e) && empty(t)) + return [ "stat", c ]; + + if (empty(t)) { + c = negate(c); + t = e; + e = null; + } else if (empty(e)) { + e = null; + } else { + // if we have both else and then, maybe it makes sense to switch them? + (function(){ + var a = gen_code(c); + var n = negate(c); + var b = gen_code(n); + if (b.length < a.length) { + var tmp = t; + t = e; + e = tmp; + c = n; + } + })(); + } + var ret = [ "if", c, t, e ]; + if (t[0] == "if" && empty(t[3]) && empty(e)) { + ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ])); + } + else if (t[0] == "stat") { + if (e) { + if (e[0] == "stat") + ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]); + else if (aborts(e)) + ret = abort_else(c, t, e); + } + else { + ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]); + } + } + else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) { + ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]); + } + else if (e && aborts(t)) { + ret = [ [ "if", c, t ] ]; + if (e[0] == "block") { + if (e[1]) ret = ret.concat(e[1]); + } + else { + ret.push(e); + } + ret = walk([ "block", ret ]); + } + else if (t && aborts(e)) { + ret = abort_else(c, t, e); + } + return ret; + }; + + function _do_while(cond, body) { + return when_constant(cond, function(cond, val){ + if (!val) { + warn_unreachable(body); + return [ "block" ]; + } else { + return [ "for", null, null, null, walk(body) ]; + } + }); + }; + + return w.with_walkers({ + "sub": function(expr, subscript) { + if (subscript[0] == "string") { + var name = subscript[1]; + if (is_identifier(name)) + return [ "dot", walk(expr), name ]; + else if (/^[1-9][0-9]*$/.test(name) || name === "0") + return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ]; + } + }, + "if": make_if, + "toplevel": function(body) { + return [ "toplevel", tighten(body) ]; + }, + "switch": function(expr, body) { + var last = body.length - 1; + return [ "switch", walk(expr), MAP(body, function(branch, i){ + var block = tighten(branch[1]); + if (i == last && block.length > 0) { + var node = block[block.length - 1]; + if (node[0] == "break" && !node[1]) + block.pop(); + } + return [ branch[0] ? walk(branch[0]) : null, block ]; + }) ]; + }, + "function": _lambda, + "defun": _lambda, + "block": function(body) { + if (body) return rmblock([ "block", tighten(body) ]); + }, + "binary": function(op, left, right) { + return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){ + return best_of(walk(c), this); + }, function no() { + return function(){ + if(op != "==" && op != "!=") return; + var l = walk(left), r = walk(right); + if(l && l[0] == "unary-prefix" && l[1] == "!" && l[2][0] == "num") + left = ['num', +!l[2][1]]; + else if (r && r[0] == "unary-prefix" && r[1] == "!" && r[2][0] == "num") + right = ['num', +!r[2][1]]; + return ["binary", op, left, right]; + }() || this; + }); + }, + "conditional": function(c, t, e) { + return make_conditional(walk(c), walk(t), walk(e)); + }, + "try": function(t, c, f) { + return [ + "try", + tighten(t), + c != null ? [ c[0], tighten(c[1]) ] : null, + f != null ? tighten(f) : null + ]; + }, + "unary-prefix": function(op, expr) { + expr = walk(expr); + var ret = [ "unary-prefix", op, expr ]; + if (op == "!") + ret = best_of(ret, negate(expr)); + return when_constant(ret, function(ast, val){ + return walk(ast); // it's either true or false, so minifies to !0 or !1 + }, function() { return ret }); + }, + "name": function(name) { + switch (name) { + case "true": return [ "unary-prefix", "!", [ "num", 0 ]]; + case "false": return [ "unary-prefix", "!", [ "num", 1 ]]; + } + }, + "while": _do_while, + "assign": function(op, lvalue, rvalue) { + lvalue = walk(lvalue); + rvalue = walk(rvalue); + var okOps = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + if (op === true && lvalue[0] === "name" && rvalue[0] === "binary" && + ~okOps.indexOf(rvalue[1]) && rvalue[2][0] === "name" && + rvalue[2][1] === lvalue[1]) { + return [ this[0], rvalue[1], lvalue, rvalue[3] ] + } + return [ this[0], op, lvalue, rvalue ]; + }, + "call": function(expr, args) { + expr = walk(expr); + if (options.unsafe && expr[0] == "dot" && expr[1][0] == "string" && expr[2] == "toString") { + return expr[1]; + } + return [ this[0], expr, MAP(args, walk) ]; + }, + "num": function (num) { + if (!isFinite(num)) + return [ "binary", "/", num === 1 / 0 + ? [ "num", 1 ] : num === -1 / 0 + ? [ "unary-prefix", "-", [ "num", 1 ] ] + : [ "num", 0 ], [ "num", 0 ] ]; + + return [ this[0], num ]; + } + }, function() { + return walk(prepare_ifs(walk(prepare_ifs(ast)))); + }); +}; + +function squeeze_2(ast, options) { + var w = ast_walker(), walk = w.walk, scope; + function with_scope(s, cont) { + var save = scope, ret; + scope = s; + ret = cont(); + scope = save; + return ret; + }; + function lambda(name, args, body) { + return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ]; + }; + return w.with_walkers({ + "directive": function(dir) { + if (scope.active_directive(dir)) + return [ "block" ]; + scope.directives.push(dir); + }, + "toplevel": function(body) { + return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ]; + }, + "function": lambda, + "defun": lambda + }, function(){ + return walk(ast_add_scope(ast)); + }); +}; + +/* -----[ re-generate code from the AST ]----- */ + +var DOT_CALL_NO_PARENS = jsp.array_to_hash([ + "name", + "array", + "object", + "string", + "dot", + "sub", + "call", + "regexp", + "defun" +]); + +function make_string(str, ascii_only) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + case "\0": return "\\0"; + } + return s; + }); + if (ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; +}; + +function to_ascii(str) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + while (code.length < 4) code = "0" + code; + return "\\u" + code; + }); +}; + +var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]); + +function gen_code(ast, options) { + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : false, + beautify : false, + ascii_only : false, + inline_script: false + }); + var beautify = !!options.beautify; + var indentation = 0, + newline = beautify ? "\n" : "", + space = beautify ? " " : ""; + + function encode_string(str) { + var ret = make_string(str, options.ascii_only); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name); + return name; + }; + + function indent(line) { + if (line == null) + line = ""; + if (beautify) + line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line; + return line; + }; + + function with_indent(cont, incr) { + if (incr == null) incr = 1; + indentation += incr; + try { return cont.apply(null, slice(arguments, 1)); } + finally { indentation -= incr; } + }; + + function last_char(str) { + str = str.toString(); + return str.charAt(str.length - 1); + }; + + function first_char(str) { + return str.toString().charAt(0); + }; + + function add_spaces(a) { + if (beautify) + return a.join(" "); + var b = []; + for (var i = 0; i < a.length; ++i) { + var next = a[i + 1]; + b.push(a[i]); + if (next && + ((is_identifier_char(last_char(a[i])) && (is_identifier_char(first_char(next)) + || first_char(next) == "\\")) || + (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString()) || + last_char(a[i]) == "/" && first_char(next) == "/"))) { + b.push(" "); + } + } + return b.join(""); + }; + + function add_commas(a) { + return a.join("," + space); + }; + + function parenthesize(expr) { + var gen = make(expr); + for (var i = 1; i < arguments.length; ++i) { + var el = arguments[i]; + if ((el instanceof Function && el(expr)) || expr[0] == el) + return "(" + gen + ")"; + } + return gen; + }; + + function best_of(a) { + if (a.length == 1) { + return a[0]; + } + if (a.length == 2) { + var b = a[1]; + a = a[0]; + return a.length <= b.length ? a : b; + } + return best_of([ a[0], best_of(a.slice(1)) ]); + }; + + function needs_parens(expr) { + if (expr[0] == "function" || expr[0] == "object") { + // dot/call on a literal function requires the + // function literal itself to be parenthesized + // only if it's the first "thing" in a + // statement. This means that the parent is + // "stat", but it could also be a "seq" and + // we're the first in this "seq" and the + // parent is "stat", and so on. Messy stuff, + // but it worths the trouble. + var a = slice(w.stack()), self = a.pop(), p = a.pop(); + while (p) { + if (p[0] == "stat") return true; + if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) || + ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) { + self = p; + p = a.pop(); + } else { + return false; + } + } + } + return !HOP(DOT_CALL_NO_PARENS, expr[0]); + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; + if (Math.floor(num) === num) { + if (num >= 0) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + } else { + a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless + "-0" + (-num).toString(8)); // same. + } + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + var w = ast_walker(); + var make = w.walk; + return w.with_walkers({ + "string": encode_string, + "num": make_num, + "name": make_name, + "debugger": function(){ return "debugger;" }, + "toplevel": function(statements) { + return make_block_statements(statements) + .join(newline + newline); + }, + "splice": function(statements) { + var parent = w.parent(); + if (HOP(SPLICE_NEEDS_BRACKETS, parent)) { + // we need block brackets in this case + return make_block.apply(this, arguments); + } else { + return MAP(make_block_statements(statements, true), + function(line, i) { + // the first line is already indented + return i > 0 ? indent(line) : line; + }).join(newline); + } + }, + "block": make_block, + "var": function(defs) { + return "var " + add_commas(MAP(defs, make_1vardef)) + ";"; + }, + "const": function(defs) { + return "const " + add_commas(MAP(defs, make_1vardef)) + ";"; + }, + "try": function(tr, ca, fi) { + var out = [ "try", make_block(tr) ]; + if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1])); + if (fi) out.push("finally", make_block(fi)); + return add_spaces(out); + }, + "throw": function(expr) { + return add_spaces([ "throw", make(expr) ]) + ";"; + }, + "new": function(ctor, args) { + args = args.length > 0 ? "(" + add_commas(MAP(args, function(expr){ + return parenthesize(expr, "seq"); + })) + ")" : ""; + return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){ + var w = ast_walker(), has_call = {}; + try { + w.with_walkers({ + "call": function() { throw has_call }, + "function": function() { return this } + }, function(){ + w.walk(expr); + }); + } catch(ex) { + if (ex === has_call) + return true; + throw ex; + } + }) + args ]); + }, + "switch": function(expr, body) { + return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]); + }, + "break": function(label) { + var out = "break"; + if (label != null) + out += " " + make_name(label); + return out + ";"; + }, + "continue": function(label) { + var out = "continue"; + if (label != null) + out += " " + make_name(label); + return out + ";"; + }, + "conditional": function(co, th, el) { + return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?", + parenthesize(th, "seq"), ":", + parenthesize(el, "seq") ]); + }, + "assign": function(op, lvalue, rvalue) { + if (op && op !== true) op += "="; + else op = "="; + return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); + }, + "dot": function(expr) { + var out = make(expr), i = 1; + if (expr[0] == "num") { + if (!/[a-f.]/i.test(out)) + out += "."; + } else if (expr[0] != "function" && needs_parens(expr)) + out = "(" + out + ")"; + while (i < arguments.length) + out += "." + make_name(arguments[i++]); + return out; + }, + "call": function(func, args) { + var f = make(func); + if (f.charAt(0) != "(" && needs_parens(func)) + f = "(" + f + ")"; + return f + "(" + add_commas(MAP(args, function(expr){ + return parenthesize(expr, "seq"); + })) + ")"; + }, + "function": make_function, + "defun": make_function, + "if": function(co, th, el) { + var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ]; + if (el) { + out.push("else", make(el)); + } + return add_spaces(out); + }, + "for": function(init, cond, step, block) { + var out = [ "for" ]; + init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space); + cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space); + step = (step != null ? make(step) : "").replace(/;*\s*$/, ""); + var args = init + cond + step; + if (args == "; ; ") args = ";;"; + out.push("(" + args + ")", make(block)); + return add_spaces(out); + }, + "for-in": function(vvar, key, hash, block) { + return add_spaces([ "for", "(" + + (vvar ? make(vvar).replace(/;+$/, "") : make(key)), + "in", + make(hash) + ")", make(block) ]); + }, + "while": function(condition, block) { + return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]); + }, + "do": function(condition, block) { + return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";"; + }, + "return": function(expr) { + var out = [ "return" ]; + if (expr != null) out.push(make(expr)); + return add_spaces(out) + ";"; + }, + "binary": function(operator, lvalue, rvalue) { + var left = make(lvalue), right = make(rvalue); + // XXX: I'm pretty sure other cases will bite here. + // we need to be smarter. + // adding parens all the time is the safest bet. + if (member(lvalue[0], [ "assign", "conditional", "seq" ]) || + lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] || + lvalue[0] == "function" && needs_parens(this)) { + left = "(" + left + ")"; + } + if (member(rvalue[0], [ "assign", "conditional", "seq" ]) || + rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] && + !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { + right = "(" + right + ")"; + } + else if (!beautify && options.inline_script && (operator == "<" || operator == "<<") + && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) { + right = " " + right; + } + return add_spaces([ left, operator, right ]); + }, + "unary-prefix": function(operator, expr) { + var val = make(expr); + if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) + val = "(" + val + ")"; + return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val; + }, + "unary-postfix": function(operator, expr) { + var val = make(expr); + if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) + val = "(" + val + ")"; + return val + operator; + }, + "sub": function(expr, subscript) { + var hash = make(expr); + if (needs_parens(expr)) + hash = "(" + hash + ")"; + return hash + "[" + make(subscript) + "]"; + }, + "object": function(props) { + var obj_needs_parens = needs_parens(this); + if (props.length == 0) + return obj_needs_parens ? "({})" : "{}"; + var out = "{" + newline + with_indent(function(){ + return MAP(props, function(p){ + if (p.length == 3) { + // getter/setter. The name is in p[0], the arg.list in p[1][2], the + // body in p[1][3] and type ("get" / "set") in p[2]. + return indent(make_function(p[0], p[1][2], p[1][3], p[2], true)); + } + var key = p[0], val = parenthesize(p[1], "seq"); + if (options.quote_keys) { + key = encode_string(key); + } else if ((typeof key == "number" || !beautify && +key + "" == key) + && parseFloat(key) >= 0) { + key = make_num(+key); + } else if (!is_identifier(key)) { + key = encode_string(key); + } + return indent(add_spaces(beautify && options.space_colon + ? [ key, ":", val ] + : [ key + ":", val ])); + }).join("," + newline); + }) + newline + indent("}"); + return obj_needs_parens ? "(" + out + ")" : out; + }, + "regexp": function(rx, mods) { + if (options.ascii_only) rx = to_ascii(rx); + return "/" + rx + "/" + mods; + }, + "array": function(elements) { + if (elements.length == 0) return "[]"; + return add_spaces([ "[", add_commas(MAP(elements, function(el, i){ + if (!beautify && el[0] == "atom" && el[1] == "undefined") return i === elements.length - 1 ? "," : ""; + return parenthesize(el, "seq"); + })), "]" ]); + }, + "stat": function(stmt) { + return stmt != null + ? make(stmt).replace(/;*\s*$/, ";") + : ";"; + }, + "seq": function() { + return add_commas(MAP(slice(arguments), make)); + }, + "label": function(name, block) { + return add_spaces([ make_name(name), ":", make(block) ]); + }, + "with": function(expr, block) { + return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]); + }, + "atom": function(name) { + return make_name(name); + }, + "directive": function(dir) { + return make_string(dir) + ";"; + } + }, function(){ return make(ast) }); + + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + function make_then(th) { + if (th == null) return ";"; + if (th[0] == "do") { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 + // IE croaks with "syntax error" on code like this: + // if (foo) do ... while(cond); else ... + // we need block brackets around do/while + return make_block([ th ]); + } + var b = th; + while (true) { + var type = b[0]; + if (type == "if") { + if (!b[3]) + // no else, we must add the block + return make([ "block", [ th ]]); + b = b[3]; + } + else if (type == "while" || type == "do") b = b[2]; + else if (type == "for" || type == "for-in") b = b[4]; + else break; + } + return make(th); + }; + + function make_function(name, args, body, keyword, no_parens) { + var out = keyword || "function"; + if (name) { + out += " " + make_name(name); + } + out += "(" + add_commas(MAP(args, make_name)) + ")"; + out = add_spaces([ out, make_block(body) ]); + return (!no_parens && needs_parens(this)) ? "(" + out + ")" : out; + }; + + function must_has_semicolon(node) { + switch (node[0]) { + case "with": + case "while": + return empty(node[2]) || must_has_semicolon(node[2]); + case "for": + case "for-in": + return empty(node[4]) || must_has_semicolon(node[4]); + case "if": + if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else' + if (node[3]) { + if (empty(node[3])) return true; // `else' present but empty + return must_has_semicolon(node[3]); // dive into the `else' branch + } + return must_has_semicolon(node[2]); // dive into the `then' branch + case "directive": + return true; + } + }; + + function make_block_statements(statements, noindent) { + for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) { + var stat = statements[i]; + var code = make(stat); + if (code != ";") { + if (!beautify && i == last && !must_has_semicolon(stat)) { + code = code.replace(/;+\s*$/, ""); + } + a.push(code); + } + } + return noindent ? a : MAP(a, indent); + }; + + function make_switch_block(body) { + var n = body.length; + if (n == 0) return "{}"; + return "{" + newline + MAP(body, function(branch, i){ + var has_body = branch[1].length > 0, code = with_indent(function(){ + return indent(branch[0] + ? add_spaces([ "case", make(branch[0]) + ":" ]) + : "default:"); + }, 0.5) + (has_body ? newline + with_indent(function(){ + return make_block_statements(branch[1]).join(newline); + }) : ""); + if (!beautify && has_body && i < n - 1) + code += ";"; + return code; + }).join(newline) + newline + indent("}"); + }; + + function make_block(statements) { + if (!statements) return ";"; + if (statements.length == 0) return "{}"; + return "{" + newline + with_indent(function(){ + return make_block_statements(statements).join(newline); + }) + newline + indent("}"); + }; + + function make_1vardef(def) { + var name = def[0], val = def[1]; + if (val != null) + name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]); + return name; + }; + +}; + +function split_lines(code, max_line_length) { + var splits = [ 0 ]; + jsp.parse(function(){ + var next_token = jsp.tokenizer(code); + var last_split = 0; + var prev_token; + function current_length(tok) { + return tok.pos - last_split; + }; + function split_here(tok) { + last_split = tok.pos; + splits.push(last_split); + }; + function custom(){ + var tok = next_token.apply(this, arguments); + out: { + if (prev_token) { + if (prev_token.type == "keyword") break out; + } + if (current_length(tok) > max_line_length) { + switch (tok.type) { + case "keyword": + case "atom": + case "name": + case "punc": + split_here(tok); + break out; + } + } + } + prev_token = tok; + return tok; + }; + custom.context = function() { + return next_token.context.apply(this, arguments); + }; + return custom; + }()); + return splits.map(function(pos, i){ + return code.substring(pos, splits[i + 1] || code.length); + }).join("\n"); +}; + +/* -----[ Utilities ]----- */ + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function defaults(args, defs) { + var ret = {}; + if (args === true) + args = {}; + for (var i in defs) if (HOP(defs, i)) { + ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; + } + return ret; +}; + +function is_identifier(name) { + return /^[a-z_$][a-z0-9_$]*$/i.test(name) + && name != "this" + && !HOP(jsp.KEYWORDS_ATOM, name) + && !HOP(jsp.RESERVED_WORDS, name) + && !HOP(jsp.KEYWORDS, name); +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +// some utilities + +var MAP; + +(function(){ + MAP = function(a, f, o) { + var ret = [], top = [], i; + function doit() { + var val = f.call(o, a[i], i); + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, val.v); + } else { + top.push(val); + } + } + else if (val != skip) { + if (val instanceof Splice) { + ret.push.apply(ret, val.v); + } else { + ret.push(val); + } + } + }; + if (a instanceof Array) for (i = 0; i < a.length; ++i) doit(); + else for (i in a) if (HOP(a, i)) doit(); + return top.concat(ret); + }; + MAP.at_top = function(val) { return new AtTop(val) }; + MAP.splice = function(val) { return new Splice(val) }; + var skip = MAP.skip = {}; + function AtTop(val) { this.v = val }; + function Splice(val) { this.v = val }; +})(); + +/* -----[ Exports ]----- */ + +exports.ast_walker = ast_walker; +exports.ast_mangle = ast_mangle; +exports.ast_squeeze = ast_squeeze; +exports.ast_lift_variables = ast_lift_variables; +exports.gen_code = gen_code; +exports.ast_add_scope = ast_add_scope; +exports.set_logger = function(logger) { warn = logger }; +exports.make_string = make_string; +exports.split_lines = split_lines; +exports.MAP = MAP; + +// keep this last! +exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more; + +// Local variables: +// js-indent-level: 4 +// End: +}); +define('uglifyjs/index', ["require", "exports", "module", "./parse-js", "./process", "./consolidator"], function(require, exports, module) { +//convienence function(src, [options]); +function uglify(orig_code, options){ + options || (options = {}); + var jsp = uglify.parser; + var pro = uglify.uglify; + + var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST + ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names + ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations + var final_code = pro.gen_code(ast, options.gen_options); // compressed code here + return final_code; +}; + +uglify.parser = require("./parse-js"); +uglify.uglify = require("./process"); +uglify.consolidator = require("./consolidator"); + +module.exports = uglify +});/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('source-map/array-set', function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var isDuplicate = this.has(aStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[util.toSetString(aStr)] = idx; + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +define('source-map/base64-vlq', function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + +}); +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('source-map/base64', function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('source-map/binary-search', function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + +}); +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('source-map/source-map-consumer', function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + var names = util.getArg(sourceMap, 'names'); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + if (version !== this._version) { + throw new Error('Unsupported version: ' + version); + } + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this.file = file; + + // `this._generatedMappings` and `this._originalMappings` hold the parsed + // mapping coordinates from the source map's "mappings" attribute. Each + // object in the array is of the form + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `this._generatedMappings` is ordered by the generated positions. + // + // `this._originalMappings` is ordered by the original positions. + this._generatedMappings = []; + this._originalMappings = []; + this._parseMappings(mappings, sourceRoot); + } + + /** + * Create a SourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns SourceMapConsumer + */ + SourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(SourceMapConsumer.prototype); + + smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + smc._generatedMappings = aSourceMap._mappings.slice() + .sort(util.compareByGeneratedPositions); + smc._originalMappings = aSourceMap._mappings.slice() + .sort(util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (an ordered list in this._generatedMappings). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this._generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this._originalMappings.push(mapping); + } + } + } + + this._originalMappings.sort(util.compareByOriginalPositions); + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositions); + + if (mapping) { + var source = util.getArg(mapping, 'source', null); + if (source && this.sourceRoot) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source && sourceRoot) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('source-map/source-map-generator', function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.originalLine) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + orginal: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guaranteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(util.compareByGeneratedPositions); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositions(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('source-map/source-node', function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine === undefined ? null : aLine; + this.column = aColumn === undefined ? null : aColumn; + this.source = aSource === undefined ? null : aSource; + this.name = aName === undefined ? null : aName; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // The generated code + // Processed fragments are removed from this array. + var remainingLines = aGeneratedCode.split('\n'); + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping === null) { + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(remainingLines.shift() + "\n"); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + } else { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate full lines with "lastMapping" + do { + code += remainingLines.shift() + "\n"; + lastGeneratedLine++; + lastGeneratedColumn = 0; + } while (lastGeneratedLine < mapping.generatedLine); + // When we reached the correct line, we add code until we + // reach the correct column too. + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + code += nextLine.substr(0, mapping.generatedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + // Create the SourceNode. + addMappingWithCode(lastMapping, code); + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + } + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + // Associate the remaining code in the current line with "lastMapping" + // and add the remaining lines without any mapping + addMappingWithCode(lastMapping, remainingLines.join("\n")); + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + mapping.source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i] instanceof SourceNode) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + chunk.split('').forEach(function (ch) { + if (ch === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +define('source-map/util', function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + var dataUrlRegexp = /^data:.+\,.+/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = aParsedUrl.scheme + "://"; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + "@" + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp) || aPath.match(dataUrlRegexp)) { + return aPath; + } + + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + url.path = aPath; + return urlGenerate(url); + } + + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + exports.join = join; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + + function strcmp(aStr1, aStr2) { + var s1 = aStr1 || ""; + var s2 = aStr2 || ""; + return (s1 > s2) - (s1 < s2); + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp; + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp || onlyCompareOriginal) { + return cmp; + } + + cmp = strcmp(mappingA.name, mappingB.name); + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + return mappingA.generatedColumn - mappingB.generatedColumn; + }; + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings where the generated positions are + * compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { + var cmp; + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + }; + exports.compareByGeneratedPositions = compareByGeneratedPositions; + +}); +define('source-map', function (require, exports, module) { + +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; + +}); + +//Distributed under the BSD license: +//Copyright 2012 (c) Mihai Bazon +define('uglifyjs2', ['exports', 'source-map', 'logger', 'env!env/file'], function (exports, MOZ_SourceMap, logger, rjsFile) { +(function(exports, global) { + global["UglifyJS"] = exports; + "use strict"; + function array_to_hash(a) { + var ret = Object.create(null); + for (var i = 0; i < a.length; ++i) ret[a[i]] = true; + return ret; + } + function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); + } + function characters(str) { + return str.split(""); + } + function member(name, array) { + for (var i = array.length; --i >= 0; ) if (array[i] == name) return true; + return false; + } + function find_if(func, array) { + for (var i = 0, n = array.length; i < n; ++i) { + if (func(array[i])) return array[i]; + } + } + function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; + } + function DefaultsError(msg, defs) { + this.msg = msg; + this.defs = defs; + } + function defaults(args, defs, croak) { + if (args === true) args = {}; + var ret = args || {}; + if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) throw new DefaultsError("`" + i + "` is not a supported option", defs); + for (var i in defs) if (defs.hasOwnProperty(i)) { + ret[i] = args && args.hasOwnProperty(i) ? args[i] : defs[i]; + } + return ret; + } + function merge(obj, ext) { + for (var i in ext) if (ext.hasOwnProperty(i)) { + obj[i] = ext[i]; + } + return obj; + } + function noop() {} + var MAP = function() { + function MAP(a, f, backwards) { + var ret = [], top = [], i; + function doit() { + var val = f(a[i], i); + var is_last = val instanceof Last; + if (is_last) val = val.v; + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, backwards ? val.v.slice().reverse() : val.v); + } else { + top.push(val); + } + } else if (val !== skip) { + if (val instanceof Splice) { + ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); + } else { + ret.push(val); + } + } + return is_last; + } + if (a instanceof Array) { + if (backwards) { + for (i = a.length; --i >= 0; ) if (doit()) break; + ret.reverse(); + top.reverse(); + } else { + for (i = 0; i < a.length; ++i) if (doit()) break; + } + } else { + for (i in a) if (a.hasOwnProperty(i)) if (doit()) break; + } + return top.concat(ret); + } + MAP.at_top = function(val) { + return new AtTop(val); + }; + MAP.splice = function(val) { + return new Splice(val); + }; + MAP.last = function(val) { + return new Last(val); + }; + var skip = MAP.skip = {}; + function AtTop(val) { + this.v = val; + } + function Splice(val) { + this.v = val; + } + function Last(val) { + this.v = val; + } + return MAP; + }(); + function push_uniq(array, el) { + if (array.indexOf(el) < 0) array.push(el); + } + function string_template(text, props) { + return text.replace(/\{(.+?)\}/g, function(str, p) { + return props[p]; + }); + } + function remove(array, el) { + for (var i = array.length; --i >= 0; ) { + if (array[i] === el) array.splice(i, 1); + } + } + function mergeSort(array, cmp) { + if (array.length < 2) return array.slice(); + function merge(a, b) { + var r = [], ai = 0, bi = 0, i = 0; + while (ai < a.length && bi < b.length) { + cmp(a[ai], b[bi]) <= 0 ? r[i++] = a[ai++] : r[i++] = b[bi++]; + } + if (ai < a.length) r.push.apply(r, a.slice(ai)); + if (bi < b.length) r.push.apply(r, b.slice(bi)); + return r; + } + function _ms(a) { + if (a.length <= 1) return a; + var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m); + left = _ms(left); + right = _ms(right); + return merge(left, right); + } + return _ms(array); + } + function set_difference(a, b) { + return a.filter(function(el) { + return b.indexOf(el) < 0; + }); + } + function set_intersection(a, b) { + return a.filter(function(el) { + return b.indexOf(el) >= 0; + }); + } + function makePredicate(words) { + if (!(words instanceof Array)) words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([ words[i] ]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + if (cats.length > 3) { + cats.sort(function(a, b) { + return b.length - a.length; + }); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + } else { + compareTo(words); + } + return new Function("str", f); + } + function all(array, predicate) { + for (var i = array.length; --i >= 0; ) if (!predicate(array[i])) return false; + return true; + } + function Dictionary() { + this._values = Object.create(null); + this._size = 0; + } + Dictionary.prototype = { + set: function(key, val) { + if (!this.has(key)) ++this._size; + this._values["$" + key] = val; + return this; + }, + add: function(key, val) { + if (this.has(key)) { + this.get(key).push(val); + } else { + this.set(key, [ val ]); + } + return this; + }, + get: function(key) { + return this._values["$" + key]; + }, + del: function(key) { + if (this.has(key)) { + --this._size; + delete this._values["$" + key]; + } + return this; + }, + has: function(key) { + return "$" + key in this._values; + }, + each: function(f) { + for (var i in this._values) f(this._values[i], i.substr(1)); + }, + size: function() { + return this._size; + }, + map: function(f) { + var ret = []; + for (var i in this._values) ret.push(f(this._values[i], i.substr(1))); + return ret; + } + }; + "use strict"; + function DEFNODE(type, props, methods, base) { + if (arguments.length < 4) base = AST_Node; + if (!props) props = []; else props = props.split(/\s+/); + var self_props = props; + if (base && base.PROPS) props = props.concat(base.PROPS); + var code = "return function AST_" + type + "(props){ if (props) { "; + for (var i = props.length; --i >= 0; ) { + code += "this." + props[i] + " = props." + props[i] + ";"; + } + var proto = base && new base(); + if (proto && proto.initialize || methods && methods.initialize) code += "this.initialize();"; + code += "}}"; + var ctor = new Function(code)(); + if (proto) { + ctor.prototype = proto; + ctor.BASE = base; + } + if (base) base.SUBCLASSES.push(ctor); + ctor.prototype.CTOR = ctor; + ctor.PROPS = props || null; + ctor.SELF_PROPS = self_props; + ctor.SUBCLASSES = []; + if (type) { + ctor.prototype.TYPE = ctor.TYPE = type; + } + if (methods) for (i in methods) if (methods.hasOwnProperty(i)) { + if (/^\$/.test(i)) { + ctor[i.substr(1)] = methods[i]; + } else { + ctor.prototype[i] = methods[i]; + } + } + ctor.DEFMETHOD = function(name, method) { + this.prototype[name] = method; + }; + return ctor; + } + var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", {}, null); + var AST_Node = DEFNODE("Node", "start end", { + clone: function() { + return new this.CTOR(this); + }, + $documentation: "Base class of all AST nodes", + $propdoc: { + start: "[AST_Token] The first token of this node", + end: "[AST_Token] The last token of this node" + }, + _walk: function(visitor) { + return visitor._visit(this); + }, + walk: function(visitor) { + return this._walk(visitor); + } + }, null); + AST_Node.warn_function = null; + AST_Node.warn = function(txt, props) { + if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props)); + }; + var AST_Statement = DEFNODE("Statement", null, { + $documentation: "Base class of all statements" + }); + var AST_Debugger = DEFNODE("Debugger", null, { + $documentation: "Represents a debugger statement" + }, AST_Statement); + var AST_Directive = DEFNODE("Directive", "value scope", { + $documentation: 'Represents a directive, like "use strict";', + $propdoc: { + value: "[string] The value of this directive as a plain string (it's not an AST_String!)", + scope: "[AST_Scope/S] The scope that this directive affects" + } + }, AST_Statement); + var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { + $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", + $propdoc: { + body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.body._walk(visitor); + }); + } + }, AST_Statement); + function walk_body(node, visitor) { + if (node.body instanceof AST_Statement) { + node.body._walk(visitor); + } else node.body.forEach(function(stat) { + stat._walk(visitor); + }); + } + var AST_Block = DEFNODE("Block", "body", { + $documentation: "A body of statements (usually bracketed)", + $propdoc: { + body: "[AST_Statement*] an array of statements" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + walk_body(this, visitor); + }); + } + }, AST_Statement); + var AST_BlockStatement = DEFNODE("BlockStatement", null, { + $documentation: "A block statement" + }, AST_Block); + var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { + $documentation: "The empty statement (empty block or simply a semicolon)", + _walk: function(visitor) { + return visitor._visit(this); + } + }, AST_Statement); + var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { + $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", + $propdoc: { + body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.body._walk(visitor); + }); + } + }, AST_Statement); + var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { + $documentation: "Statement with a label", + $propdoc: { + label: "[AST_Label] a label definition" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.label._walk(visitor); + this.body._walk(visitor); + }); + } + }, AST_StatementWithBody); + var AST_DWLoop = DEFNODE("DWLoop", "condition", { + $documentation: "Base class for do/while statements", + $propdoc: { + condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.condition._walk(visitor); + this.body._walk(visitor); + }); + } + }, AST_StatementWithBody); + var AST_Do = DEFNODE("Do", null, { + $documentation: "A `do` statement" + }, AST_DWLoop); + var AST_While = DEFNODE("While", null, { + $documentation: "A `while` statement" + }, AST_DWLoop); + var AST_For = DEFNODE("For", "init condition step", { + $documentation: "A `for` statement", + $propdoc: { + init: "[AST_Node?] the `for` initialization code, or null if empty", + condition: "[AST_Node?] the `for` termination clause, or null if empty", + step: "[AST_Node?] the `for` update clause, or null if empty" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + if (this.init) this.init._walk(visitor); + if (this.condition) this.condition._walk(visitor); + if (this.step) this.step._walk(visitor); + this.body._walk(visitor); + }); + } + }, AST_StatementWithBody); + var AST_ForIn = DEFNODE("ForIn", "init name object", { + $documentation: "A `for ... in` statement", + $propdoc: { + init: "[AST_Node] the `for/in` initialization code", + name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var", + object: "[AST_Node] the object that we're looping through" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.init._walk(visitor); + this.object._walk(visitor); + this.body._walk(visitor); + }); + } + }, AST_StatementWithBody); + var AST_With = DEFNODE("With", "expression", { + $documentation: "A `with` statement", + $propdoc: { + expression: "[AST_Node] the `with` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.expression._walk(visitor); + this.body._walk(visitor); + }); + } + }, AST_StatementWithBody); + var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { + $documentation: "Base class for all statements introducing a lexical scope", + $propdoc: { + directives: "[string*/S] an array of directives declared in this scope", + variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope", + functions: "[Object/S] like `variables`, but only lists function declarations", + uses_with: "[boolean/S] tells whether this scope uses the `with` statement", + uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`", + parent_scope: "[AST_Scope?/S] link to the parent scope", + enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", + cname: "[integer/S] current index for mangling variables (used internally by the mangler)" + } + }, AST_Block); + var AST_Toplevel = DEFNODE("Toplevel", "globals", { + $documentation: "The toplevel scope", + $propdoc: { + globals: "[Object/S] a map of name -> SymbolDef for all undeclared names" + }, + wrap_enclose: function(arg_parameter_pairs) { + var self = this; + var args = []; + var parameters = []; + arg_parameter_pairs.forEach(function(pair) { + var split = pair.split(":"); + args.push(split[0]); + parameters.push(split[1]); + }); + var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) { + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(self.body); + } + })); + return wrapped_tl; + }, + wrap_commonjs: function(name, export_all) { + var self = this; + var to_export = []; + if (export_all) { + self.figure_out_scope(); + self.walk(new TreeWalker(function(node) { + if (node instanceof AST_SymbolDeclaration && node.definition().global) { + if (!find_if(function(n) { + return n.name == node.name; + }, to_export)) to_export.push(node); + } + })); + } + var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) { + if (node instanceof AST_SimpleStatement) { + node = node.body; + if (node instanceof AST_String) switch (node.getValue()) { + case "$ORIG": + return MAP.splice(self.body); + + case "$EXPORTS": + var body = []; + to_export.forEach(function(sym) { + body.push(new AST_SimpleStatement({ + body: new AST_Assign({ + left: new AST_Sub({ + expression: new AST_SymbolRef({ + name: "exports" + }), + property: new AST_String({ + value: sym.name + }) + }), + operator: "=", + right: new AST_SymbolRef(sym) + }) + })); + }); + return MAP.splice(body); + } + } + })); + return wrapped_tl; + } + }, AST_Scope); + var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { + $documentation: "Base class for functions", + $propdoc: { + name: "[AST_SymbolDeclaration?] the name of this function", + argnames: "[AST_SymbolFunarg*] array of function arguments", + uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + if (this.name) this.name._walk(visitor); + this.argnames.forEach(function(arg) { + arg._walk(visitor); + }); + walk_body(this, visitor); + }); + } + }, AST_Scope); + var AST_Accessor = DEFNODE("Accessor", null, { + $documentation: "A setter/getter function" + }, AST_Lambda); + var AST_Function = DEFNODE("Function", null, { + $documentation: "A function expression" + }, AST_Lambda); + var AST_Defun = DEFNODE("Defun", null, { + $documentation: "A function definition" + }, AST_Lambda); + var AST_Jump = DEFNODE("Jump", null, { + $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" + }, AST_Statement); + var AST_Exit = DEFNODE("Exit", "value", { + $documentation: "Base class for “exits” (`return` and `throw`)", + $propdoc: { + value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" + }, + _walk: function(visitor) { + return visitor._visit(this, this.value && function() { + this.value._walk(visitor); + }); + } + }, AST_Jump); + var AST_Return = DEFNODE("Return", null, { + $documentation: "A `return` statement" + }, AST_Exit); + var AST_Throw = DEFNODE("Throw", null, { + $documentation: "A `throw` statement" + }, AST_Exit); + var AST_LoopControl = DEFNODE("LoopControl", "label", { + $documentation: "Base class for loop control statements (`break` and `continue`)", + $propdoc: { + label: "[AST_LabelRef?] the label, or null if none" + }, + _walk: function(visitor) { + return visitor._visit(this, this.label && function() { + this.label._walk(visitor); + }); + } + }, AST_Jump); + var AST_Break = DEFNODE("Break", null, { + $documentation: "A `break` statement" + }, AST_LoopControl); + var AST_Continue = DEFNODE("Continue", null, { + $documentation: "A `continue` statement" + }, AST_LoopControl); + var AST_If = DEFNODE("If", "condition alternative", { + $documentation: "A `if` statement", + $propdoc: { + condition: "[AST_Node] the `if` condition", + alternative: "[AST_Statement?] the `else` part, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.condition._walk(visitor); + this.body._walk(visitor); + if (this.alternative) this.alternative._walk(visitor); + }); + } + }, AST_StatementWithBody); + var AST_Switch = DEFNODE("Switch", "expression", { + $documentation: "A `switch` statement", + $propdoc: { + expression: "[AST_Node] the `switch` “discriminant”" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } + }, AST_Block); + var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { + $documentation: "Base class for `switch` branches" + }, AST_Block); + var AST_Default = DEFNODE("Default", null, { + $documentation: "A `default` switch branch" + }, AST_SwitchBranch); + var AST_Case = DEFNODE("Case", "expression", { + $documentation: "A `case` switch branch", + $propdoc: { + expression: "[AST_Node] the `case` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } + }, AST_SwitchBranch); + var AST_Try = DEFNODE("Try", "bcatch bfinally", { + $documentation: "A `try` statement", + $propdoc: { + bcatch: "[AST_Catch?] the catch block, or null if not present", + bfinally: "[AST_Finally?] the finally block, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + walk_body(this, visitor); + if (this.bcatch) this.bcatch._walk(visitor); + if (this.bfinally) this.bfinally._walk(visitor); + }); + } + }, AST_Block); + var AST_Catch = DEFNODE("Catch", "argname", { + $documentation: "A `catch` node; only makes sense as part of a `try` statement", + $propdoc: { + argname: "[AST_SymbolCatch] symbol for the exception" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.argname._walk(visitor); + walk_body(this, visitor); + }); + } + }, AST_Block); + var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" + }, AST_Block); + var AST_Definitions = DEFNODE("Definitions", "definitions", { + $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", + $propdoc: { + definitions: "[AST_VarDef*] array of variable definitions" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.definitions.forEach(function(def) { + def._walk(visitor); + }); + }); + } + }, AST_Statement); + var AST_Var = DEFNODE("Var", null, { + $documentation: "A `var` statement" + }, AST_Definitions); + var AST_Const = DEFNODE("Const", null, { + $documentation: "A `const` statement" + }, AST_Definitions); + var AST_VarDef = DEFNODE("VarDef", "name value", { + $documentation: "A variable declaration; only appears in a AST_Definitions node", + $propdoc: { + name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", + value: "[AST_Node?] initializer, or null of there's no initializer" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.name._walk(visitor); + if (this.value) this.value._walk(visitor); + }); + } + }); + var AST_Call = DEFNODE("Call", "expression args", { + $documentation: "A function call expression", + $propdoc: { + expression: "[AST_Node] expression to invoke as function", + args: "[AST_Node*] array of arguments" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.expression._walk(visitor); + this.args.forEach(function(arg) { + arg._walk(visitor); + }); + }); + } + }); + var AST_New = DEFNODE("New", null, { + $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" + }, AST_Call); + var AST_Seq = DEFNODE("Seq", "car cdr", { + $documentation: "A sequence expression (two comma-separated expressions)", + $propdoc: { + car: "[AST_Node] first element in sequence", + cdr: "[AST_Node] second element in sequence" + }, + $cons: function(x, y) { + var seq = new AST_Seq(x); + seq.car = x; + seq.cdr = y; + return seq; + }, + $from_array: function(array) { + if (array.length == 0) return null; + if (array.length == 1) return array[0].clone(); + var list = null; + for (var i = array.length; --i >= 0; ) { + list = AST_Seq.cons(array[i], list); + } + var p = list; + while (p) { + if (p.cdr && !p.cdr.cdr) { + p.cdr = p.cdr.car; + break; + } + p = p.cdr; + } + return list; + }, + to_array: function() { + var p = this, a = []; + while (p) { + a.push(p.car); + if (p.cdr && !(p.cdr instanceof AST_Seq)) { + a.push(p.cdr); + break; + } + p = p.cdr; + } + return a; + }, + add: function(node) { + var p = this; + while (p) { + if (!(p.cdr instanceof AST_Seq)) { + var cell = AST_Seq.cons(p.cdr, node); + return p.cdr = cell; + } + p = p.cdr; + } + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.car._walk(visitor); + if (this.cdr) this.cdr._walk(visitor); + }); + } + }); + var AST_PropAccess = DEFNODE("PropAccess", "expression property", { + $documentation: 'Base class for property access expressions, i.e. `a.foo` or `a["foo"]`', + $propdoc: { + expression: "[AST_Node] the “container” expression", + property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node" + } + }); + var AST_Dot = DEFNODE("Dot", null, { + $documentation: "A dotted property access expression", + _walk: function(visitor) { + return visitor._visit(this, function() { + this.expression._walk(visitor); + }); + } + }, AST_PropAccess); + var AST_Sub = DEFNODE("Sub", null, { + $documentation: 'Index-style property access, i.e. `a["foo"]`', + _walk: function(visitor) { + return visitor._visit(this, function() { + this.expression._walk(visitor); + this.property._walk(visitor); + }); + } + }, AST_PropAccess); + var AST_Unary = DEFNODE("Unary", "operator expression", { + $documentation: "Base class for unary expressions", + $propdoc: { + operator: "[string] the operator", + expression: "[AST_Node] expression that this unary operator applies to" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.expression._walk(visitor); + }); + } + }); + var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { + $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" + }, AST_Unary); + var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { + $documentation: "Unary postfix expression, i.e. `i++`" + }, AST_Unary); + var AST_Binary = DEFNODE("Binary", "left operator right", { + $documentation: "Binary expression, i.e. `a + b`", + $propdoc: { + left: "[AST_Node] left-hand side expression", + operator: "[string] the operator", + right: "[AST_Node] right-hand side expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.left._walk(visitor); + this.right._walk(visitor); + }); + } + }); + var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { + $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", + $propdoc: { + condition: "[AST_Node]", + consequent: "[AST_Node]", + alternative: "[AST_Node]" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.condition._walk(visitor); + this.consequent._walk(visitor); + this.alternative._walk(visitor); + }); + } + }); + var AST_Assign = DEFNODE("Assign", null, { + $documentation: "An assignment expression — `a = b + 5`" + }, AST_Binary); + var AST_Array = DEFNODE("Array", "elements", { + $documentation: "An array literal", + $propdoc: { + elements: "[AST_Node*] array of elements" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.elements.forEach(function(el) { + el._walk(visitor); + }); + }); + } + }); + var AST_Object = DEFNODE("Object", "properties", { + $documentation: "An object literal", + $propdoc: { + properties: "[AST_ObjectProperty*] array of properties" + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.properties.forEach(function(prop) { + prop._walk(visitor); + }); + }); + } + }); + var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { + $documentation: "Base class for literal object properties", + $propdoc: { + key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code", + value: "[AST_Node] property value. For setters and getters this is an AST_Function." + }, + _walk: function(visitor) { + return visitor._visit(this, function() { + this.value._walk(visitor); + }); + } + }); + var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { + $documentation: "A key: value object property" + }, AST_ObjectProperty); + var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { + $documentation: "An object setter property" + }, AST_ObjectProperty); + var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { + $documentation: "An object getter property" + }, AST_ObjectProperty); + var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { + $propdoc: { + name: "[string] name of this symbol", + scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", + thedef: "[SymbolDef/S] the definition of this symbol" + }, + $documentation: "Base class for all symbols" + }); + var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { + $documentation: "The name of a property accessor (setter/getter function)" + }, AST_Symbol); + var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { + $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", + $propdoc: { + init: "[AST_Node*/S] array of initializers for this declaration." + } + }, AST_Symbol); + var AST_SymbolVar = DEFNODE("SymbolVar", null, { + $documentation: "Symbol defining a variable" + }, AST_SymbolDeclaration); + var AST_SymbolConst = DEFNODE("SymbolConst", null, { + $documentation: "A constant declaration" + }, AST_SymbolDeclaration); + var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { + $documentation: "Symbol naming a function argument" + }, AST_SymbolVar); + var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { + $documentation: "Symbol defining a function" + }, AST_SymbolDeclaration); + var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { + $documentation: "Symbol naming a function expression" + }, AST_SymbolDeclaration); + var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { + $documentation: "Symbol naming the exception in catch" + }, AST_SymbolDeclaration); + var AST_Label = DEFNODE("Label", "references", { + $documentation: "Symbol naming a label (declaration)", + $propdoc: { + references: "[AST_LabelRef*] a list of nodes referring to this label" + } + }, AST_Symbol); + var AST_SymbolRef = DEFNODE("SymbolRef", null, { + $documentation: "Reference to some symbol (not definition/declaration)" + }, AST_Symbol); + var AST_LabelRef = DEFNODE("LabelRef", null, { + $documentation: "Reference to a label symbol" + }, AST_Symbol); + var AST_This = DEFNODE("This", null, { + $documentation: "The `this` symbol" + }, AST_Symbol); + var AST_Constant = DEFNODE("Constant", null, { + $documentation: "Base class for all constants", + getValue: function() { + return this.value; + } + }); + var AST_String = DEFNODE("String", "value", { + $documentation: "A string literal", + $propdoc: { + value: "[string] the contents of this string" + } + }, AST_Constant); + var AST_Number = DEFNODE("Number", "value", { + $documentation: "A number literal", + $propdoc: { + value: "[number] the numeric value" + } + }, AST_Constant); + var AST_RegExp = DEFNODE("RegExp", "value", { + $documentation: "A regexp literal", + $propdoc: { + value: "[RegExp] the actual regexp" + } + }, AST_Constant); + var AST_Atom = DEFNODE("Atom", null, { + $documentation: "Base class for atoms" + }, AST_Constant); + var AST_Null = DEFNODE("Null", null, { + $documentation: "The `null` atom", + value: null + }, AST_Atom); + var AST_NaN = DEFNODE("NaN", null, { + $documentation: "The impossible value", + value: 0 / 0 + }, AST_Atom); + var AST_Undefined = DEFNODE("Undefined", null, { + $documentation: "The `undefined` value", + value: function() {}() + }, AST_Atom); + var AST_Hole = DEFNODE("Hole", null, { + $documentation: "A hole in an array", + value: function() {}() + }, AST_Atom); + var AST_Infinity = DEFNODE("Infinity", null, { + $documentation: "The `Infinity` value", + value: 1 / 0 + }, AST_Atom); + var AST_Boolean = DEFNODE("Boolean", null, { + $documentation: "Base class for booleans" + }, AST_Atom); + var AST_False = DEFNODE("False", null, { + $documentation: "The `false` atom", + value: false + }, AST_Boolean); + var AST_True = DEFNODE("True", null, { + $documentation: "The `true` atom", + value: true + }, AST_Boolean); + function TreeWalker(callback) { + this.visit = callback; + this.stack = []; + } + TreeWalker.prototype = { + _visit: function(node, descend) { + this.stack.push(node); + var ret = this.visit(node, descend ? function() { + descend.call(node); + } : noop); + if (!ret && descend) { + descend.call(node); + } + this.stack.pop(); + return ret; + }, + parent: function(n) { + return this.stack[this.stack.length - 2 - (n || 0)]; + }, + push: function(node) { + this.stack.push(node); + }, + pop: function() { + return this.stack.pop(); + }, + self: function() { + return this.stack[this.stack.length - 1]; + }, + find_parent: function(type) { + var stack = this.stack; + for (var i = stack.length; --i >= 0; ) { + var x = stack[i]; + if (x instanceof type) return x; + } + }, + has_directive: function(type) { + return this.find_parent(AST_Scope).has_directive(type); + }, + in_boolean_context: function() { + var stack = this.stack; + var i = stack.length, self = stack[--i]; + while (i > 0) { + var p = stack[--i]; + if (p instanceof AST_If && p.condition === self || p instanceof AST_Conditional && p.condition === self || p instanceof AST_DWLoop && p.condition === self || p instanceof AST_For && p.condition === self || p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) { + return true; + } + if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) return false; + self = p; + } + }, + loopcontrol_target: function(label) { + var stack = this.stack; + if (label) { + for (var i = stack.length; --i >= 0; ) { + var x = stack[i]; + if (x instanceof AST_LabeledStatement && x.label.name == label.name) { + return x.body; + } + } + } else { + for (var i = stack.length; --i >= 0; ) { + var x = stack[i]; + if (x instanceof AST_Switch || x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) return x; + } + } + } + }; + "use strict"; + var KEYWORDS = "break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with"; + var KEYWORDS_ATOM = "false null true"; + var RESERVED_WORDS = "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile" + " " + KEYWORDS_ATOM + " " + KEYWORDS; + var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case"; + KEYWORDS = makePredicate(KEYWORDS); + RESERVED_WORDS = makePredicate(RESERVED_WORDS); + KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); + KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); + var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); + var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; + var RE_OCT_NUMBER = /^0[0-7]+$/; + var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + var OPERATORS = makePredicate([ "in", "instanceof", "typeof", "new", "void", "delete", "++", "--", "+", "-", "!", "~", "&", "|", "^", "*", "/", "%", ">>", "<<", ">>>", "<", ">", "<=", ">=", "==", "===", "!=", "!==", "?", "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=", "&&", "||" ]); + var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); + var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:")); + var PUNC_CHARS = makePredicate(characters("[]{}(),;:")); + var REGEXP_MODIFIERS = makePredicate(characters("gmsiy")); + var UNICODE = { + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") + }; + function is_letter(code) { + return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 170 && UNICODE.letter.test(String.fromCharCode(code)); + } + function is_digit(code) { + return code >= 48 && code <= 57; + } + function is_alphanumeric_char(code) { + return is_digit(code) || is_letter(code); + } + function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); + } + function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); + } + function is_identifier(name) { + return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); + } + function is_identifier_start(code) { + return code == 36 || code == 95 || is_letter(code); + } + function is_identifier_char(ch) { + var code = ch.charCodeAt(0); + return is_identifier_start(code) || is_digit(code) || code == 8204 || code == 8205 || is_unicode_combining_mark(ch) || is_unicode_connector_punctuation(ch); + } + function is_identifier_string(str) { + var i = str.length; + if (i == 0) return false; + if (is_digit(str.charCodeAt(0))) return false; + while (--i >= 0) { + if (!is_identifier_char(str.charAt(i))) return false; + } + return true; + } + function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } + } + function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + this.stack = new Error().stack; + } + JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; + }; + function js_error(message, filename, line, col, pos) { + throw new JS_Parse_Error(message, line, col, pos); + } + function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); + } + var EX_EOF = {}; + function tokenizer($TEXT, filename) { + var S = { + text: $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ""), + filename: filename, + pos: 0, + tokpos: 0, + line: 1, + tokline: 0, + col: 0, + tokcol: 0, + newline_before: false, + regex_allowed: false, + comments_before: [] + }; + function peek() { + return S.text.charAt(S.pos); + } + function next(signal_eof, in_string) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) throw EX_EOF; + if (ch == "\n") { + S.newline_before = S.newline_before || !in_string; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + } + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + } + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + } + function token(type, value, is_comment) { + S.regex_allowed = type == "operator" && !UNARY_POSTFIX(value) || type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value) || type == "punc" && PUNC_BEFORE_EXPRESSION(value); + var ret = { + type: type, + value: value, + line: S.tokline, + col: S.tokcol, + pos: S.tokpos, + endpos: S.pos, + nlb: S.newline_before, + file: filename + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + for (var i = 0, len = ret.comments_before.length; i < len; i++) { + ret.nlb = ret.nlb || ret.comments_before[i].nlb; + } + } + S.newline_before = false; + return new AST_Token(ret); + } + function skip_whitespace() { + while (WHITESPACE_CHARS(peek())) next(); + } + function read_while(pred) { + var ret = "", ch, i = 0; + while ((ch = peek()) && pred(ch, i++)) ret += next(); + return ret; + } + function parse_error(err) { + js_error(err, filename, S.tokline, S.tokcol, S.tokpos); + } + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i) { + var code = ch.charCodeAt(0); + switch (code) { + case 120: + case 88: + return has_x ? false : has_x = true; + + case 101: + case 69: + return has_x ? true : has_e ? false : has_e = after_e = true; + + case 45: + return after_e || i == 0 && !prefix; + + case 43: + return after_e; + + case after_e = false, 46: + return !has_dot && !has_x && !has_e ? has_dot = true : false; + } + return is_alphanumeric_char(code); + }); + if (prefix) num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + } + function read_escaped_char(in_string) { + var ch = next(true, in_string); + switch (ch.charCodeAt(0)) { + case 110: + return "\n"; + + case 114: + return "\r"; + + case 116: + return " "; + + case 98: + return "\b"; + + case 118: + return " "; + + case 102: + return "\f"; + + case 48: + return "\x00"; + + case 120: + return String.fromCharCode(hex_bytes(2)); + + case 117: + return String.fromCharCode(hex_bytes(4)); + + case 10: + return ""; + + default: + return ch; + } + } + function hex_bytes(n) { + var num = 0; + for (;n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) parse_error("Invalid hex-character pattern in string"); + num = num << 4 | digit; + } + return num; + } + var read_string = with_eof_error("Unterminated string constant", function() { + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") { + var octal_len = 0, first = null; + ch = read_while(function(ch) { + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } else if (first <= "3" && octal_len <= 2) return ++octal_len; else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); else ch = read_escaped_char(true); + } else if (ch == quote) break; + ret += ch; + } + return token("string", ret); + }); + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + } + var read_multiline_comment = with_eof_error("Unterminated multiline comment", function() { + next(); + var i = find("*/", true); + var text = S.text.substring(S.pos, i); + var a = text.split("\n"), n = a.length; + S.pos = i + 2; + S.line += n - 1; + if (n > 1) S.col = a[n - 1].length; else S.col += a[n - 1].length; + S.col += 2; + S.newline_before = S.newline_before || text.indexOf("\n") >= 0; + return token("comment2", text, true); + }); + function read_name() { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, next(); else if (is_identifier_char(ch)) name += next(); else break; + } else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (KEYWORDS(name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + return name; + } + var read_regexp = with_eof_error("Unterminated regular expression", function(regexp) { + var prev_backslash = false, ch, in_class = false; + while (ch = next(true)) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", new RegExp(regexp, mods)); + }); + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (OPERATORS(bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + } + return token("operator", grow(prefix || next())); + } + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp("") : read_operator("/"); + } + function handle_dot() { + next(); + return is_digit(peek().charCodeAt(0)) ? read_num(".") : token("punc", "."); + } + function read_word() { + var word = read_name(); + return KEYWORDS_ATOM(word) ? token("atom", word) : !KEYWORDS(word) ? token("name", word) : OPERATORS(word) ? token("operator", word) : token("keyword", word); + } + function with_eof_error(eof_error, cont) { + return function(x) { + try { + return cont(x); + } catch (ex) { + if (ex === EX_EOF) parse_error(eof_error); else throw ex; + } + }; + } + function next_token(force_regexp) { + if (force_regexp != null) return read_regexp(force_regexp); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: + case 39: + return read_string(); + + case 46: + return handle_dot(); + + case 47: + return handle_slash(); + } + if (is_digit(code)) return read_num(); + if (PUNC_CHARS(ch)) return token("punc", next()); + if (OPERATOR_CHARS(ch)) return read_operator(); + if (code == 92 || is_identifier_start(code)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + } + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + return next_token; + } + var UNARY_PREFIX = makePredicate([ "typeof", "void", "delete", "--", "++", "!", "~", "-", "+" ]); + var UNARY_POSTFIX = makePredicate([ "--", "++" ]); + var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); + var PRECEDENCE = function(a, ret) { + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; + }([ [ "||" ], [ "&&" ], [ "|" ], [ "^" ], [ "&" ], [ "==", "===", "!=", "!==" ], [ "<", ">", "<=", ">=", "in", "instanceof" ], [ ">>", "<<", ">>>" ], [ "+", "-" ], [ "*", "/", "%" ] ], {}); + var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + function parse($TEXT, options) { + options = defaults(options, { + strict: false, + filename: null, + toplevel: null, + expression: false + }); + var S = { + input: typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT, + token: null, + prev: null, + peeked: null, + in_function: 0, + in_directives: true, + in_loop: 0, + labels: [] + }; + S.token = next(); + function is(type, value) { + return is_token(S.token, type, value); + } + function peek() { + return S.peeked || (S.peeked = S.input()); + } + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && (S.token.type == "string" || is("punc", ";")); + return S.token; + } + function prev() { + return S.prev; + } + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, ctx.filename, line != null ? line : ctx.tokline, col != null ? col : ctx.tokcol, pos != null ? pos : ctx.tokpos); + } + function token_error(token, msg) { + croak(msg, token.line, token.col); + } + function unexpected(token) { + if (token == null) token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + } + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); + } + function expect(punc) { + return expect_token("punc", punc); + } + function can_insert_semicolon() { + return !options.strict && (S.token.nlb || is("eof") || is("punc", "}")); + } + function semicolon() { + if (is("punc", ";")) next(); else if (!can_insert_semicolon()) unexpected(); + } + function parenthesised() { + expect("("); + var exp = expression(true); + expect(")"); + return exp; + } + function embed_tokens(parser) { + return function() { + var start = S.token; + var expr = parser(); + var end = prev(); + expr.start = start; + expr.end = end; + return expr; + }; + } + var statement = embed_tokens(function() { + var tmp; + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); + } + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + if (dir && stat.body instanceof AST_String && !is("punc", ",")) return new AST_Directive({ + value: stat.body.value + }); + return stat; + + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") ? labeled_statement() : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return new AST_BlockStatement({ + start: S.token, + body: block_(), + end: prev() + }); + + case "[": + case "(": + return simple_statement(); + + case ";": + next(); + return new AST_EmptyStatement(); + + default: + unexpected(); + } + + case "keyword": + switch (tmp = S.token.value, next(), tmp) { + case "break": + return break_cont(AST_Break); + + case "continue": + return break_cont(AST_Continue); + + case "debugger": + semicolon(); + return new AST_Debugger(); + + case "do": + return new AST_Do({ + body: in_loop(statement), + condition: (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), + tmp) + }); + + case "while": + return new AST_While({ + condition: parenthesised(), + body: in_loop(statement) + }); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) croak("'return' outside of function"); + return new AST_Return({ + value: is("punc", ";") ? (next(), null) : can_insert_semicolon() ? null : (tmp = expression(true), + semicolon(), tmp) + }); + + case "switch": + return new AST_Switch({ + expression: parenthesised(), + body: in_loop(switch_body_) + }); + + case "throw": + if (S.token.nlb) croak("Illegal newline after 'throw'"); + return new AST_Throw({ + value: (tmp = expression(true), semicolon(), tmp) + }); + + case "try": + return try_(); + + case "var": + return tmp = var_(), semicolon(), tmp; + + case "const": + return tmp = const_(), semicolon(), tmp; + + case "with": + return new AST_With({ + expression: parenthesised(), + body: statement() + }); + + default: + unexpected(); + } + } + }); + function labeled_statement() { + var label = as_symbol(AST_Label); + if (find_if(function(l) { + return l.name == label.name; + }, S.labels)) { + croak("Label " + label.name + " defined twice"); + } + expect(":"); + S.labels.push(label); + var stat = statement(); + S.labels.pop(); + return new AST_LabeledStatement({ + body: stat, + label: label + }); + } + function simple_statement(tmp) { + return new AST_SimpleStatement({ + body: (tmp = expression(true), semicolon(), tmp) + }); + } + function break_cont(type) { + var label = null; + if (!can_insert_semicolon()) { + label = as_symbol(AST_LabelRef, true); + } + if (label != null) { + if (!find_if(function(l) { + return l.name == label.name; + }, S.labels)) croak("Undefined label " + label.name); + } else if (S.in_loop == 0) croak(type.TYPE + " not inside a loop or switch"); + semicolon(); + return new type({ + label: label + }); + } + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") ? (next(), var_(true)) : expression(true, true); + if (is("operator", "in")) { + if (init instanceof AST_Var && init.definitions.length > 1) croak("Only one variable declaration allowed in for..in loop"); + next(); + return for_in(init); + } + } + return regular_for(init); + } + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(true); + expect(";"); + var step = is("punc", ")") ? null : expression(true); + expect(")"); + return new AST_For({ + init: init, + condition: test, + step: step, + body: in_loop(statement) + }); + } + function for_in(init) { + var lhs = init instanceof AST_Var ? init.definitions[0].name : null; + var obj = expression(true); + expect(")"); + return new AST_ForIn({ + init: init, + name: lhs, + object: obj, + body: in_loop(statement) + }); + } + var function_ = function(in_statement, ctor) { + var is_accessor = ctor === AST_Accessor; + var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : is_accessor ? AST_SymbolAccessor : AST_SymbolLambda) : is_accessor && (is("string") || is("num")) ? as_atom_node() : null; + if (in_statement && !name) unexpected(); + expect("("); + if (!ctor) ctor = in_statement ? AST_Defun : AST_Function; + return new ctor({ + name: name, + argnames: function(first, a) { + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + a.push(as_symbol(AST_SymbolFunarg)); + } + next(); + return a; + }(true, []), + body: function(loop, labels) { + ++S.in_function; + S.in_directives = true; + S.in_loop = 0; + S.labels = []; + var a = block_(); + --S.in_function; + S.in_loop = loop; + S.labels = labels; + return a; + }(S.in_loop, S.labels) + }); + }; + function if_() { + var cond = parenthesised(), body = statement(), belse = null; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return new AST_If({ + condition: cond, + body: body, + alternative: belse + }); + } + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + } + function switch_body_() { + expect("{"); + var a = [], cur = null, branch = null, tmp; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Case({ + start: (tmp = S.token, next(), tmp), + expression: expression(true), + body: cur + }); + a.push(branch); + expect(":"); + } else if (is("keyword", "default")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Default({ + start: (tmp = S.token, next(), expect(":"), tmp), + body: cur + }); + a.push(branch); + } else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + if (branch) branch.end = prev(); + next(); + return a; + } + function try_() { + var body = block_(), bcatch = null, bfinally = null; + if (is("keyword", "catch")) { + var start = S.token; + next(); + expect("("); + var name = as_symbol(AST_SymbolCatch); + expect(")"); + bcatch = new AST_Catch({ + start: start, + argname: name, + body: block_(), + end: prev() + }); + } + if (is("keyword", "finally")) { + var start = S.token; + next(); + bfinally = new AST_Finally({ + start: start, + body: block_(), + end: prev() + }); + } + if (!bcatch && !bfinally) croak("Missing catch/finally blocks"); + return new AST_Try({ + body: body, + bcatch: bcatch, + bfinally: bfinally + }); + } + function vardefs(no_in, in_const) { + var a = []; + for (;;) { + a.push(new AST_VarDef({ + start: S.token, + name: as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), + value: is("operator", "=") ? (next(), expression(false, no_in)) : null, + end: prev() + })); + if (!is("punc", ",")) break; + next(); + } + return a; + } + var var_ = function(no_in) { + return new AST_Var({ + start: prev(), + definitions: vardefs(no_in, false), + end: prev() + }); + }; + var const_ = function() { + return new AST_Const({ + start: prev(), + definitions: vardefs(false, true), + end: prev() + }); + }; + var new_ = function() { + var start = S.token; + expect_token("operator", "new"); + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(new AST_New({ + start: start, + expression: newexp, + args: args, + end: prev() + }), true); + }; + function as_atom_node() { + var tok = S.token, ret; + switch (tok.type) { + case "name": + return as_symbol(AST_SymbolRef); + + case "num": + ret = new AST_Number({ + start: tok, + end: tok, + value: tok.value + }); + break; + + case "string": + ret = new AST_String({ + start: tok, + end: tok, + value: tok.value + }); + break; + + case "regexp": + ret = new AST_RegExp({ + start: tok, + end: tok, + value: tok.value + }); + break; + + case "atom": + switch (tok.value) { + case "false": + ret = new AST_False({ + start: tok, + end: tok + }); + break; + + case "true": + ret = new AST_True({ + start: tok, + end: tok + }); + break; + + case "null": + ret = new AST_Null({ + start: tok, + end: tok + }); + break; + } + break; + } + next(); + return ret; + } + var expr_atom = function(allow_calls) { + if (is("operator", "new")) { + return new_(); + } + var start = S.token; + if (is("punc")) { + switch (start.value) { + case "(": + next(); + var ex = expression(true); + ex.start = start; + ex.end = S.token; + expect(")"); + return subscripts(ex, allow_calls); + + case "[": + return subscripts(array_(), allow_calls); + + case "{": + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + var func = function_(false); + func.start = start; + func.end = prev(); + return subscripts(func, allow_calls); + } + if (ATOMIC_START_TOKEN[S.token.type]) { + return subscripts(as_atom_node(), allow_calls); + } + unexpected(); + }; + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push(new AST_Hole({ + start: S.token, + end: S.token + })); + } else { + a.push(expression(false)); + } + } + next(); + return a; + } + var array_ = embed_tokens(function() { + expect("["); + return new AST_Array({ + elements: expr_list("]", !options.strict, true) + }); + }); + var object_ = embed_tokens(function() { + expect("{"); + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!options.strict && is("punc", "}")) break; + var start = S.token; + var type = start.type; + var name = as_property_name(); + if (type == "name" && !is("punc", ":")) { + if (name == "get") { + a.push(new AST_ObjectGetter({ + start: start, + key: name, + value: function_(false, AST_Accessor), + end: prev() + })); + continue; + } + if (name == "set") { + a.push(new AST_ObjectSetter({ + start: start, + key: name, + value: function_(false, AST_Accessor), + end: prev() + })); + continue; + } + } + expect(":"); + a.push(new AST_ObjectKeyVal({ + start: start, + key: name, + value: expression(false), + end: prev() + })); + } + next(); + return new AST_Object({ + properties: a + }); + }); + function as_property_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "num": + case "string": + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + + default: + unexpected(); + } + } + function as_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + + default: + unexpected(); + } + } + function as_symbol(type, noerror) { + if (!is("name")) { + if (!noerror) croak("Name expected"); + return null; + } + var name = S.token.value; + var sym = new (name == "this" ? AST_This : type)({ + name: String(S.token.value), + start: S.token, + end: S.token + }); + next(); + return sym; + } + var subscripts = function(expr, allow_calls) { + var start = expr.start; + if (is("punc", ".")) { + next(); + return subscripts(new AST_Dot({ + start: start, + expression: expr, + property: as_name(), + end: prev() + }), allow_calls); + } + if (is("punc", "[")) { + next(); + var prop = expression(true); + expect("]"); + return subscripts(new AST_Sub({ + start: start, + expression: expr, + property: prop, + end: prev() + }), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(new AST_Call({ + start: start, + expression: expr, + args: expr_list(")"), + end: prev() + }), true); + } + return expr; + }; + var maybe_unary = function(allow_calls) { + var start = S.token; + if (is("operator") && UNARY_PREFIX(start.value)) { + next(); + var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); + ex.start = start; + ex.end = prev(); + return ex; + } + var val = expr_atom(allow_calls); + while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { + val = make_unary(AST_UnaryPostfix, S.token.value, val); + val.start = start; + val.end = S.token; + next(); + } + return val; + }; + function make_unary(ctor, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) croak("Invalid use of " + op + " operator"); + return new ctor({ + operator: op, + expression: expr + }); + } + var expr_op = function(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(new AST_Binary({ + start: left.start, + left: left, + operator: op, + right: right, + end: right.end + }), min_prec, no_in); + } + return left; + }; + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + } + var maybe_conditional = function(no_in) { + var start = S.token; + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return new AST_Conditional({ + start: start, + condition: expr, + consequent: yes, + alternative: expression(false, no_in), + end: peek() + }); + } + return expr; + }; + function is_assignable(expr) { + if (!options.strict) return true; + if (expr instanceof AST_This) return false; + return expr instanceof AST_PropAccess || expr instanceof AST_Symbol; + } + var maybe_assign = function(no_in) { + var start = S.token; + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && ASSIGNMENT(val)) { + if (is_assignable(left)) { + next(); + return new AST_Assign({ + start: start, + left: left, + operator: val, + right: maybe_assign(no_in), + end: prev() + }); + } + croak("Invalid assignment"); + } + return left; + }; + var expression = function(commas, no_in) { + var start = S.token; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return new AST_Seq({ + start: start, + car: expr, + cdr: expression(true, no_in), + end: peek() + }); + } + return expr; + }; + function in_loop(cont) { + ++S.in_loop; + var ret = cont(); + --S.in_loop; + return ret; + } + if (options.expression) { + return expression(true); + } + return function() { + var start = S.token; + var body = []; + while (!is("eof")) body.push(statement()); + var end = prev(); + var toplevel = options.toplevel; + if (toplevel) { + toplevel.body = toplevel.body.concat(body); + toplevel.end = end; + } else { + toplevel = new AST_Toplevel({ + start: start, + body: body, + end: end + }); + } + return toplevel; + }(); + } + "use strict"; + function TreeTransformer(before, after) { + TreeWalker.call(this); + this.before = before; + this.after = after; + } + TreeTransformer.prototype = new TreeWalker(); + (function(undefined) { + function _(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list) { + var x, y; + tw.push(this); + if (tw.before) x = tw.before(this, descend, in_list); + if (x === undefined) { + if (!tw.after) { + x = this; + descend(x, tw); + } else { + tw.stack[tw.stack.length - 1] = x = this.clone(); + descend(x, tw); + y = tw.after(x, in_list); + if (y !== undefined) x = y; + } + } + tw.pop(); + return x; + }); + } + function do_list(list, tw) { + return MAP(list, function(node) { + return node.transform(tw, true); + }); + } + _(AST_Node, noop); + _(AST_LabeledStatement, function(self, tw) { + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + _(AST_SimpleStatement, function(self, tw) { + self.body = self.body.transform(tw); + }); + _(AST_Block, function(self, tw) { + self.body = do_list(self.body, tw); + }); + _(AST_DWLoop, function(self, tw) { + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + _(AST_For, function(self, tw) { + if (self.init) self.init = self.init.transform(tw); + if (self.condition) self.condition = self.condition.transform(tw); + if (self.step) self.step = self.step.transform(tw); + self.body = self.body.transform(tw); + }); + _(AST_ForIn, function(self, tw) { + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + _(AST_With, function(self, tw) { + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + _(AST_Exit, function(self, tw) { + if (self.value) self.value = self.value.transform(tw); + }); + _(AST_LoopControl, function(self, tw) { + if (self.label) self.label = self.label.transform(tw); + }); + _(AST_If, function(self, tw) { + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + if (self.alternative) self.alternative = self.alternative.transform(tw); + }); + _(AST_Switch, function(self, tw) { + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + _(AST_Case, function(self, tw) { + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + _(AST_Try, function(self, tw) { + self.body = do_list(self.body, tw); + if (self.bcatch) self.bcatch = self.bcatch.transform(tw); + if (self.bfinally) self.bfinally = self.bfinally.transform(tw); + }); + _(AST_Catch, function(self, tw) { + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + _(AST_Definitions, function(self, tw) { + self.definitions = do_list(self.definitions, tw); + }); + _(AST_VarDef, function(self, tw) { + self.name = self.name.transform(tw); + if (self.value) self.value = self.value.transform(tw); + }); + _(AST_Lambda, function(self, tw) { + if (self.name) self.name = self.name.transform(tw); + self.argnames = do_list(self.argnames, tw); + self.body = do_list(self.body, tw); + }); + _(AST_Call, function(self, tw) { + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + _(AST_Seq, function(self, tw) { + self.car = self.car.transform(tw); + self.cdr = self.cdr.transform(tw); + }); + _(AST_Dot, function(self, tw) { + self.expression = self.expression.transform(tw); + }); + _(AST_Sub, function(self, tw) { + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + _(AST_Unary, function(self, tw) { + self.expression = self.expression.transform(tw); + }); + _(AST_Binary, function(self, tw) { + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + _(AST_Conditional, function(self, tw) { + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + _(AST_Array, function(self, tw) { + self.elements = do_list(self.elements, tw); + }); + _(AST_Object, function(self, tw) { + self.properties = do_list(self.properties, tw); + }); + _(AST_ObjectProperty, function(self, tw) { + self.value = self.value.transform(tw); + }); + })(); + "use strict"; + function SymbolDef(scope, index, orig) { + this.name = orig.name; + this.orig = [ orig ]; + this.scope = scope; + this.references = []; + this.global = false; + this.mangled_name = null; + this.undeclared = false; + this.constant = false; + this.index = index; + } + SymbolDef.prototype = { + unmangleable: function(options) { + return this.global && !(options && options.toplevel) || this.undeclared || !(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with); + }, + mangle: function(options) { + if (!this.mangled_name && !this.unmangleable(options)) { + var s = this.scope; + if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8) s = s.parent_scope; + this.mangled_name = s.next_mangled(options); + } + } + }; + AST_Toplevel.DEFMETHOD("figure_out_scope", function() { + var self = this; + var scope = self.parent_scope = null; + var labels = new Dictionary(); + var nesting = 0; + var tw = new TreeWalker(function(node, descend) { + if (node instanceof AST_Scope) { + node.init_scope_vars(nesting); + var save_scope = node.parent_scope = scope; + var save_labels = labels; + ++nesting; + scope = node; + labels = new Dictionary(); + descend(); + labels = save_labels; + scope = save_scope; + --nesting; + return true; + } + if (node instanceof AST_Directive) { + node.scope = scope; + push_uniq(scope.directives, node.value); + return true; + } + if (node instanceof AST_With) { + for (var s = scope; s; s = s.parent_scope) s.uses_with = true; + return; + } + if (node instanceof AST_LabeledStatement) { + var l = node.label; + if (labels.has(l.name)) throw new Error(string_template("Label {name} defined twice", l)); + labels.set(l.name, l); + descend(); + labels.del(l.name); + return true; + } + if (node instanceof AST_Symbol) { + node.scope = scope; + } + if (node instanceof AST_Label) { + node.thedef = node; + node.init_scope_vars(); + } + if (node instanceof AST_SymbolLambda) { + scope.def_function(node); + } else if (node instanceof AST_SymbolDefun) { + (node.scope = scope.parent_scope).def_function(node); + } else if (node instanceof AST_SymbolVar || node instanceof AST_SymbolConst) { + var def = scope.def_variable(node); + def.constant = node instanceof AST_SymbolConst; + def.init = tw.parent().value; + } else if (node instanceof AST_SymbolCatch) { + scope.def_variable(node); + } + if (node instanceof AST_LabelRef) { + var sym = labels.get(node.name); + if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", { + name: node.name, + line: node.start.line, + col: node.start.col + })); + node.thedef = sym; + } + }); + self.walk(tw); + var func = null; + var globals = self.globals = new Dictionary(); + var tw = new TreeWalker(function(node, descend) { + if (node instanceof AST_Lambda) { + var prev_func = func; + func = node; + descend(); + func = prev_func; + return true; + } + if (node instanceof AST_LabelRef) { + node.reference(); + return true; + } + if (node instanceof AST_SymbolRef) { + var name = node.name; + var sym = node.scope.find_variable(name); + if (!sym) { + var g; + if (globals.has(name)) { + g = globals.get(name); + } else { + g = new SymbolDef(self, globals.size(), node); + g.undeclared = true; + g.global = true; + globals.set(name, g); + } + node.thedef = g; + if (name == "eval" && tw.parent() instanceof AST_Call) { + for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) s.uses_eval = true; + } + if (name == "arguments") { + func.uses_arguments = true; + } + } else { + node.thedef = sym; + } + node.reference(); + return true; + } + }); + self.walk(tw); + }); + AST_Scope.DEFMETHOD("init_scope_vars", function(nesting) { + this.directives = []; + this.variables = new Dictionary(); + this.functions = new Dictionary(); + this.uses_with = false; + this.uses_eval = false; + this.parent_scope = null; + this.enclosed = []; + this.cname = -1; + this.nesting = nesting; + }); + AST_Scope.DEFMETHOD("strict", function() { + return this.has_directive("use strict"); + }); + AST_Lambda.DEFMETHOD("init_scope_vars", function() { + AST_Scope.prototype.init_scope_vars.apply(this, arguments); + this.uses_arguments = false; + }); + AST_SymbolRef.DEFMETHOD("reference", function() { + var def = this.definition(); + def.references.push(this); + var s = this.scope; + while (s) { + push_uniq(s.enclosed, def); + if (s === def.scope) break; + s = s.parent_scope; + } + this.frame = this.scope.nesting - def.scope.nesting; + }); + AST_Label.DEFMETHOD("init_scope_vars", function() { + this.references = []; + }); + AST_LabelRef.DEFMETHOD("reference", function() { + this.thedef.references.push(this); + }); + AST_Scope.DEFMETHOD("find_variable", function(name) { + if (name instanceof AST_Symbol) name = name.name; + return this.variables.get(name) || this.parent_scope && this.parent_scope.find_variable(name); + }); + AST_Scope.DEFMETHOD("has_directive", function(value) { + return this.parent_scope && this.parent_scope.has_directive(value) || (this.directives.indexOf(value) >= 0 ? this : null); + }); + AST_Scope.DEFMETHOD("def_function", function(symbol) { + this.functions.set(symbol.name, this.def_variable(symbol)); + }); + AST_Scope.DEFMETHOD("def_variable", function(symbol) { + var def; + if (!this.variables.has(symbol.name)) { + def = new SymbolDef(this, this.variables.size(), symbol); + this.variables.set(symbol.name, def); + def.global = !this.parent_scope; + } else { + def = this.variables.get(symbol.name); + def.orig.push(symbol); + } + return symbol.thedef = def; + }); + AST_Scope.DEFMETHOD("next_mangled", function(options) { + var ext = this.enclosed; + out: while (true) { + var m = base54(++this.cname); + if (!is_identifier(m)) continue; + for (var i = ext.length; --i >= 0; ) { + var sym = ext[i]; + var name = sym.mangled_name || sym.unmangleable(options) && sym.name; + if (m == name) continue out; + } + return m; + } + }); + AST_Scope.DEFMETHOD("references", function(sym) { + if (sym instanceof AST_Symbol) sym = sym.definition(); + return this.enclosed.indexOf(sym) < 0 ? null : sym; + }); + AST_Symbol.DEFMETHOD("unmangleable", function(options) { + return this.definition().unmangleable(options); + }); + AST_SymbolAccessor.DEFMETHOD("unmangleable", function() { + return true; + }); + AST_Label.DEFMETHOD("unmangleable", function() { + return false; + }); + AST_Symbol.DEFMETHOD("unreferenced", function() { + return this.definition().references.length == 0 && !(this.scope.uses_eval || this.scope.uses_with); + }); + AST_Symbol.DEFMETHOD("undeclared", function() { + return this.definition().undeclared; + }); + AST_LabelRef.DEFMETHOD("undeclared", function() { + return false; + }); + AST_Label.DEFMETHOD("undeclared", function() { + return false; + }); + AST_Symbol.DEFMETHOD("definition", function() { + return this.thedef; + }); + AST_Symbol.DEFMETHOD("global", function() { + return this.definition().global; + }); + AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) { + return defaults(options, { + except: [], + eval: false, + sort: false, + toplevel: false, + screw_ie8: false + }); + }); + AST_Toplevel.DEFMETHOD("mangle_names", function(options) { + options = this._default_mangler_options(options); + var lname = -1; + var to_mangle = []; + var tw = new TreeWalker(function(node, descend) { + if (node instanceof AST_LabeledStatement) { + var save_nesting = lname; + descend(); + lname = save_nesting; + return true; + } + if (node instanceof AST_Scope) { + var p = tw.parent(), a = []; + node.variables.each(function(symbol) { + if (options.except.indexOf(symbol.name) < 0) { + a.push(symbol); + } + }); + if (options.sort) a.sort(function(a, b) { + return b.references.length - a.references.length; + }); + to_mangle.push.apply(to_mangle, a); + return; + } + if (node instanceof AST_Label) { + var name; + do name = base54(++lname); while (!is_identifier(name)); + node.mangled_name = name; + return true; + } + }); + this.walk(tw); + to_mangle.forEach(function(def) { + def.mangle(options); + }); + }); + AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) { + options = this._default_mangler_options(options); + var tw = new TreeWalker(function(node) { + if (node instanceof AST_Constant) base54.consider(node.print_to_string()); else if (node instanceof AST_Return) base54.consider("return"); else if (node instanceof AST_Throw) base54.consider("throw"); else if (node instanceof AST_Continue) base54.consider("continue"); else if (node instanceof AST_Break) base54.consider("break"); else if (node instanceof AST_Debugger) base54.consider("debugger"); else if (node instanceof AST_Directive) base54.consider(node.value); else if (node instanceof AST_While) base54.consider("while"); else if (node instanceof AST_Do) base54.consider("do while"); else if (node instanceof AST_If) { + base54.consider("if"); + if (node.alternative) base54.consider("else"); + } else if (node instanceof AST_Var) base54.consider("var"); else if (node instanceof AST_Const) base54.consider("const"); else if (node instanceof AST_Lambda) base54.consider("function"); else if (node instanceof AST_For) base54.consider("for"); else if (node instanceof AST_ForIn) base54.consider("for in"); else if (node instanceof AST_Switch) base54.consider("switch"); else if (node instanceof AST_Case) base54.consider("case"); else if (node instanceof AST_Default) base54.consider("default"); else if (node instanceof AST_With) base54.consider("with"); else if (node instanceof AST_ObjectSetter) base54.consider("set" + node.key); else if (node instanceof AST_ObjectGetter) base54.consider("get" + node.key); else if (node instanceof AST_ObjectKeyVal) base54.consider(node.key); else if (node instanceof AST_New) base54.consider("new"); else if (node instanceof AST_This) base54.consider("this"); else if (node instanceof AST_Try) base54.consider("try"); else if (node instanceof AST_Catch) base54.consider("catch"); else if (node instanceof AST_Finally) base54.consider("finally"); else if (node instanceof AST_Symbol && node.unmangleable(options)) base54.consider(node.name); else if (node instanceof AST_Unary || node instanceof AST_Binary) base54.consider(node.operator); else if (node instanceof AST_Dot) base54.consider(node.property); + }); + this.walk(tw); + base54.sort(); + }); + var base54 = function() { + var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + var chars, frequency; + function reset() { + frequency = Object.create(null); + chars = string.split("").map(function(ch) { + return ch.charCodeAt(0); + }); + chars.forEach(function(ch) { + frequency[ch] = 0; + }); + } + base54.consider = function(str) { + for (var i = str.length; --i >= 0; ) { + var code = str.charCodeAt(i); + if (code in frequency) ++frequency[code]; + } + }; + base54.sort = function() { + chars = mergeSort(chars, function(a, b) { + if (is_digit(a) && !is_digit(b)) return 1; + if (is_digit(b) && !is_digit(a)) return -1; + return frequency[b] - frequency[a]; + }); + }; + base54.reset = reset; + reset(); + base54.get = function() { + return chars; + }; + base54.freq = function() { + return frequency; + }; + function base54(num) { + var ret = "", base = 54; + do { + ret += String.fromCharCode(chars[num % base]); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + } + return base54; + }(); + AST_Toplevel.DEFMETHOD("scope_warnings", function(options) { + options = defaults(options, { + undeclared: false, + unreferenced: true, + assign_to_global: true, + func_arguments: true, + nested_defuns: true, + eval: true + }); + var tw = new TreeWalker(function(node) { + if (options.undeclared && node instanceof AST_SymbolRef && node.undeclared()) { + AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.assign_to_global) { + var sym = null; + if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) sym = node.left; else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) sym = node.init; + if (sym && (sym.undeclared() || sym.global() && sym.scope !== sym.definition().scope)) { + AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { + msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", + name: sym.name, + file: sym.start.file, + line: sym.start.line, + col: sym.start.col + }); + } + } + if (options.eval && node instanceof AST_SymbolRef && node.undeclared() && node.name == "eval") { + AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); + } + if (options.unreferenced && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) && node.unreferenced()) { + AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { + type: node instanceof AST_Label ? "Label" : "Symbol", + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.func_arguments && node instanceof AST_Lambda && node.uses_arguments) { + AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { + name: node.name ? node.name.name : "anonymous", + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.nested_defuns && node instanceof AST_Defun && !(tw.parent() instanceof AST_Scope)) { + AST_Node.warn('Function {name} declared in nested statement "{type}" [{file}:{line},{col}]', { + name: node.name.name, + type: tw.parent().TYPE, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + }); + this.walk(tw); + }); + "use strict"; + function OutputStream(options) { + options = defaults(options, { + indent_start: 0, + indent_level: 4, + quote_keys: false, + space_colon: true, + ascii_only: false, + inline_script: false, + width: 80, + max_line_len: 32e3, + beautify: false, + source_map: null, + bracketize: false, + semicolons: true, + comments: false, + preserve_line: false, + screw_ie8: false + }, true); + var indentation = 0; + var current_col = 0; + var current_line = 1; + var current_pos = 0; + var OUTPUT = ""; + function to_ascii(str, identifier) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + if (code.length <= 2 && !identifier) { + while (code.length < 2) code = "0" + code; + return "\\x" + code; + } else { + while (code.length < 4) code = "0" + code; + return "\\u" + code; + } + }); + } + function make_string(str) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s) { + switch (s) { + case "\\": + return "\\\\"; + + case "\b": + return "\\b"; + + case "\f": + return "\\f"; + + case "\n": + return "\\n"; + + case "\r": + return "\\r"; + + case "\u2028": + return "\\u2028"; + + case "\u2029": + return "\\u2029"; + + case '"': + ++dq; + return '"'; + + case "'": + ++sq; + return "'"; + + case "\x00": + return "\\x00"; + } + return s; + }); + if (options.ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; else return '"' + str.replace(/\x22/g, '\\"') + '"'; + } + function encode_string(str) { + var ret = make_string(str); + if (options.inline_script) ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + } + function make_name(name) { + name = name.toString(); + if (options.ascii_only) name = to_ascii(name, true); + return name; + } + function make_indent(back) { + return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); + } + var might_need_space = false; + var might_need_semicolon = false; + var last = null; + function last_char() { + return last.charAt(last.length - 1); + } + function maybe_newline() { + if (options.max_line_len && current_col > options.max_line_len) print("\n"); + } + var requireSemicolonChars = makePredicate("( [ + * / - , ."); + function print(str) { + str = String(str); + var ch = str.charAt(0); + if (might_need_semicolon) { + if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) { + if (options.semicolons || requireSemicolonChars(ch)) { + OUTPUT += ";"; + current_col++; + current_pos++; + } else { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + } + if (!options.beautify) might_need_space = false; + } + might_need_semicolon = false; + maybe_newline(); + } + if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { + var target_line = stack[stack.length - 1].start.line; + while (current_line < target_line) { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + might_need_space = false; + } + } + if (might_need_space) { + var prev = last_char(); + if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\") || /^[\+\-\/]$/.test(ch) && ch == prev) { + OUTPUT += " "; + current_col++; + current_pos++; + } + might_need_space = false; + } + var a = str.split(/\r?\n/), n = a.length - 1; + current_line += n; + if (n == 0) { + current_col += a[n].length; + } else { + current_col = a[n].length; + } + current_pos += str.length; + last = str; + OUTPUT += str; + } + var space = options.beautify ? function() { + print(" "); + } : function() { + might_need_space = true; + }; + var indent = options.beautify ? function(half) { + if (options.beautify) { + print(make_indent(half ? .5 : 0)); + } + } : noop; + var with_indent = options.beautify ? function(col, cont) { + if (col === true) col = next_indent(); + var save_indentation = indentation; + indentation = col; + var ret = cont(); + indentation = save_indentation; + return ret; + } : function(col, cont) { + return cont(); + }; + var newline = options.beautify ? function() { + print("\n"); + } : noop; + var semicolon = options.beautify ? function() { + print(";"); + } : function() { + might_need_semicolon = true; + }; + function force_semicolon() { + might_need_semicolon = false; + print(";"); + } + function next_indent() { + return indentation + options.indent_level; + } + function with_block(cont) { + var ret; + print("{"); + newline(); + with_indent(next_indent(), function() { + ret = cont(); + }); + indent(); + print("}"); + return ret; + } + function with_parens(cont) { + print("("); + var ret = cont(); + print(")"); + return ret; + } + function with_square(cont) { + print("["); + var ret = cont(); + print("]"); + return ret; + } + function comma() { + print(","); + space(); + } + function colon() { + print(":"); + if (options.space_colon) space(); + } + var add_mapping = options.source_map ? function(token, name) { + try { + if (token) options.source_map.add(token.file || "?", current_line, current_col, token.line, token.col, !name && token.type == "name" ? token.value : name); + } catch (ex) { + AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + file: token.file, + line: token.line, + col: token.col, + cline: current_line, + ccol: current_col, + name: name || "" + }); + } + } : noop; + function get() { + return OUTPUT; + } + var stack = []; + return { + get: get, + toString: get, + indent: indent, + indentation: function() { + return indentation; + }, + current_width: function() { + return current_col - indentation; + }, + should_break: function() { + return options.width && this.current_width() >= options.width; + }, + newline: newline, + print: print, + space: space, + comma: comma, + colon: colon, + last: function() { + return last; + }, + semicolon: semicolon, + force_semicolon: force_semicolon, + to_ascii: to_ascii, + print_name: function(name) { + print(make_name(name)); + }, + print_string: function(str) { + print(encode_string(str)); + }, + next_indent: next_indent, + with_indent: with_indent, + with_block: with_block, + with_parens: with_parens, + with_square: with_square, + add_mapping: add_mapping, + option: function(opt) { + return options[opt]; + }, + line: function() { + return current_line; + }, + col: function() { + return current_col; + }, + pos: function() { + return current_pos; + }, + push_node: function(node) { + stack.push(node); + }, + pop_node: function() { + return stack.pop(); + }, + stack: function() { + return stack; + }, + parent: function(n) { + return stack[stack.length - 2 - (n || 0)]; + } + }; + } + (function() { + function DEFPRINT(nodetype, generator) { + nodetype.DEFMETHOD("_codegen", generator); + } + AST_Node.DEFMETHOD("print", function(stream, force_parens) { + var self = this, generator = self._codegen; + function doit() { + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + } + stream.push_node(self); + if (force_parens || self.needs_parens(stream)) { + stream.with_parens(doit); + } else { + doit(); + } + stream.pop_node(); + }); + AST_Node.DEFMETHOD("print_to_string", function(options) { + var s = OutputStream(options); + this.print(s); + return s.get(); + }); + AST_Node.DEFMETHOD("add_comments", function(output) { + var c = output.option("comments"), self = this; + if (c) { + var start = self.start; + if (start && !start._comments_dumped) { + start._comments_dumped = true; + var comments = start.comments_before; + if (self instanceof AST_Exit && self.value && self.value.start.comments_before.length > 0) { + comments = (comments || []).concat(self.value.start.comments_before); + self.value.start.comments_before = []; + } + if (c.test) { + comments = comments.filter(function(comment) { + return c.test(comment.value); + }); + } else if (typeof c == "function") { + comments = comments.filter(function(comment) { + return c(self, comment); + }); + } + comments.forEach(function(c) { + if (c.type == "comment1") { + output.print("//" + c.value + "\n"); + output.indent(); + } else if (c.type == "comment2") { + output.print("/*" + c.value + "*/"); + if (start.nlb) { + output.print("\n"); + output.indent(); + } else { + output.space(); + } + } + }); + } + } + }); + function PARENS(nodetype, func) { + nodetype.DEFMETHOD("needs_parens", func); + } + PARENS(AST_Node, function() { + return false; + }); + PARENS(AST_Function, function(output) { + return first_in_statement(output); + }); + PARENS(AST_Object, function(output) { + return first_in_statement(output); + }); + PARENS(AST_Unary, function(output) { + var p = output.parent(); + return p instanceof AST_PropAccess && p.expression === this; + }); + PARENS(AST_Seq, function(output) { + var p = output.parent(); + return p instanceof AST_Call || p instanceof AST_Unary || p instanceof AST_Binary || p instanceof AST_VarDef || p instanceof AST_Dot || p instanceof AST_Array || p instanceof AST_ObjectProperty || p instanceof AST_Conditional; + }); + PARENS(AST_Binary, function(output) { + var p = output.parent(); + if (p instanceof AST_Call && p.expression === this) return true; + if (p instanceof AST_Unary) return true; + if (p instanceof AST_PropAccess && p.expression === this) return true; + if (p instanceof AST_Binary) { + var po = p.operator, pp = PRECEDENCE[po]; + var so = this.operator, sp = PRECEDENCE[so]; + if (pp > sp || pp == sp && this === p.right && !(so == po && (so == "*" || so == "&&" || so == "||"))) { + return true; + } + } + }); + PARENS(AST_PropAccess, function(output) { + var p = output.parent(); + if (p instanceof AST_New && p.expression === this) { + try { + this.walk(new TreeWalker(function(node) { + if (node instanceof AST_Call) throw p; + })); + } catch (ex) { + if (ex !== p) throw ex; + return true; + } + } + }); + PARENS(AST_Call, function(output) { + var p = output.parent(); + return p instanceof AST_New && p.expression === this; + }); + PARENS(AST_New, function(output) { + var p = output.parent(); + if (no_constructor_parens(this, output) && (p instanceof AST_PropAccess || p instanceof AST_Call && p.expression === this)) return true; + }); + PARENS(AST_Number, function(output) { + var p = output.parent(); + if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) return true; + }); + PARENS(AST_NaN, function(output) { + var p = output.parent(); + if (p instanceof AST_PropAccess && p.expression === this) return true; + }); + function assign_and_conditional_paren_rules(output) { + var p = output.parent(); + if (p instanceof AST_Unary) return true; + if (p instanceof AST_Binary && !(p instanceof AST_Assign)) return true; + if (p instanceof AST_Call && p.expression === this) return true; + if (p instanceof AST_Conditional && p.condition === this) return true; + if (p instanceof AST_PropAccess && p.expression === this) return true; + } + PARENS(AST_Assign, assign_and_conditional_paren_rules); + PARENS(AST_Conditional, assign_and_conditional_paren_rules); + DEFPRINT(AST_Directive, function(self, output) { + output.print_string(self.value); + output.semicolon(); + }); + DEFPRINT(AST_Debugger, function(self, output) { + output.print("debugger"); + output.semicolon(); + }); + function display_body(body, is_toplevel, output) { + var last = body.length - 1; + body.forEach(function(stmt, i) { + if (!(stmt instanceof AST_EmptyStatement)) { + output.indent(); + stmt.print(output); + if (!(i == last && is_toplevel)) { + output.newline(); + if (is_toplevel) output.newline(); + } + } + }); + } + AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) { + force_statement(this.body, output); + }); + DEFPRINT(AST_Statement, function(self, output) { + self.body.print(output); + output.semicolon(); + }); + DEFPRINT(AST_Toplevel, function(self, output) { + display_body(self.body, true, output); + output.print(""); + }); + DEFPRINT(AST_LabeledStatement, function(self, output) { + self.label.print(output); + output.colon(); + self.body.print(output); + }); + DEFPRINT(AST_SimpleStatement, function(self, output) { + self.body.print(output); + output.semicolon(); + }); + function print_bracketed(body, output) { + if (body.length > 0) output.with_block(function() { + display_body(body, false, output); + }); else output.print("{}"); + } + DEFPRINT(AST_BlockStatement, function(self, output) { + print_bracketed(self.body, output); + }); + DEFPRINT(AST_EmptyStatement, function(self, output) { + output.semicolon(); + }); + DEFPRINT(AST_Do, function(self, output) { + output.print("do"); + output.space(); + self._do_print_body(output); + output.space(); + output.print("while"); + output.space(); + output.with_parens(function() { + self.condition.print(output); + }); + output.semicolon(); + }); + DEFPRINT(AST_While, function(self, output) { + output.print("while"); + output.space(); + output.with_parens(function() { + self.condition.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_For, function(self, output) { + output.print("for"); + output.space(); + output.with_parens(function() { + if (self.init) { + if (self.init instanceof AST_Definitions) { + self.init.print(output); + } else { + parenthesize_for_noin(self.init, output, true); + } + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.condition) { + self.condition.print(output); + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.step) { + self.step.print(output); + } + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_ForIn, function(self, output) { + output.print("for"); + output.space(); + output.with_parens(function() { + self.init.print(output); + output.space(); + output.print("in"); + output.space(); + self.object.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_With, function(self, output) { + output.print("with"); + output.space(); + output.with_parens(function() { + self.expression.print(output); + }); + output.space(); + self._do_print_body(output); + }); + AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) { + var self = this; + if (!nokeyword) { + output.print("function"); + } + if (self.name) { + output.space(); + self.name.print(output); + } + output.with_parens(function() { + self.argnames.forEach(function(arg, i) { + if (i) output.comma(); + arg.print(output); + }); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Lambda, function(self, output) { + self._do_print(output); + }); + AST_Exit.DEFMETHOD("_do_print", function(output, kind) { + output.print(kind); + if (this.value) { + output.space(); + this.value.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Return, function(self, output) { + self._do_print(output, "return"); + }); + DEFPRINT(AST_Throw, function(self, output) { + self._do_print(output, "throw"); + }); + AST_LoopControl.DEFMETHOD("_do_print", function(output, kind) { + output.print(kind); + if (this.label) { + output.space(); + this.label.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Break, function(self, output) { + self._do_print(output, "break"); + }); + DEFPRINT(AST_Continue, function(self, output) { + self._do_print(output, "continue"); + }); + function make_then(self, output) { + if (output.option("bracketize")) { + make_block(self.body, output); + return; + } + if (!self.body) return output.force_semicolon(); + if (self.body instanceof AST_Do && !output.option("screw_ie8")) { + make_block(self.body, output); + return; + } + var b = self.body; + while (true) { + if (b instanceof AST_If) { + if (!b.alternative) { + make_block(self.body, output); + return; + } + b = b.alternative; + } else if (b instanceof AST_StatementWithBody) { + b = b.body; + } else break; + } + force_statement(self.body, output); + } + DEFPRINT(AST_If, function(self, output) { + output.print("if"); + output.space(); + output.with_parens(function() { + self.condition.print(output); + }); + output.space(); + if (self.alternative) { + make_then(self, output); + output.space(); + output.print("else"); + output.space(); + force_statement(self.alternative, output); + } else { + self._do_print_body(output); + } + }); + DEFPRINT(AST_Switch, function(self, output) { + output.print("switch"); + output.space(); + output.with_parens(function() { + self.expression.print(output); + }); + output.space(); + if (self.body.length > 0) output.with_block(function() { + self.body.forEach(function(stmt, i) { + if (i) output.newline(); + output.indent(true); + stmt.print(output); + }); + }); else output.print("{}"); + }); + AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) { + if (this.body.length > 0) { + output.newline(); + this.body.forEach(function(stmt) { + output.indent(); + stmt.print(output); + output.newline(); + }); + } + }); + DEFPRINT(AST_Default, function(self, output) { + output.print("default:"); + self._do_print_body(output); + }); + DEFPRINT(AST_Case, function(self, output) { + output.print("case"); + output.space(); + self.expression.print(output); + output.print(":"); + self._do_print_body(output); + }); + DEFPRINT(AST_Try, function(self, output) { + output.print("try"); + output.space(); + print_bracketed(self.body, output); + if (self.bcatch) { + output.space(); + self.bcatch.print(output); + } + if (self.bfinally) { + output.space(); + self.bfinally.print(output); + } + }); + DEFPRINT(AST_Catch, function(self, output) { + output.print("catch"); + output.space(); + output.with_parens(function() { + self.argname.print(output); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Finally, function(self, output) { + output.print("finally"); + output.space(); + print_bracketed(self.body, output); + }); + AST_Definitions.DEFMETHOD("_do_print", function(output, kind) { + output.print(kind); + output.space(); + this.definitions.forEach(function(def, i) { + if (i) output.comma(); + def.print(output); + }); + var p = output.parent(); + var in_for = p instanceof AST_For || p instanceof AST_ForIn; + var avoid_semicolon = in_for && p.init === this; + if (!avoid_semicolon) output.semicolon(); + }); + DEFPRINT(AST_Var, function(self, output) { + self._do_print(output, "var"); + }); + DEFPRINT(AST_Const, function(self, output) { + self._do_print(output, "const"); + }); + function parenthesize_for_noin(node, output, noin) { + if (!noin) node.print(output); else try { + node.walk(new TreeWalker(function(node) { + if (node instanceof AST_Binary && node.operator == "in") throw output; + })); + node.print(output); + } catch (ex) { + if (ex !== output) throw ex; + node.print(output, true); + } + } + DEFPRINT(AST_VarDef, function(self, output) { + self.name.print(output); + if (self.value) { + output.space(); + output.print("="); + output.space(); + var p = output.parent(1); + var noin = p instanceof AST_For || p instanceof AST_ForIn; + parenthesize_for_noin(self.value, output, noin); + } + }); + DEFPRINT(AST_Call, function(self, output) { + self.expression.print(output); + if (self instanceof AST_New && no_constructor_parens(self, output)) return; + output.with_parens(function() { + self.args.forEach(function(expr, i) { + if (i) output.comma(); + expr.print(output); + }); + }); + }); + DEFPRINT(AST_New, function(self, output) { + output.print("new"); + output.space(); + AST_Call.prototype._codegen(self, output); + }); + AST_Seq.DEFMETHOD("_do_print", function(output) { + this.car.print(output); + if (this.cdr) { + output.comma(); + if (output.should_break()) { + output.newline(); + output.indent(); + } + this.cdr.print(output); + } + }); + DEFPRINT(AST_Seq, function(self, output) { + self._do_print(output); + }); + DEFPRINT(AST_Dot, function(self, output) { + var expr = self.expression; + expr.print(output); + if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (!/[xa-f.]/i.test(output.last())) { + output.print("."); + } + } + output.print("."); + output.add_mapping(self.end); + output.print_name(self.property); + }); + DEFPRINT(AST_Sub, function(self, output) { + self.expression.print(output); + output.print("["); + self.property.print(output); + output.print("]"); + }); + DEFPRINT(AST_UnaryPrefix, function(self, output) { + var op = self.operator; + output.print(op); + if (/^[a-z]/i.test(op)) output.space(); + self.expression.print(output); + }); + DEFPRINT(AST_UnaryPostfix, function(self, output) { + self.expression.print(output); + output.print(self.operator); + }); + DEFPRINT(AST_Binary, function(self, output) { + self.left.print(output); + output.space(); + output.print(self.operator); + output.space(); + self.right.print(output); + }); + DEFPRINT(AST_Conditional, function(self, output) { + self.condition.print(output); + output.space(); + output.print("?"); + output.space(); + self.consequent.print(output); + output.space(); + output.colon(); + self.alternative.print(output); + }); + DEFPRINT(AST_Array, function(self, output) { + output.with_square(function() { + var a = self.elements, len = a.length; + if (len > 0) output.space(); + a.forEach(function(exp, i) { + if (i) output.comma(); + exp.print(output); + if (i === len - 1 && exp instanceof AST_Hole) output.comma(); + }); + if (len > 0) output.space(); + }); + }); + DEFPRINT(AST_Object, function(self, output) { + if (self.properties.length > 0) output.with_block(function() { + self.properties.forEach(function(prop, i) { + if (i) { + output.print(","); + output.newline(); + } + output.indent(); + prop.print(output); + }); + output.newline(); + }); else output.print("{}"); + }); + DEFPRINT(AST_ObjectKeyVal, function(self, output) { + var key = self.key; + if (output.option("quote_keys")) { + output.print_string(key + ""); + } else if ((typeof key == "number" || !output.option("beautify") && +key + "" == key) && parseFloat(key) >= 0) { + output.print(make_num(key)); + } else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) { + output.print_name(key); + } else { + output.print_string(key); + } + output.colon(); + self.value.print(output); + }); + DEFPRINT(AST_ObjectSetter, function(self, output) { + output.print("set"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_ObjectGetter, function(self, output) { + output.print("get"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_Symbol, function(self, output) { + var def = self.definition(); + output.print_name(def ? def.mangled_name || def.name : self.name); + }); + DEFPRINT(AST_Undefined, function(self, output) { + output.print("void 0"); + }); + DEFPRINT(AST_Hole, noop); + DEFPRINT(AST_Infinity, function(self, output) { + output.print("1/0"); + }); + DEFPRINT(AST_NaN, function(self, output) { + output.print("0/0"); + }); + DEFPRINT(AST_This, function(self, output) { + output.print("this"); + }); + DEFPRINT(AST_Constant, function(self, output) { + output.print(self.getValue()); + }); + DEFPRINT(AST_String, function(self, output) { + output.print_string(self.getValue()); + }); + DEFPRINT(AST_Number, function(self, output) { + output.print(make_num(self.getValue())); + }); + DEFPRINT(AST_RegExp, function(self, output) { + var str = self.getValue().toString(); + if (output.option("ascii_only")) str = output.to_ascii(str); + output.print(str); + var p = output.parent(); + if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) output.print(" "); + }); + function force_statement(stat, output) { + if (output.option("bracketize")) { + if (!stat || stat instanceof AST_EmptyStatement) output.print("{}"); else if (stat instanceof AST_BlockStatement) stat.print(output); else output.with_block(function() { + output.indent(); + stat.print(output); + output.newline(); + }); + } else { + if (!stat || stat instanceof AST_EmptyStatement) output.force_semicolon(); else stat.print(output); + } + } + function first_in_statement(output) { + var a = output.stack(), i = a.length, node = a[--i], p = a[--i]; + while (i > 0) { + if (p instanceof AST_Statement && p.body === node) return true; + if (p instanceof AST_Seq && p.car === node || p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) || p instanceof AST_Dot && p.expression === node || p instanceof AST_Sub && p.expression === node || p instanceof AST_Conditional && p.condition === node || p instanceof AST_Binary && p.left === node || p instanceof AST_UnaryPostfix && p.expression === node) { + node = p; + p = a[--i]; + } else { + return false; + } + } + } + function no_constructor_parens(self, output) { + return self.args.length == 0 && !output.option("beautify"); + } + function best_of(a) { + var best = a[0], len = best.length; + for (var i = 1; i < a.length; ++i) { + if (a[i].length < len) { + best = a[i]; + len = best.length; + } + } + return best; + } + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace("e+", "e") ], m; + if (Math.floor(num) === num) { + if (num >= 0) { + a.push("0x" + num.toString(16).toLowerCase(), "0" + num.toString(8)); + } else { + a.push("-0x" + (-num).toString(16).toLowerCase(), "-0" + (-num).toString(8)); + } + if (m = /^(.*?)(0+)$/.exec(num)) { + a.push(m[1] + "e" + m[2].length); + } + } else if (m = /^0?\.(0+)(.*)$/.exec(num)) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), str.substr(str.indexOf("."))); + } + return best_of(a); + } + function make_block(stmt, output) { + if (stmt instanceof AST_BlockStatement) { + stmt.print(output); + return; + } + output.with_block(function() { + output.indent(); + stmt.print(output); + output.newline(); + }); + } + function DEFMAP(nodetype, generator) { + nodetype.DEFMETHOD("add_source_map", function(stream) { + generator(this, stream); + }); + } + DEFMAP(AST_Node, noop); + function basic_sourcemap_gen(self, output) { + output.add_mapping(self.start); + } + DEFMAP(AST_Directive, basic_sourcemap_gen); + DEFMAP(AST_Debugger, basic_sourcemap_gen); + DEFMAP(AST_Symbol, basic_sourcemap_gen); + DEFMAP(AST_Jump, basic_sourcemap_gen); + DEFMAP(AST_StatementWithBody, basic_sourcemap_gen); + DEFMAP(AST_LabeledStatement, noop); + DEFMAP(AST_Lambda, basic_sourcemap_gen); + DEFMAP(AST_Switch, basic_sourcemap_gen); + DEFMAP(AST_SwitchBranch, basic_sourcemap_gen); + DEFMAP(AST_BlockStatement, basic_sourcemap_gen); + DEFMAP(AST_Toplevel, noop); + DEFMAP(AST_New, basic_sourcemap_gen); + DEFMAP(AST_Try, basic_sourcemap_gen); + DEFMAP(AST_Catch, basic_sourcemap_gen); + DEFMAP(AST_Finally, basic_sourcemap_gen); + DEFMAP(AST_Definitions, basic_sourcemap_gen); + DEFMAP(AST_Constant, basic_sourcemap_gen); + DEFMAP(AST_ObjectProperty, function(self, output) { + output.add_mapping(self.start, self.key); + }); + })(); + "use strict"; + function Compressor(options, false_by_default) { + if (!(this instanceof Compressor)) return new Compressor(options, false_by_default); + TreeTransformer.call(this, this.before, this.after); + this.options = defaults(options, { + sequences: !false_by_default, + properties: !false_by_default, + dead_code: !false_by_default, + drop_debugger: !false_by_default, + unsafe: false, + unsafe_comps: false, + conditionals: !false_by_default, + comparisons: !false_by_default, + evaluate: !false_by_default, + booleans: !false_by_default, + loops: !false_by_default, + unused: !false_by_default, + hoist_funs: !false_by_default, + hoist_vars: false, + if_return: !false_by_default, + join_vars: !false_by_default, + cascade: !false_by_default, + side_effects: !false_by_default, + negate_iife: !false_by_default, + screw_ie8: false, + warnings: true, + global_defs: {} + }, true); + } + Compressor.prototype = new TreeTransformer(); + merge(Compressor.prototype, { + option: function(key) { + return this.options[key]; + }, + warn: function() { + if (this.options.warnings) AST_Node.warn.apply(AST_Node, arguments); + }, + before: function(node, descend, in_list) { + if (node._squeezed) return node; + if (node instanceof AST_Scope) { + node.drop_unused(this); + node = node.hoist_declarations(this); + } + descend(node, this); + node = node.optimize(this); + if (node instanceof AST_Scope) { + var save_warnings = this.options.warnings; + this.options.warnings = false; + node.drop_unused(this); + this.options.warnings = save_warnings; + } + node._squeezed = true; + return node; + } + }); + (function() { + function OPT(node, optimizer) { + node.DEFMETHOD("optimize", function(compressor) { + var self = this; + if (self._optimized) return self; + var opt = optimizer(self, compressor); + opt._optimized = true; + if (opt === self) return opt; + return opt.transform(compressor); + }); + } + OPT(AST_Node, function(self, compressor) { + return self; + }); + AST_Node.DEFMETHOD("equivalent_to", function(node) { + return this.print_to_string() == node.print_to_string(); + }); + function make_node(ctor, orig, props) { + if (!props) props = {}; + if (orig) { + if (!props.start) props.start = orig.start; + if (!props.end) props.end = orig.end; + } + return new ctor(props); + } + function make_node_from_constant(compressor, val, orig) { + if (val instanceof AST_Node) return val.transform(compressor); + switch (typeof val) { + case "string": + return make_node(AST_String, orig, { + value: val + }).optimize(compressor); + + case "number": + return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, { + value: val + }).optimize(compressor); + + case "boolean": + return make_node(val ? AST_True : AST_False, orig).optimize(compressor); + + case "undefined": + return make_node(AST_Undefined, orig).optimize(compressor); + + default: + if (val === null) { + return make_node(AST_Null, orig).optimize(compressor); + } + if (val instanceof RegExp) { + return make_node(AST_RegExp, orig).optimize(compressor); + } + throw new Error(string_template("Can't handle constant of type: {type}", { + type: typeof val + })); + } + } + function as_statement_array(thing) { + if (thing === null) return []; + if (thing instanceof AST_BlockStatement) return thing.body; + if (thing instanceof AST_EmptyStatement) return []; + if (thing instanceof AST_Statement) return [ thing ]; + throw new Error("Can't convert thing to statement array"); + } + function is_empty(thing) { + if (thing === null) return true; + if (thing instanceof AST_EmptyStatement) return true; + if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + return false; + } + function loop_body(x) { + if (x instanceof AST_Switch) return x; + if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { + return x.body instanceof AST_BlockStatement ? x.body : x; + } + return x; + } + function tighten_body(statements, compressor) { + var CHANGED; + do { + CHANGED = false; + statements = eliminate_spurious_blocks(statements); + if (compressor.option("dead_code")) { + statements = eliminate_dead_code(statements, compressor); + } + if (compressor.option("if_return")) { + statements = handle_if_return(statements, compressor); + } + if (compressor.option("sequences")) { + statements = sequencesize(statements, compressor); + } + if (compressor.option("join_vars")) { + statements = join_consecutive_vars(statements, compressor); + } + } while (CHANGED); + if (compressor.option("negate_iife")) { + negate_iifes(statements, compressor); + } + return statements; + function eliminate_spurious_blocks(statements) { + var seen_dirs = []; + return statements.reduce(function(a, stat) { + if (stat instanceof AST_BlockStatement) { + CHANGED = true; + a.push.apply(a, eliminate_spurious_blocks(stat.body)); + } else if (stat instanceof AST_EmptyStatement) { + CHANGED = true; + } else if (stat instanceof AST_Directive) { + if (seen_dirs.indexOf(stat.value) < 0) { + a.push(stat); + seen_dirs.push(stat.value); + } else { + CHANGED = true; + } + } else { + a.push(stat); + } + return a; + }, []); + } + function handle_if_return(statements, compressor) { + var self = compressor.self(); + var in_lambda = self instanceof AST_Lambda; + var ret = []; + loop: for (var i = statements.length; --i >= 0; ) { + var stat = statements[i]; + switch (true) { + case in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0: + CHANGED = true; + continue loop; + + case stat instanceof AST_If: + if (stat.body instanceof AST_Return) { + if ((in_lambda && ret.length == 0 || ret[0] instanceof AST_Return && !ret[0].value) && !stat.body.value && !stat.alternative) { + CHANGED = true; + var cond = make_node(AST_SimpleStatement, stat.condition, { + body: stat.condition + }); + ret.unshift(cond); + continue loop; + } + if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0]; + ret[0] = stat.transform(compressor); + continue loop; + } + if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0] || make_node(AST_Return, stat, { + value: make_node(AST_Undefined, stat) + }); + ret[0] = stat.transform(compressor); + continue loop; + } + if (!stat.body.value && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: as_statement_array(stat.alternative).concat(ret) + }); + stat.alternative = null; + ret = [ stat.transform(compressor) ]; + continue loop; + } + if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) { + CHANGED = true; + ret.push(make_node(AST_Return, ret[0], { + value: make_node(AST_Undefined, ret[0]) + }).transform(compressor)); + ret = as_statement_array(stat.alternative).concat(ret); + ret.unshift(stat); + continue loop; + } + } + var ab = aborts(stat.body); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && (ab instanceof AST_Return && !ab.value && in_lambda || ab instanceof AST_Continue && self === loop_body(lct) || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct)) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + var body = as_statement_array(stat.body).slice(0, -1); + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: ret + }); + stat.alternative = make_node(AST_BlockStatement, stat, { + body: body + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + var ab = aborts(stat.alternative); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && (ab instanceof AST_Return && !ab.value && in_lambda || ab instanceof AST_Continue && self === loop_body(lct) || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct)) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + stat = stat.clone(); + stat.body = make_node(AST_BlockStatement, stat.body, { + body: as_statement_array(stat.body).concat(ret) + }); + stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + body: as_statement_array(stat.alternative).slice(0, -1) + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + ret.unshift(stat); + break; + + default: + ret.unshift(stat); + break; + } + } + return ret; + } + function eliminate_dead_code(statements, compressor) { + var has_quit = false; + var orig = statements.length; + var self = compressor.self(); + statements = statements.reduce(function(a, stat) { + if (has_quit) { + extract_declarations_from_unreachable_code(compressor, stat, a); + } else { + if (stat instanceof AST_LoopControl) { + var lct = compressor.loopcontrol_target(stat.label); + if (stat instanceof AST_Break && lct instanceof AST_BlockStatement && loop_body(lct) === self || stat instanceof AST_Continue && loop_body(lct) === self) { + if (stat.label) { + remove(stat.label.thedef.references, stat.label); + } + } else { + a.push(stat); + } + } else { + a.push(stat); + } + if (aborts(stat)) has_quit = true; + } + return a; + }, []); + CHANGED = statements.length != orig; + return statements; + } + function sequencesize(statements, compressor) { + if (statements.length < 2) return statements; + var seq = [], ret = []; + function push_seq() { + seq = AST_Seq.from_array(seq); + if (seq) ret.push(make_node(AST_SimpleStatement, seq, { + body: seq + })); + seq = []; + } + statements.forEach(function(stat) { + if (stat instanceof AST_SimpleStatement) seq.push(stat.body); else push_seq(), ret.push(stat); + }); + push_seq(); + ret = sequencesize_2(ret, compressor); + CHANGED = ret.length != statements.length; + return ret; + } + function sequencesize_2(statements, compressor) { + function cons_seq(right) { + ret.pop(); + var left = prev.body; + if (left instanceof AST_Seq) { + left.add(right); + } else { + left = AST_Seq.cons(left, right); + } + return left.transform(compressor); + } + var ret = [], prev = null; + statements.forEach(function(stat) { + if (prev) { + if (stat instanceof AST_For) { + var opera = {}; + try { + prev.body.walk(new TreeWalker(function(node) { + if (node instanceof AST_Binary && node.operator == "in") throw opera; + })); + if (stat.init && !(stat.init instanceof AST_Definitions)) { + stat.init = cons_seq(stat.init); + } else if (!stat.init) { + stat.init = prev.body; + ret.pop(); + } + } catch (ex) { + if (ex !== opera) throw ex; + } + } else if (stat instanceof AST_If) { + stat.condition = cons_seq(stat.condition); + } else if (stat instanceof AST_With) { + stat.expression = cons_seq(stat.expression); + } else if (stat instanceof AST_Exit && stat.value) { + stat.value = cons_seq(stat.value); + } else if (stat instanceof AST_Exit) { + stat.value = cons_seq(make_node(AST_Undefined, stat)); + } else if (stat instanceof AST_Switch) { + stat.expression = cons_seq(stat.expression); + } + } + ret.push(stat); + prev = stat instanceof AST_SimpleStatement ? stat : null; + }); + return ret; + } + function join_consecutive_vars(statements, compressor) { + var prev = null; + return statements.reduce(function(a, stat) { + if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { + prev.definitions = prev.definitions.concat(stat.definitions); + CHANGED = true; + } else if (stat instanceof AST_For && prev instanceof AST_Definitions && (!stat.init || stat.init.TYPE == prev.TYPE)) { + CHANGED = true; + a.pop(); + if (stat.init) { + stat.init.definitions = prev.definitions.concat(stat.init.definitions); + } else { + stat.init = prev; + } + a.push(stat); + prev = stat; + } else { + prev = stat; + a.push(stat); + } + return a; + }, []); + } + function negate_iifes(statements, compressor) { + statements.forEach(function(stat) { + if (stat instanceof AST_SimpleStatement) { + stat.body = function transform(thing) { + return thing.transform(new TreeTransformer(function(node) { + if (node instanceof AST_Call && node.expression instanceof AST_Function) { + return make_node(AST_UnaryPrefix, node, { + operator: "!", + expression: node + }); + } else if (node instanceof AST_Call) { + node.expression = transform(node.expression); + } else if (node instanceof AST_Seq) { + node.car = transform(node.car); + } else if (node instanceof AST_Conditional) { + var expr = transform(node.condition); + if (expr !== node.condition) { + node.condition = expr; + var tmp = node.consequent; + node.consequent = node.alternative; + node.alternative = tmp; + } + } + return node; + })); + }(stat.body); + } + }); + } + } + function extract_declarations_from_unreachable_code(compressor, stat, target) { + compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); + stat.walk(new TreeWalker(function(node) { + if (node instanceof AST_Definitions) { + compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); + node.remove_initializers(); + target.push(node); + return true; + } + if (node instanceof AST_Defun) { + target.push(node); + return true; + } + if (node instanceof AST_Scope) { + return true; + } + })); + } + (function(def) { + var unary_bool = [ "!", "delete" ]; + var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; + def(AST_Node, function() { + return false; + }); + def(AST_UnaryPrefix, function() { + return member(this.operator, unary_bool); + }); + def(AST_Binary, function() { + return member(this.operator, binary_bool) || (this.operator == "&&" || this.operator == "||") && this.left.is_boolean() && this.right.is_boolean(); + }); + def(AST_Conditional, function() { + return this.consequent.is_boolean() && this.alternative.is_boolean(); + }); + def(AST_Assign, function() { + return this.operator == "=" && this.right.is_boolean(); + }); + def(AST_Seq, function() { + return this.cdr.is_boolean(); + }); + def(AST_True, function() { + return true; + }); + def(AST_False, function() { + return true; + }); + })(function(node, func) { + node.DEFMETHOD("is_boolean", func); + }); + (function(def) { + def(AST_Node, function() { + return false; + }); + def(AST_String, function() { + return true; + }); + def(AST_UnaryPrefix, function() { + return this.operator == "typeof"; + }); + def(AST_Binary, function(compressor) { + return this.operator == "+" && (this.left.is_string(compressor) || this.right.is_string(compressor)); + }); + def(AST_Assign, function(compressor) { + return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); + }); + def(AST_Seq, function(compressor) { + return this.cdr.is_string(compressor); + }); + def(AST_Conditional, function(compressor) { + return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); + }); + def(AST_Call, function(compressor) { + return compressor.option("unsafe") && this.expression instanceof AST_SymbolRef && this.expression.name == "String" && this.expression.undeclared(); + }); + })(function(node, func) { + node.DEFMETHOD("is_string", func); + }); + function best_of(ast1, ast2) { + return ast1.print_to_string().length > ast2.print_to_string().length ? ast2 : ast1; + } + (function(def) { + AST_Node.DEFMETHOD("evaluate", function(compressor) { + if (!compressor.option("evaluate")) return [ this ]; + try { + var val = this._eval(), ast = make_node_from_constant(compressor, val, this); + return [ best_of(ast, this), val ]; + } catch (ex) { + if (ex !== def) throw ex; + return [ this ]; + } + }); + def(AST_Statement, function() { + throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); + }); + def(AST_Function, function() { + throw def; + }); + function ev(node) { + return node._eval(); + } + def(AST_Node, function() { + throw def; + }); + def(AST_Constant, function() { + return this.getValue(); + }); + def(AST_UnaryPrefix, function() { + var e = this.expression; + switch (this.operator) { + case "!": + return !ev(e); + + case "typeof": + if (e instanceof AST_Function) return typeof function() {}; + e = ev(e); + if (e instanceof RegExp) throw def; + return typeof e; + + case "void": + return void ev(e); + + case "~": + return ~ev(e); + + case "-": + e = ev(e); + if (e === 0) throw def; + return -e; + + case "+": + return +ev(e); + } + throw def; + }); + def(AST_Binary, function() { + var left = this.left, right = this.right; + switch (this.operator) { + case "&&": + return ev(left) && ev(right); + + case "||": + return ev(left) || ev(right); + + case "|": + return ev(left) | ev(right); + + case "&": + return ev(left) & ev(right); + + case "^": + return ev(left) ^ ev(right); + + case "+": + return ev(left) + ev(right); + + case "*": + return ev(left) * ev(right); + + case "/": + return ev(left) / ev(right); + + case "%": + return ev(left) % ev(right); + + case "-": + return ev(left) - ev(right); + + case "<<": + return ev(left) << ev(right); + + case ">>": + return ev(left) >> ev(right); + + case ">>>": + return ev(left) >>> ev(right); + + case "==": + return ev(left) == ev(right); + + case "===": + return ev(left) === ev(right); + + case "!=": + return ev(left) != ev(right); + + case "!==": + return ev(left) !== ev(right); + + case "<": + return ev(left) < ev(right); + + case "<=": + return ev(left) <= ev(right); + + case ">": + return ev(left) > ev(right); + + case ">=": + return ev(left) >= ev(right); + + case "in": + return ev(left) in ev(right); + + case "instanceof": + return ev(left) instanceof ev(right); + } + throw def; + }); + def(AST_Conditional, function() { + return ev(this.condition) ? ev(this.consequent) : ev(this.alternative); + }); + def(AST_SymbolRef, function() { + var d = this.definition(); + if (d && d.constant && d.init) return ev(d.init); + throw def; + }); + })(function(node, func) { + node.DEFMETHOD("_eval", func); + }); + (function(def) { + function basic_negation(exp) { + return make_node(AST_UnaryPrefix, exp, { + operator: "!", + expression: exp + }); + } + def(AST_Node, function() { + return basic_negation(this); + }); + def(AST_Statement, function() { + throw new Error("Cannot negate a statement"); + }); + def(AST_Function, function() { + return basic_negation(this); + }); + def(AST_UnaryPrefix, function() { + if (this.operator == "!") return this.expression; + return basic_negation(this); + }); + def(AST_Seq, function(compressor) { + var self = this.clone(); + self.cdr = self.cdr.negate(compressor); + return self; + }); + def(AST_Conditional, function(compressor) { + var self = this.clone(); + self.consequent = self.consequent.negate(compressor); + self.alternative = self.alternative.negate(compressor); + return best_of(basic_negation(this), self); + }); + def(AST_Binary, function(compressor) { + var self = this.clone(), op = this.operator; + if (compressor.option("unsafe_comps")) { + switch (op) { + case "<=": + self.operator = ">"; + return self; + + case "<": + self.operator = ">="; + return self; + + case ">=": + self.operator = "<"; + return self; + + case ">": + self.operator = "<="; + return self; + } + } + switch (op) { + case "==": + self.operator = "!="; + return self; + + case "!=": + self.operator = "=="; + return self; + + case "===": + self.operator = "!=="; + return self; + + case "!==": + self.operator = "==="; + return self; + + case "&&": + self.operator = "||"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + + case "||": + self.operator = "&&"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + } + return basic_negation(this); + }); + })(function(node, func) { + node.DEFMETHOD("negate", function(compressor) { + return func.call(this, compressor); + }); + }); + (function(def) { + def(AST_Node, function() { + return true; + }); + def(AST_EmptyStatement, function() { + return false; + }); + def(AST_Constant, function() { + return false; + }); + def(AST_This, function() { + return false; + }); + def(AST_Block, function() { + for (var i = this.body.length; --i >= 0; ) { + if (this.body[i].has_side_effects()) return true; + } + return false; + }); + def(AST_SimpleStatement, function() { + return this.body.has_side_effects(); + }); + def(AST_Defun, function() { + return true; + }); + def(AST_Function, function() { + return false; + }); + def(AST_Binary, function() { + return this.left.has_side_effects() || this.right.has_side_effects(); + }); + def(AST_Assign, function() { + return true; + }); + def(AST_Conditional, function() { + return this.condition.has_side_effects() || this.consequent.has_side_effects() || this.alternative.has_side_effects(); + }); + def(AST_Unary, function() { + return this.operator == "delete" || this.operator == "++" || this.operator == "--" || this.expression.has_side_effects(); + }); + def(AST_SymbolRef, function() { + return false; + }); + def(AST_Object, function() { + for (var i = this.properties.length; --i >= 0; ) if (this.properties[i].has_side_effects()) return true; + return false; + }); + def(AST_ObjectProperty, function() { + return this.value.has_side_effects(); + }); + def(AST_Array, function() { + for (var i = this.elements.length; --i >= 0; ) if (this.elements[i].has_side_effects()) return true; + return false; + }); + def(AST_PropAccess, function() { + return true; + }); + def(AST_Seq, function() { + return this.car.has_side_effects() || this.cdr.has_side_effects(); + }); + })(function(node, func) { + node.DEFMETHOD("has_side_effects", func); + }); + function aborts(thing) { + return thing && thing.aborts(); + } + (function(def) { + def(AST_Statement, function() { + return null; + }); + def(AST_Jump, function() { + return this; + }); + function block_aborts() { + var n = this.body.length; + return n > 0 && aborts(this.body[n - 1]); + } + def(AST_BlockStatement, block_aborts); + def(AST_SwitchBranch, block_aborts); + def(AST_If, function() { + return this.alternative && aborts(this.body) && aborts(this.alternative); + }); + })(function(node, func) { + node.DEFMETHOD("aborts", func); + }); + OPT(AST_Directive, function(self, compressor) { + if (self.scope.has_directive(self.value) !== self.scope) { + return make_node(AST_EmptyStatement, self); + } + return self; + }); + OPT(AST_Debugger, function(self, compressor) { + if (compressor.option("drop_debugger")) return make_node(AST_EmptyStatement, self); + return self; + }); + OPT(AST_LabeledStatement, function(self, compressor) { + if (self.body instanceof AST_Break && compressor.loopcontrol_target(self.body.label) === self.body) { + return make_node(AST_EmptyStatement, self); + } + return self.label.references.length == 0 ? self.body : self; + }); + OPT(AST_Block, function(self, compressor) { + self.body = tighten_body(self.body, compressor); + return self; + }); + OPT(AST_BlockStatement, function(self, compressor) { + self.body = tighten_body(self.body, compressor); + switch (self.body.length) { + case 1: + return self.body[0]; + + case 0: + return make_node(AST_EmptyStatement, self); + } + return self; + }); + AST_Scope.DEFMETHOD("drop_unused", function(compressor) { + var self = this; + if (compressor.option("unused") && !(self instanceof AST_Toplevel) && !self.uses_eval) { + var in_use = []; + var initializations = new Dictionary(); + var scope = this; + var tw = new TreeWalker(function(node, descend) { + if (node !== self) { + if (node instanceof AST_Defun) { + initializations.add(node.name.name, node); + return true; + } + if (node instanceof AST_Definitions && scope === self) { + node.definitions.forEach(function(def) { + if (def.value) { + initializations.add(def.name.name, def.value); + if (def.value.has_side_effects()) { + def.value.walk(tw); + } + } + }); + return true; + } + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + return true; + } + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(); + scope = save_scope; + return true; + } + } + }); + self.walk(tw); + for (var i = 0; i < in_use.length; ++i) { + in_use[i].orig.forEach(function(decl) { + var init = initializations.get(decl.name); + if (init) init.forEach(function(init) { + var tw = new TreeWalker(function(node) { + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + } + }); + init.walk(tw); + }); + }); + } + var tt = new TreeTransformer(function before(node, descend, in_list) { + if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) { + for (var a = node.argnames, i = a.length; --i >= 0; ) { + var sym = a[i]; + if (sym.unreferenced()) { + a.pop(); + compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { + name: sym.name, + file: sym.start.file, + line: sym.start.line, + col: sym.start.col + }); + } else break; + } + } + if (node instanceof AST_Defun && node !== self) { + if (!member(node.name.definition(), in_use)) { + compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { + name: node.name.name, + file: node.name.start.file, + line: node.name.start.line, + col: node.name.start.col + }); + return make_node(AST_EmptyStatement, node); + } + return node; + } + if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { + var def = node.definitions.filter(function(def) { + if (member(def.name.definition(), in_use)) return true; + var w = { + name: def.name.name, + file: def.name.start.file, + line: def.name.start.line, + col: def.name.start.col + }; + if (def.value && def.value.has_side_effects()) { + def._unused_side_effects = true; + compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); + return true; + } + compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w); + return false; + }); + def = mergeSort(def, function(a, b) { + if (!a.value && b.value) return -1; + if (!b.value && a.value) return 1; + return 0; + }); + var side_effects = []; + for (var i = 0; i < def.length; ) { + var x = def[i]; + if (x._unused_side_effects) { + side_effects.push(x.value); + def.splice(i, 1); + } else { + if (side_effects.length > 0) { + side_effects.push(x.value); + x.value = AST_Seq.from_array(side_effects); + side_effects = []; + } + ++i; + } + } + if (side_effects.length > 0) { + side_effects = make_node(AST_BlockStatement, node, { + body: [ make_node(AST_SimpleStatement, node, { + body: AST_Seq.from_array(side_effects) + }) ] + }); + } else { + side_effects = null; + } + if (def.length == 0 && !side_effects) { + return make_node(AST_EmptyStatement, node); + } + if (def.length == 0) { + return side_effects; + } + node.definitions = def; + if (side_effects) { + side_effects.body.unshift(node); + node = side_effects; + } + return node; + } + if (node instanceof AST_For && node.init instanceof AST_BlockStatement) { + descend(node, this); + var body = node.init.body.slice(0, -1); + node.init = node.init.body.slice(-1)[0].body; + body.push(node); + return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + body: body + }); + } + if (node instanceof AST_Scope && node !== self) return node; + }); + self.transform(tt); + } + }); + AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) { + var hoist_funs = compressor.option("hoist_funs"); + var hoist_vars = compressor.option("hoist_vars"); + var self = this; + if (hoist_funs || hoist_vars) { + var dirs = []; + var hoisted = []; + var vars = new Dictionary(), vars_found = 0, var_decl = 0; + self.walk(new TreeWalker(function(node) { + if (node instanceof AST_Scope && node !== self) return true; + if (node instanceof AST_Var) { + ++var_decl; + return true; + } + })); + hoist_vars = hoist_vars && var_decl > 1; + var tt = new TreeTransformer(function before(node) { + if (node !== self) { + if (node instanceof AST_Directive) { + dirs.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Defun && hoist_funs) { + hoisted.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Var && hoist_vars) { + node.definitions.forEach(function(def) { + vars.set(def.name.name, def); + ++vars_found; + }); + var seq = node.to_assignments(); + var p = tt.parent(); + if (p instanceof AST_ForIn && p.init === node) { + if (seq == null) return node.definitions[0].name; + return seq; + } + if (p instanceof AST_For && p.init === node) { + return seq; + } + if (!seq) return make_node(AST_EmptyStatement, node); + return make_node(AST_SimpleStatement, node, { + body: seq + }); + } + if (node instanceof AST_Scope) return node; + } + }); + self = self.transform(tt); + if (vars_found > 0) { + var defs = []; + vars.each(function(def, name) { + if (self instanceof AST_Lambda && find_if(function(x) { + return x.name == def.name.name; + }, self.argnames)) { + vars.del(name); + } else { + def = def.clone(); + def.value = null; + defs.push(def); + vars.set(name, def); + } + }); + if (defs.length > 0) { + for (var i = 0; i < self.body.length; ) { + if (self.body[i] instanceof AST_SimpleStatement) { + var expr = self.body[i].body, sym, assign; + if (expr instanceof AST_Assign && expr.operator == "=" && (sym = expr.left) instanceof AST_Symbol && vars.has(sym.name)) { + var def = vars.get(sym.name); + if (def.value) break; + def.value = expr.right; + remove(defs, def); + defs.push(def); + self.body.splice(i, 1); + continue; + } + if (expr instanceof AST_Seq && (assign = expr.car) instanceof AST_Assign && assign.operator == "=" && (sym = assign.left) instanceof AST_Symbol && vars.has(sym.name)) { + var def = vars.get(sym.name); + if (def.value) break; + def.value = assign.right; + remove(defs, def); + defs.push(def); + self.body[i].body = expr.cdr; + continue; + } + } + if (self.body[i] instanceof AST_EmptyStatement) { + self.body.splice(i, 1); + continue; + } + if (self.body[i] instanceof AST_BlockStatement) { + var tmp = [ i, 1 ].concat(self.body[i].body); + self.body.splice.apply(self.body, tmp); + continue; + } + break; + } + defs = make_node(AST_Var, self, { + definitions: defs + }); + hoisted.push(defs); + } + } + self.body = dirs.concat(hoisted, self.body); + } + return self; + }); + OPT(AST_SimpleStatement, function(self, compressor) { + if (compressor.option("side_effects")) { + if (!self.body.has_side_effects()) { + compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); + return make_node(AST_EmptyStatement, self); + } + } + return self; + }); + OPT(AST_DWLoop, function(self, compressor) { + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (!compressor.option("loops")) return self; + if (cond.length > 1) { + if (cond[1]) { + return make_node(AST_For, self, { + body: self.body + }); + } else if (self instanceof AST_While) { + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { + body: a + }); + } + } + } + return self; + }); + function if_break_in_loop(self, compressor) { + function drop_it(rest) { + rest = as_statement_array(rest); + if (self.body instanceof AST_BlockStatement) { + self.body = self.body.clone(); + self.body.body = rest.concat(self.body.body.slice(1)); + self.body = self.body.transform(compressor); + } else { + self.body = make_node(AST_BlockStatement, self.body, { + body: rest + }).transform(compressor); + } + if_break_in_loop(self, compressor); + } + var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof AST_If) { + if (first.body instanceof AST_Break && compressor.loopcontrol_target(first.body.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition.negate(compressor) + }); + } else { + self.condition = first.condition.negate(compressor); + } + drop_it(first.alternative); + } else if (first.alternative instanceof AST_Break && compressor.loopcontrol_target(first.alternative.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition + }); + } else { + self.condition = first.condition; + } + drop_it(first.body); + } + } + } + OPT(AST_While, function(self, compressor) { + if (!compressor.option("loops")) return self; + self = AST_DWLoop.prototype.optimize.call(self, compressor); + if (self instanceof AST_While) { + if_break_in_loop(self, compressor); + self = make_node(AST_For, self, self).transform(compressor); + } + return self; + }); + OPT(AST_For, function(self, compressor) { + var cond = self.condition; + if (cond) { + cond = cond.evaluate(compressor); + self.condition = cond[0]; + } + if (!compressor.option("loops")) return self; + if (cond) { + if (cond.length > 1 && !cond[1]) { + if (compressor.option("dead_code")) { + var a = []; + if (self.init instanceof AST_Statement) { + a.push(self.init); + } else if (self.init) { + a.push(make_node(AST_SimpleStatement, self.init, { + body: self.init + })); + } + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { + body: a + }); + } + } + } + if_break_in_loop(self, compressor); + return self; + }); + OPT(AST_If, function(self, compressor) { + if (!compressor.option("conditionals")) return self; + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + if (self.alternative) { + extract_declarations_from_unreachable_code(compressor, self.alternative, a); + } + a.push(self.body); + return make_node(AST_BlockStatement, self, { + body: a + }).transform(compressor); + } + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + if (self.alternative) a.push(self.alternative); + return make_node(AST_BlockStatement, self, { + body: a + }).transform(compressor); + } + } + } + if (is_empty(self.alternative)) self.alternative = null; + var negated = self.condition.negate(compressor); + var negated_is_best = best_of(self.condition, negated) === negated; + if (self.alternative && negated_is_best) { + negated_is_best = false; + self.condition = negated; + var tmp = self.body; + self.body = self.alternative || make_node(AST_EmptyStatement); + self.alternative = tmp; + } + if (is_empty(self.body) && is_empty(self.alternative)) { + return make_node(AST_SimpleStatement, self.condition, { + body: self.condition + }).transform(compressor); + } + if (self.body instanceof AST_SimpleStatement && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: self.body.body, + alternative: self.alternative.body + }) + }).transform(compressor); + } + if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { + if (negated_is_best) return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator: "||", + left: negated, + right: self.body.body + }) + }).transform(compressor); + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator: "&&", + left: self.condition, + right: self.body.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_EmptyStatement && self.alternative && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator: "||", + left: self.condition, + right: self.alternative.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_Exit && self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) { + return make_node(self.body.CTOR, self, { + value: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: self.body.value || make_node(AST_Undefined, self.body).optimize(compressor), + alternative: self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor) + }) + }).transform(compressor); + } + if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) { + self.condition = make_node(AST_Binary, self.condition, { + operator: "&&", + left: self.condition, + right: self.body.condition + }).transform(compressor); + self.body = self.body.body; + } + if (aborts(self.body)) { + if (self.alternative) { + var alt = self.alternative; + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, alt ] + }).transform(compressor); + } + } + if (aborts(self.alternative)) { + var body = self.body; + self.body = self.alternative; + self.condition = negated_is_best ? negated : self.condition.negate(compressor); + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, body ] + }).transform(compressor); + } + return self; + }); + OPT(AST_Switch, function(self, compressor) { + if (self.body.length == 0 && compressor.option("conditionals")) { + return make_node(AST_SimpleStatement, self, { + body: self.expression + }).transform(compressor); + } + for (;;) { + var last_branch = self.body[self.body.length - 1]; + if (last_branch) { + var stat = last_branch.body[last_branch.body.length - 1]; + if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) last_branch.body.pop(); + if (last_branch instanceof AST_Default && last_branch.body.length == 0) { + self.body.pop(); + continue; + } + } + break; + } + var exp = self.expression.evaluate(compressor); + out: if (exp.length == 2) try { + self.expression = exp[0]; + if (!compressor.option("dead_code")) break out; + var value = exp[1]; + var in_if = false; + var in_block = false; + var started = false; + var stopped = false; + var ruined = false; + var tt = new TreeTransformer(function(node, descend, in_list) { + if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) { + return node; + } else if (node instanceof AST_Switch && node === self) { + node = node.clone(); + descend(node, this); + return ruined ? node : make_node(AST_BlockStatement, node, { + body: node.body.reduce(function(a, branch) { + return a.concat(branch.body); + }, []) + }).transform(compressor); + } else if (node instanceof AST_If || node instanceof AST_Try) { + var save = in_if; + in_if = !in_block; + descend(node, this); + in_if = save; + return node; + } else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) { + var save = in_block; + in_block = true; + descend(node, this); + in_block = save; + return node; + } else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) { + if (in_if) { + ruined = true; + return node; + } + if (in_block) return node; + stopped = true; + return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + } else if (node instanceof AST_SwitchBranch && this.parent() === self) { + if (stopped) return MAP.skip; + if (node instanceof AST_Case) { + var exp = node.expression.evaluate(compressor); + if (exp.length < 2) { + throw self; + } + if (exp[1] === value || started) { + started = true; + if (aborts(node)) stopped = true; + descend(node, this); + return node; + } + return MAP.skip; + } + descend(node, this); + return node; + } + }); + tt.stack = compressor.stack.slice(); + self = self.transform(tt); + } catch (ex) { + if (ex !== self) throw ex; + } + return self; + }); + OPT(AST_Case, function(self, compressor) { + self.body = tighten_body(self.body, compressor); + return self; + }); + OPT(AST_Try, function(self, compressor) { + self.body = tighten_body(self.body, compressor); + return self; + }); + AST_Definitions.DEFMETHOD("remove_initializers", function() { + this.definitions.forEach(function(def) { + def.value = null; + }); + }); + AST_Definitions.DEFMETHOD("to_assignments", function() { + var assignments = this.definitions.reduce(function(a, def) { + if (def.value) { + var name = make_node(AST_SymbolRef, def.name, def.name); + a.push(make_node(AST_Assign, def, { + operator: "=", + left: name, + right: def.value + })); + } + return a; + }, []); + if (assignments.length == 0) return null; + return AST_Seq.from_array(assignments); + }); + OPT(AST_Definitions, function(self, compressor) { + if (self.definitions.length == 0) return make_node(AST_EmptyStatement, self); + return self; + }); + OPT(AST_Function, function(self, compressor) { + self = AST_Lambda.prototype.optimize.call(self, compressor); + if (compressor.option("unused")) { + if (self.name && self.name.unreferenced()) { + self.name = null; + } + } + return self; + }); + OPT(AST_Call, function(self, compressor) { + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Array": + if (self.args.length != 1) { + return make_node(AST_Array, self, { + elements: self.args + }); + } + break; + + case "Object": + if (self.args.length == 0) { + return make_node(AST_Object, self, { + properties: [] + }); + } + break; + + case "String": + if (self.args.length == 0) return make_node(AST_String, self, { + value: "" + }); + return make_node(AST_Binary, self, { + left: self.args[0], + operator: "+", + right: make_node(AST_String, self, { + value: "" + }) + }); + + case "Function": + if (all(self.args, function(x) { + return x instanceof AST_String; + })) { + try { + var code = "(function(" + self.args.slice(0, -1).map(function(arg) { + return arg.value; + }).join(",") + "){" + self.args[self.args.length - 1].value + "})()"; + var ast = parse(code); + ast.figure_out_scope(); + var comp = new Compressor(compressor.options); + ast = ast.transform(comp); + ast.figure_out_scope(); + ast.mangle_names(); + var fun = ast.body[0].body.expression; + var args = fun.argnames.map(function(arg, i) { + return make_node(AST_String, self.args[i], { + value: arg.print_to_string() + }); + }); + var code = OutputStream(); + AST_BlockStatement.prototype._codegen.call(fun, fun, code); + code = code.toString().replace(/^\{|\}$/g, ""); + args.push(make_node(AST_String, self.args[self.args.length - 1], { + value: code + })); + self.args = args; + return self; + } catch (ex) { + if (ex instanceof JS_Parse_Error) { + compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start); + compressor.warn(ex.toString()); + } else { + console.log(ex); + } + } + } + break; + } + } else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { + return make_node(AST_Binary, self, { + left: make_node(AST_String, self, { + value: "" + }), + operator: "+", + right: exp.expression + }).transform(compressor); + } + } + if (compressor.option("side_effects")) { + if (self.expression instanceof AST_Function && self.args.length == 0 && !AST_Block.prototype.has_side_effects.call(self.expression)) { + return make_node(AST_Undefined, self).transform(compressor); + } + } + return self; + }); + OPT(AST_New, function(self, compressor) { + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Object": + case "RegExp": + case "Function": + case "Error": + case "Array": + return make_node(AST_Call, self, self).transform(compressor); + } + } + } + return self; + }); + OPT(AST_Seq, function(self, compressor) { + if (!compressor.option("side_effects")) return self; + if (!self.car.has_side_effects()) { + var p; + if (!(self.cdr instanceof AST_SymbolRef && self.cdr.name == "eval" && self.cdr.undeclared() && (p = compressor.parent()) instanceof AST_Call && p.expression === self)) { + return self.cdr; + } + } + if (compressor.option("cascade")) { + if (self.car instanceof AST_Assign && !self.car.left.has_side_effects() && self.car.left.equivalent_to(self.cdr)) { + return self.car; + } + if (!self.car.has_side_effects() && !self.cdr.has_side_effects() && self.car.equivalent_to(self.cdr)) { + return self.car; + } + } + return self; + }); + AST_Unary.DEFMETHOD("lift_sequences", function(compressor) { + if (compressor.option("sequences")) { + if (this.expression instanceof AST_Seq) { + var seq = this.expression; + var x = seq.to_array(); + this.expression = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + OPT(AST_UnaryPostfix, function(self, compressor) { + return self.lift_sequences(compressor); + }); + OPT(AST_UnaryPrefix, function(self, compressor) { + self = self.lift_sequences(compressor); + var e = self.expression; + if (compressor.option("booleans") && compressor.in_boolean_context()) { + switch (self.operator) { + case "!": + if (e instanceof AST_UnaryPrefix && e.operator == "!") { + return e.expression; + } + break; + + case "typeof": + compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (e instanceof AST_Binary && self.operator == "!") { + self = best_of(self, e.negate(compressor)); + } + } + return self.evaluate(compressor)[0]; + }); + AST_Binary.DEFMETHOD("lift_sequences", function(compressor) { + if (compressor.option("sequences")) { + if (this.left instanceof AST_Seq) { + var seq = this.left; + var x = seq.to_array(); + this.left = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + if (this.right instanceof AST_Seq && !(this.operator == "||" || this.operator == "&&") && !this.left.has_side_effects()) { + var seq = this.right; + var x = seq.to_array(); + this.right = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + var commutativeOperators = makePredicate("== === != !== * & | ^"); + OPT(AST_Binary, function(self, compressor) { + var reverse = compressor.has_directive("use asm") ? noop : function(op, force) { + if (force || !(self.left.has_side_effects() || self.right.has_side_effects())) { + if (op) self.operator = op; + var tmp = self.left; + self.left = self.right; + self.right = tmp; + } + }; + if (commutativeOperators(self.operator)) { + if (self.right instanceof AST_Constant && !(self.left instanceof AST_Constant)) { + reverse(null, true); + } + } + self = self.lift_sequences(compressor); + if (compressor.option("comparisons")) switch (self.operator) { + case "===": + case "!==": + if (self.left.is_string(compressor) && self.right.is_string(compressor) || self.left.is_boolean() && self.right.is_boolean()) { + self.operator = self.operator.substr(0, 2); + } + + case "==": + case "!=": + if (self.left instanceof AST_String && self.left.value == "undefined" && self.right instanceof AST_UnaryPrefix && self.right.operator == "typeof" && compressor.option("unsafe")) { + if (!(self.right.expression instanceof AST_SymbolRef) || !self.right.expression.undeclared()) { + self.right = self.right.expression; + self.left = make_node(AST_Undefined, self.left).optimize(compressor); + if (self.operator.length == 2) self.operator += "="; + } + } + break; + } + if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) { + case "&&": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if (ll.length > 1 && !ll[1] || rr.length > 1 && !rr[1]) { + compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); + return make_node(AST_False, self); + } + if (ll.length > 1 && ll[1]) { + return rr[0]; + } + if (rr.length > 1 && rr[1]) { + return ll[0]; + } + break; + + case "||": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if (ll.length > 1 && ll[1] || rr.length > 1 && rr[1]) { + compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (ll.length > 1 && !ll[1]) { + return rr[0]; + } + if (rr.length > 1 && !rr[1]) { + return ll[0]; + } + break; + + case "+": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if (ll.length > 1 && ll[0] instanceof AST_String && ll[1] || rr.length > 1 && rr[0] instanceof AST_String && rr[1]) { + compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + break; + } + var exp = self.evaluate(compressor); + if (exp.length > 1) { + if (best_of(exp[0], self) !== self) return exp[0]; + } + if (compressor.option("comparisons")) { + if (!(compressor.parent() instanceof AST_Binary) || compressor.parent() instanceof AST_Assign) { + var negated = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: self.negate(compressor) + }); + self = best_of(self, negated); + } + switch (self.operator) { + case "<": + reverse(">"); + break; + + case "<=": + reverse(">="); + break; + } + } + if (self.operator == "+" && self.right instanceof AST_String && self.right.getValue() === "" && self.left instanceof AST_Binary && self.left.operator == "+" && self.left.is_string(compressor)) { + return self.left; + } + return self; + }); + OPT(AST_SymbolRef, function(self, compressor) { + if (self.undeclared()) { + var defines = compressor.option("global_defs"); + if (defines && defines.hasOwnProperty(self.name)) { + return make_node_from_constant(compressor, defines[self.name], self); + } + switch (self.name) { + case "undefined": + return make_node(AST_Undefined, self); + + case "NaN": + return make_node(AST_NaN, self); + + case "Infinity": + return make_node(AST_Infinity, self); + } + } + return self; + }); + OPT(AST_Undefined, function(self, compressor) { + if (compressor.option("unsafe")) { + var scope = compressor.find_parent(AST_Scope); + var undef = scope.find_variable("undefined"); + if (undef) { + var ref = make_node(AST_SymbolRef, self, { + name: "undefined", + scope: scope, + thedef: undef + }); + ref.reference(); + return ref; + } + } + return self; + }); + var ASSIGN_OPS = [ "+", "-", "/", "*", "%", ">>", "<<", ">>>", "|", "^", "&" ]; + OPT(AST_Assign, function(self, compressor) { + self = self.lift_sequences(compressor); + if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary && self.right.left instanceof AST_SymbolRef && self.right.left.name == self.left.name && member(self.right.operator, ASSIGN_OPS)) { + self.operator = self.right.operator + "="; + self.right = self.right.right; + } + return self; + }); + OPT(AST_Conditional, function(self, compressor) { + if (!compressor.option("conditionals")) return self; + if (self.condition instanceof AST_Seq) { + var car = self.condition.car; + self.condition = self.condition.cdr; + return AST_Seq.cons(car, self); + } + var cond = self.condition.evaluate(compressor); + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.start); + return self.consequent; + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.start); + return self.alternative; + } + } + var negated = cond[0].negate(compressor); + if (best_of(cond[0], negated) === negated) { + self = make_node(AST_Conditional, self, { + condition: negated, + consequent: self.alternative, + alternative: self.consequent + }); + } + var consequent = self.consequent; + var alternative = self.alternative; + if (consequent instanceof AST_Assign && alternative instanceof AST_Assign && consequent.operator == alternative.operator && consequent.left.equivalent_to(alternative.left)) { + self = make_node(AST_Assign, self, { + operator: consequent.operator, + left: consequent.left, + right: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: consequent.right, + alternative: alternative.right + }) + }); + } + return self; + }); + OPT(AST_Boolean, function(self, compressor) { + if (compressor.option("booleans")) { + var p = compressor.parent(); + if (p instanceof AST_Binary && (p.operator == "==" || p.operator == "!=")) { + compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { + operator: p.operator, + value: self.value, + file: p.start.file, + line: p.start.line, + col: p.start.col + }); + return make_node(AST_Number, self, { + value: +self.value + }); + } + return make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: make_node(AST_Number, self, { + value: 1 - self.value + }) + }); + } + return self; + }); + OPT(AST_Sub, function(self, compressor) { + var prop = self.property; + if (prop instanceof AST_String && compressor.option("properties")) { + prop = prop.getValue(); + if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) { + return make_node(AST_Dot, self, { + expression: self.expression, + property: prop + }); + } + } + return self; + }); + function literals_in_boolean_context(self, compressor) { + if (compressor.option("booleans") && compressor.in_boolean_context()) { + return make_node(AST_True, self); + } + return self; + } + OPT(AST_Array, literals_in_boolean_context); + OPT(AST_Object, literals_in_boolean_context); + OPT(AST_RegExp, literals_in_boolean_context); + })(); + "use strict"; + function SourceMap(options) { + options = defaults(options, { + file: null, + root: null, + orig: null + }); + var generator = new MOZ_SourceMap.SourceMapGenerator({ + file: options.file, + sourceRoot: options.root + }); + var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); + function add(source, gen_line, gen_col, orig_line, orig_col, name) { + if (orig_map) { + var info = orig_map.originalPositionFor({ + line: orig_line, + column: orig_col + }); + source = info.source; + orig_line = info.line; + orig_col = info.column; + name = info.name; + } + generator.addMapping({ + generated: { + line: gen_line, + column: gen_col + }, + original: { + line: orig_line, + column: orig_col + }, + source: source, + name: name + }); + } + return { + add: add, + get: function() { + return generator; + }, + toString: function() { + return generator.toString(); + } + }; + } + "use strict"; + (function() { + var MOZ_TO_ME = { + TryStatement: function(M) { + return new AST_Try({ + start: my_start_token(M), + end: my_end_token(M), + body: from_moz(M.block).body, + bcatch: from_moz(M.handlers[0]), + bfinally: M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + }); + }, + CatchClause: function(M) { + return new AST_Catch({ + start: my_start_token(M), + end: my_end_token(M), + argname: from_moz(M.param), + body: from_moz(M.body).body + }); + }, + ObjectExpression: function(M) { + return new AST_Object({ + start: my_start_token(M), + end: my_end_token(M), + properties: M.properties.map(function(prop) { + var key = prop.key; + var name = key.type == "Identifier" ? key.name : key.value; + var args = { + start: my_start_token(key), + end: my_end_token(prop.value), + key: name, + value: from_moz(prop.value) + }; + switch (prop.kind) { + case "init": + return new AST_ObjectKeyVal(args); + + case "set": + args.value.name = from_moz(key); + return new AST_ObjectSetter(args); + + case "get": + args.value.name = from_moz(key); + return new AST_ObjectGetter(args); + } + }) + }); + }, + SequenceExpression: function(M) { + return AST_Seq.from_array(M.expressions.map(from_moz)); + }, + MemberExpression: function(M) { + return new (M.computed ? AST_Sub : AST_Dot)({ + start: my_start_token(M), + end: my_end_token(M), + property: M.computed ? from_moz(M.property) : M.property.name, + expression: from_moz(M.object) + }); + }, + SwitchCase: function(M) { + return new (M.test ? AST_Case : AST_Default)({ + start: my_start_token(M), + end: my_end_token(M), + expression: from_moz(M.test), + body: M.consequent.map(from_moz) + }); + }, + Literal: function(M) { + var val = M.value, args = { + start: my_start_token(M), + end: my_end_token(M) + }; + if (val === null) return new AST_Null(args); + switch (typeof val) { + case "string": + args.value = val; + return new AST_String(args); + + case "number": + args.value = val; + return new AST_Number(args); + + case "boolean": + return new (val ? AST_True : AST_False)(args); + + default: + args.value = val; + return new AST_RegExp(args); + } + }, + UnaryExpression: From_Moz_Unary, + UpdateExpression: From_Moz_Unary, + Identifier: function(M) { + var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; + return new (M.name == "this" ? AST_This : p.type == "LabeledStatement" ? AST_Label : p.type == "VariableDeclarator" && p.id === M ? p.kind == "const" ? AST_SymbolConst : AST_SymbolVar : p.type == "FunctionExpression" ? p.id === M ? AST_SymbolLambda : AST_SymbolFunarg : p.type == "FunctionDeclaration" ? p.id === M ? AST_SymbolDefun : AST_SymbolFunarg : p.type == "CatchClause" ? AST_SymbolCatch : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef : AST_SymbolRef)({ + start: my_start_token(M), + end: my_end_token(M), + name: M.name + }); + } + }; + function From_Moz_Unary(M) { + var prefix = "prefix" in M ? M.prefix : M.type == "UnaryExpression" ? true : false; + return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + start: my_start_token(M), + end: my_end_token(M), + operator: M.operator, + expression: from_moz(M.argument) + }); + } + var ME_TO_MOZ = {}; + map("Node", AST_Node); + map("Program", AST_Toplevel, "body@body"); + map("Function", AST_Function, "id>name, params@argnames, body%body"); + map("EmptyStatement", AST_EmptyStatement); + map("BlockStatement", AST_BlockStatement, "body@body"); + map("ExpressionStatement", AST_SimpleStatement, "expression>body"); + map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); + map("BreakStatement", AST_Break, "label>label"); + map("ContinueStatement", AST_Continue, "label>label"); + map("WithStatement", AST_With, "object>expression, body>body"); + map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", AST_Return, "argument>value"); + map("ThrowStatement", AST_Throw, "argument>value"); + map("WhileStatement", AST_While, "test>condition, body>body"); + map("DoWhileStatement", AST_Do, "test>condition, body>body"); + map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); + map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); + map("DebuggerStatement", AST_Debugger); + map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body"); + map("VariableDeclaration", AST_Var, "declarations@definitions"); + map("VariableDeclarator", AST_VarDef, "id>name, init>value"); + map("ThisExpression", AST_This); + map("ArrayExpression", AST_Array, "elements@elements"); + map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body"); + map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); + map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); + map("NewExpression", AST_New, "callee>expression, arguments@args"); + map("CallExpression", AST_Call, "callee>expression, arguments@args"); + function my_start_token(moznode) { + return new AST_Token({ + file: moznode.loc && moznode.loc.source, + line: moznode.loc && moznode.loc.start.line, + col: moznode.loc && moznode.loc.start.column, + pos: moznode.start, + endpos: moznode.start + }); + } + function my_end_token(moznode) { + return new AST_Token({ + file: moznode.loc && moznode.loc.source, + line: moznode.loc && moznode.loc.end.line, + col: moznode.loc && moznode.loc.end.column, + pos: moznode.end, + endpos: moznode.end + }); + } + function map(moztype, mytype, propmap) { + var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; + moz_to_me += "return new mytype({\n" + "start: my_start_token(M),\n" + "end: my_end_token(M)"; + if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) { + var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); + if (!m) throw new Error("Can't understand property map: " + prop); + var moz = "M." + m[1], how = m[2], my = m[3]; + moz_to_me += ",\n" + my + ": "; + if (how == "@") { + moz_to_me += moz + ".map(from_moz)"; + } else if (how == ">") { + moz_to_me += "from_moz(" + moz + ")"; + } else if (how == "=") { + moz_to_me += moz; + } else if (how == "%") { + moz_to_me += "from_moz(" + moz + ").body"; + } else throw new Error("Can't understand operator in propmap: " + prop); + }); + moz_to_me += "\n})}"; + moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(mytype, my_start_token, my_end_token, from_moz); + return MOZ_TO_ME[moztype] = moz_to_me; + } + var FROM_MOZ_STACK = null; + function from_moz(node) { + FROM_MOZ_STACK.push(node); + var ret = node != null ? MOZ_TO_ME[node.type](node) : null; + FROM_MOZ_STACK.pop(); + return ret; + } + AST_Node.from_mozilla_ast = function(node) { + var save_stack = FROM_MOZ_STACK; + FROM_MOZ_STACK = []; + var ast = from_moz(node); + FROM_MOZ_STACK = save_stack; + return ast; + }; + })(); + exports["array_to_hash"] = array_to_hash; + exports["slice"] = slice; + exports["characters"] = characters; + exports["member"] = member; + exports["find_if"] = find_if; + exports["repeat_string"] = repeat_string; + exports["DefaultsError"] = DefaultsError; + exports["defaults"] = defaults; + exports["merge"] = merge; + exports["noop"] = noop; + exports["MAP"] = MAP; + exports["push_uniq"] = push_uniq; + exports["string_template"] = string_template; + exports["remove"] = remove; + exports["mergeSort"] = mergeSort; + exports["set_difference"] = set_difference; + exports["set_intersection"] = set_intersection; + exports["makePredicate"] = makePredicate; + exports["all"] = all; + exports["Dictionary"] = Dictionary; + exports["DEFNODE"] = DEFNODE; + exports["AST_Token"] = AST_Token; + exports["AST_Node"] = AST_Node; + exports["AST_Statement"] = AST_Statement; + exports["AST_Debugger"] = AST_Debugger; + exports["AST_Directive"] = AST_Directive; + exports["AST_SimpleStatement"] = AST_SimpleStatement; + exports["walk_body"] = walk_body; + exports["AST_Block"] = AST_Block; + exports["AST_BlockStatement"] = AST_BlockStatement; + exports["AST_EmptyStatement"] = AST_EmptyStatement; + exports["AST_StatementWithBody"] = AST_StatementWithBody; + exports["AST_LabeledStatement"] = AST_LabeledStatement; + exports["AST_DWLoop"] = AST_DWLoop; + exports["AST_Do"] = AST_Do; + exports["AST_While"] = AST_While; + exports["AST_For"] = AST_For; + exports["AST_ForIn"] = AST_ForIn; + exports["AST_With"] = AST_With; + exports["AST_Scope"] = AST_Scope; + exports["AST_Toplevel"] = AST_Toplevel; + exports["AST_Lambda"] = AST_Lambda; + exports["AST_Accessor"] = AST_Accessor; + exports["AST_Function"] = AST_Function; + exports["AST_Defun"] = AST_Defun; + exports["AST_Jump"] = AST_Jump; + exports["AST_Exit"] = AST_Exit; + exports["AST_Return"] = AST_Return; + exports["AST_Throw"] = AST_Throw; + exports["AST_LoopControl"] = AST_LoopControl; + exports["AST_Break"] = AST_Break; + exports["AST_Continue"] = AST_Continue; + exports["AST_If"] = AST_If; + exports["AST_Switch"] = AST_Switch; + exports["AST_SwitchBranch"] = AST_SwitchBranch; + exports["AST_Default"] = AST_Default; + exports["AST_Case"] = AST_Case; + exports["AST_Try"] = AST_Try; + exports["AST_Catch"] = AST_Catch; + exports["AST_Finally"] = AST_Finally; + exports["AST_Definitions"] = AST_Definitions; + exports["AST_Var"] = AST_Var; + exports["AST_Const"] = AST_Const; + exports["AST_VarDef"] = AST_VarDef; + exports["AST_Call"] = AST_Call; + exports["AST_New"] = AST_New; + exports["AST_Seq"] = AST_Seq; + exports["AST_PropAccess"] = AST_PropAccess; + exports["AST_Dot"] = AST_Dot; + exports["AST_Sub"] = AST_Sub; + exports["AST_Unary"] = AST_Unary; + exports["AST_UnaryPrefix"] = AST_UnaryPrefix; + exports["AST_UnaryPostfix"] = AST_UnaryPostfix; + exports["AST_Binary"] = AST_Binary; + exports["AST_Conditional"] = AST_Conditional; + exports["AST_Assign"] = AST_Assign; + exports["AST_Array"] = AST_Array; + exports["AST_Object"] = AST_Object; + exports["AST_ObjectProperty"] = AST_ObjectProperty; + exports["AST_ObjectKeyVal"] = AST_ObjectKeyVal; + exports["AST_ObjectSetter"] = AST_ObjectSetter; + exports["AST_ObjectGetter"] = AST_ObjectGetter; + exports["AST_Symbol"] = AST_Symbol; + exports["AST_SymbolAccessor"] = AST_SymbolAccessor; + exports["AST_SymbolDeclaration"] = AST_SymbolDeclaration; + exports["AST_SymbolVar"] = AST_SymbolVar; + exports["AST_SymbolConst"] = AST_SymbolConst; + exports["AST_SymbolFunarg"] = AST_SymbolFunarg; + exports["AST_SymbolDefun"] = AST_SymbolDefun; + exports["AST_SymbolLambda"] = AST_SymbolLambda; + exports["AST_SymbolCatch"] = AST_SymbolCatch; + exports["AST_Label"] = AST_Label; + exports["AST_SymbolRef"] = AST_SymbolRef; + exports["AST_LabelRef"] = AST_LabelRef; + exports["AST_This"] = AST_This; + exports["AST_Constant"] = AST_Constant; + exports["AST_String"] = AST_String; + exports["AST_Number"] = AST_Number; + exports["AST_RegExp"] = AST_RegExp; + exports["AST_Atom"] = AST_Atom; + exports["AST_Null"] = AST_Null; + exports["AST_NaN"] = AST_NaN; + exports["AST_Undefined"] = AST_Undefined; + exports["AST_Hole"] = AST_Hole; + exports["AST_Infinity"] = AST_Infinity; + exports["AST_Boolean"] = AST_Boolean; + exports["AST_False"] = AST_False; + exports["AST_True"] = AST_True; + exports["TreeWalker"] = TreeWalker; + exports["KEYWORDS"] = KEYWORDS; + exports["KEYWORDS_ATOM"] = KEYWORDS_ATOM; + exports["RESERVED_WORDS"] = RESERVED_WORDS; + exports["KEYWORDS_BEFORE_EXPRESSION"] = KEYWORDS_BEFORE_EXPRESSION; + exports["OPERATOR_CHARS"] = OPERATOR_CHARS; + exports["RE_HEX_NUMBER"] = RE_HEX_NUMBER; + exports["RE_OCT_NUMBER"] = RE_OCT_NUMBER; + exports["RE_DEC_NUMBER"] = RE_DEC_NUMBER; + exports["OPERATORS"] = OPERATORS; + exports["WHITESPACE_CHARS"] = WHITESPACE_CHARS; + exports["PUNC_BEFORE_EXPRESSION"] = PUNC_BEFORE_EXPRESSION; + exports["PUNC_CHARS"] = PUNC_CHARS; + exports["REGEXP_MODIFIERS"] = REGEXP_MODIFIERS; + exports["UNICODE"] = UNICODE; + exports["is_letter"] = is_letter; + exports["is_digit"] = is_digit; + exports["is_alphanumeric_char"] = is_alphanumeric_char; + exports["is_unicode_combining_mark"] = is_unicode_combining_mark; + exports["is_unicode_connector_punctuation"] = is_unicode_connector_punctuation; + exports["is_identifier"] = is_identifier; + exports["is_identifier_start"] = is_identifier_start; + exports["is_identifier_char"] = is_identifier_char; + exports["is_identifier_string"] = is_identifier_string; + exports["parse_js_number"] = parse_js_number; + exports["JS_Parse_Error"] = JS_Parse_Error; + exports["js_error"] = js_error; + exports["is_token"] = is_token; + exports["EX_EOF"] = EX_EOF; + exports["tokenizer"] = tokenizer; + exports["UNARY_PREFIX"] = UNARY_PREFIX; + exports["UNARY_POSTFIX"] = UNARY_POSTFIX; + exports["ASSIGNMENT"] = ASSIGNMENT; + exports["PRECEDENCE"] = PRECEDENCE; + exports["STATEMENTS_WITH_LABELS"] = STATEMENTS_WITH_LABELS; + exports["ATOMIC_START_TOKEN"] = ATOMIC_START_TOKEN; + exports["parse"] = parse; + exports["TreeTransformer"] = TreeTransformer; + exports["SymbolDef"] = SymbolDef; + exports["base54"] = base54; + exports["OutputStream"] = OutputStream; + exports["Compressor"] = Compressor; + exports["SourceMap"] = SourceMap; +})({}, function() { + return exports; +}()); + +var UglifyJS = exports.UglifyJS; + +UglifyJS.AST_Node.warn_function = function(txt) { + logger.error("uglifyjs2 WARN: " + txt); +}; + +//JRB: MODIFIED FROM UGLIFY SOURCE +//to take a name for the file, and then set toplevel.filename to be that name. +exports.minify = function(files, options, name) { + options = UglifyJS.defaults(options, { + outSourceMap : null, + sourceRoot : null, + inSourceMap : null, + fromString : false, + warnings : false, + mangle : {}, + output : null, + compress : {} + }); + if (typeof files == "string") + files = [ files ]; + + UglifyJS.base54.reset(); + + // 1. parse + var toplevel = null; + files.forEach(function(file){ + var code = options.fromString + ? file + : rjsFile.readFile(file, "utf8"); + toplevel = UglifyJS.parse(code, { + filename: options.fromString ? name : file, + toplevel: toplevel + }); + }); + + // 2. compress + if (options.compress) { + var compress = { warnings: options.warnings }; + UglifyJS.merge(compress, options.compress); + toplevel.figure_out_scope(); + var sq = UglifyJS.Compressor(compress); + toplevel = toplevel.transform(sq); + } + + // 3. mangle + if (options.mangle) { + toplevel.figure_out_scope(); + toplevel.compute_char_frequency(); + toplevel.mangle_names(options.mangle); + } + + // 4. output + var inMap = options.inSourceMap; + var output = {}; + if (typeof options.inSourceMap == "string") { + inMap = rjsFile.readFile(options.inSourceMap, "utf8"); + } + if (options.outSourceMap) { + output.source_map = UglifyJS.SourceMap({ + file: options.outSourceMap, + orig: inMap, + root: options.sourceRoot + }); + } + if (options.output) { + UglifyJS.merge(output, options.output); + } + var stream = UglifyJS.OutputStream(output); + toplevel.print(stream); + return { + code : stream + "", + map : output.source_map + "" + }; +}; + +// exports.describe_ast = function() { +// function doitem(ctor) { +// var sub = {}; +// ctor.SUBCLASSES.forEach(function(ctor){ +// sub[ctor.TYPE] = doitem(ctor); +// }); +// var ret = {}; +// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; +// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; +// return ret; +// } +// return doitem(UglifyJS.AST_Node).sub; +// } + +exports.describe_ast = function() { + var out = UglifyJS.OutputStream({ beautify: true }); + function doitem(ctor) { + out.print("AST_" + ctor.TYPE); + var props = ctor.SELF_PROPS.filter(function(prop){ + return !/^\$/.test(prop); + }); + if (props.length > 0) { + out.space(); + out.with_parens(function(){ + props.forEach(function(prop, i){ + if (i) out.space(); + out.print(prop); + }); + }); + } + if (ctor.documentation) { + out.space(); + out.print_string(ctor.documentation); + } + if (ctor.SUBCLASSES.length > 0) { + out.space(); + out.with_block(function(){ + ctor.SUBCLASSES.forEach(function(ctor, i){ + out.indent(); + doitem(ctor); + out.newline(); + }); + }); + } + }; + doitem(UglifyJS.AST_Node); + return out + ""; +}; + +}); +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint plusplus: true */ +/*global define: false */ + +define('parse', ['./esprimaAdapter', 'lang'], function (esprima, lang) { + 'use strict'; + + function arrayToString(ary) { + var output = '['; + if (ary) { + ary.forEach(function (item, i) { + output += (i > 0 ? ',' : '') + '"' + lang.jsEscape(item) + '"'; + }); + } + output += ']'; + + return output; + } + + //This string is saved off because JSLint complains + //about obj.arguments use, as 'reserved word' + var argPropName = 'arguments'; + + //From an esprima example for traversing its ast. + function traverse(object, visitor) { + var key, child; + + if (!object) { + return; + } + + if (visitor.call(null, object) === false) { + return false; + } + for (key in object) { + if (object.hasOwnProperty(key)) { + child = object[key]; + if (typeof child === 'object' && child !== null) { + if (traverse(child, visitor) === false) { + return false; + } + } + } + } + } + + //Like traverse, but visitor returning false just + //stops that subtree analysis, not the rest of tree + //visiting. + function traverseBroad(object, visitor) { + var key, child; + + if (!object) { + return; + } + + if (visitor.call(null, object) === false) { + return false; + } + for (key in object) { + if (object.hasOwnProperty(key)) { + child = object[key]; + if (typeof child === 'object' && child !== null) { + traverse(child, visitor); + } + } + } + } + + /** + * Pulls out dependencies from an array literal with just string members. + * If string literals, will just return those string values in an array, + * skipping other items in the array. + * + * @param {Node} node an AST node. + * + * @returns {Array} an array of strings. + * If null is returned, then it means the input node was not a valid + * dependency. + */ + function getValidDeps(node) { + if (!node || node.type !== 'ArrayExpression' || !node.elements) { + return; + } + + var deps = []; + + node.elements.some(function (elem) { + if (elem.type === 'Literal') { + deps.push(elem.value); + } + }); + + return deps.length ? deps : undefined; + } + + /** + * Main parse function. Returns a string of any valid require or + * define/require.def calls as part of one JavaScript source string. + * @param {String} moduleName the module name that represents this file. + * It is used to create a default define if there is not one already for the + * file. This allows properly tracing dependencies for builds. Otherwise, if + * the file just has a require() call, the file dependencies will not be + * properly reflected: the file will come before its dependencies. + * @param {String} moduleName + * @param {String} fileName + * @param {String} fileContents + * @param {Object} options optional options. insertNeedsDefine: true will + * add calls to require.needsDefine() if appropriate. + * @returns {String} JS source string or null, if no require or + * define/require.def calls are found. + */ + function parse(moduleName, fileName, fileContents, options) { + options = options || {}; + + //Set up source input + var i, moduleCall, depString, + moduleDeps = [], + result = '', + moduleList = [], + needsDefine = true, + astRoot = esprima.parse(fileContents); + + parse.recurse(astRoot, function (callName, config, name, deps) { + if (!deps) { + deps = []; + } + + if (callName === 'define' && (!name || name === moduleName)) { + needsDefine = false; + } + + if (!name) { + //If there is no module name, the dependencies are for + //this file/default module name. + moduleDeps = moduleDeps.concat(deps); + } else { + moduleList.push({ + name: name, + deps: deps + }); + } + + //If define was found, no need to dive deeper, unless + //the config explicitly wants to dig deeper. + return !!options.findNestedDependencies; + }, options); + + if (options.insertNeedsDefine && needsDefine) { + result += 'require.needsDefine("' + moduleName + '");'; + } + + if (moduleDeps.length || moduleList.length) { + for (i = 0; i < moduleList.length; i++) { + moduleCall = moduleList[i]; + if (result) { + result += '\n'; + } + + //If this is the main module for this file, combine any + //"anonymous" dependencies (could come from a nested require + //call) with this module. + if (moduleCall.name === moduleName) { + moduleCall.deps = moduleCall.deps.concat(moduleDeps); + moduleDeps = []; + } + + depString = arrayToString(moduleCall.deps); + result += 'define("' + moduleCall.name + '",' + + depString + ');'; + } + if (moduleDeps.length) { + if (result) { + result += '\n'; + } + depString = arrayToString(moduleDeps); + result += 'define("' + moduleName + '",' + depString + ');'; + } + } + + return result || null; + } + + parse.traverse = traverse; + parse.traverseBroad = traverseBroad; + + /** + * Handles parsing a file recursively for require calls. + * @param {Array} parentNode the AST node to start with. + * @param {Function} onMatch function to call on a parse match. + * @param {Object} [options] This is normally the build config options if + * it is passed. + */ + parse.recurse = function (object, onMatch, options) { + //Like traverse, but skips if branches that would not be processed + //after has application that results in tests of true or false boolean + //literal values. + var key, child, + hasHas = options && options.has; + + if (!object) { + return; + } + + //If has replacement has resulted in if(true){} or if(false){}, take + //the appropriate branch and skip the other one. + if (hasHas && object.type === 'IfStatement' && object.test.type && + object.test.type === 'Literal') { + if (object.test.value) { + //Take the if branch + this.recurse(object.consequent, onMatch, options); + } else { + //Take the else branch + this.recurse(object.alternate, onMatch, options); + } + } else { + if (this.parseNode(object, onMatch) === false) { + return; + } + for (key in object) { + if (object.hasOwnProperty(key)) { + child = object[key]; + if (typeof child === 'object' && child !== null) { + this.recurse(child, onMatch, options); + } + } + } + } + }; + + /** + * Determines if the file defines the require/define module API. + * Specifically, it looks for the `define.amd = ` expression. + * @param {String} fileName + * @param {String} fileContents + * @returns {Boolean} + */ + parse.definesRequire = function (fileName, fileContents) { + var found = false; + + traverse(esprima.parse(fileContents), function (node) { + if (parse.hasDefineAmd(node)) { + found = true; + + //Stop traversal + return false; + } + }); + + return found; + }; + + /** + * Finds require("") calls inside a CommonJS anonymous module wrapped in a + * define(function(require, exports, module){}) wrapper. These dependencies + * will be added to a modified define() call that lists the dependencies + * on the outside of the function. + * @param {String} fileName + * @param {String|Object} fileContents: a string of contents, or an already + * parsed AST tree. + * @returns {Array} an array of module names that are dependencies. Always + * returns an array, but could be of length zero. + */ + parse.getAnonDeps = function (fileName, fileContents) { + var astRoot = typeof fileContents === 'string' ? + esprima.parse(fileContents) : fileContents, + defFunc = this.findAnonDefineFactory(astRoot); + + return parse.getAnonDepsFromNode(defFunc); + }; + + /** + * Finds require("") calls inside a CommonJS anonymous module wrapped + * in a define function, given an AST node for the definition function. + * @param {Node} node the AST node for the definition function. + * @returns {Array} and array of dependency names. Can be of zero length. + */ + parse.getAnonDepsFromNode = function (node) { + var deps = [], + funcArgLength; + + if (node) { + this.findRequireDepNames(node, deps); + + //If no deps, still add the standard CommonJS require, exports, + //module, in that order, to the deps, but only if specified as + //function args. In particular, if exports is used, it is favored + //over the return value of the function, so only add it if asked. + funcArgLength = node.params && node.params.length; + if (funcArgLength) { + deps = (funcArgLength > 1 ? ["require", "exports", "module"] : + ["require"]).concat(deps); + } + } + return deps; + }; + + parse.isDefineNodeWithArgs = function (node) { + return node && node.type === 'CallExpression' && + node.callee && node.callee.type === 'Identifier' && + node.callee.name === 'define' && node[argPropName]; + }; + + /** + * Finds the function in define(function (require, exports, module){}); + * @param {Array} node + * @returns {Boolean} + */ + parse.findAnonDefineFactory = function (node) { + var match; + + traverse(node, function (node) { + var arg0, arg1; + + if (parse.isDefineNodeWithArgs(node)) { + + //Just the factory function passed to define + arg0 = node[argPropName][0]; + if (arg0 && arg0.type === 'FunctionExpression') { + match = arg0; + return false; + } + + //A string literal module ID followed by the factory function. + arg1 = node[argPropName][1]; + if (arg0.type === 'Literal' && + arg1 && arg1.type === 'FunctionExpression') { + match = arg1; + return false; + } + } + }); + + return match; + }; + + /** + * Finds any config that is passed to requirejs. That includes calls to + * require/requirejs.config(), as well as require({}, ...) and + * requirejs({}, ...) + * @param {String} fileContents + * + * @returns {Object} a config details object with the following properties: + * - config: {Object} the config object found. Can be undefined if no + * config found. + * - range: {Array} the start index and end index in the contents where + * the config was found. Can be undefined if no config found. + * Can throw an error if the config in the file cannot be evaluated in + * a build context to valid JavaScript. + */ + parse.findConfig = function (fileContents) { + /*jslint evil: true */ + var jsConfig, foundConfig, stringData, foundRange, quote, quoteMatch, + quoteRegExp = /(:\s|\[\s*)(['"])/, + astRoot = esprima.parse(fileContents, { + loc: true + }); + + traverse(astRoot, function (node) { + var arg, + requireType = parse.hasRequire(node); + + if (requireType && (requireType === 'require' || + requireType === 'requirejs' || + requireType === 'requireConfig' || + requireType === 'requirejsConfig')) { + + arg = node[argPropName] && node[argPropName][0]; + + if (arg && arg.type === 'ObjectExpression') { + stringData = parse.nodeToString(fileContents, arg); + jsConfig = stringData.value; + foundRange = stringData.range; + return false; + } + } else { + arg = parse.getRequireObjectLiteral(node); + if (arg) { + stringData = parse.nodeToString(fileContents, arg); + jsConfig = stringData.value; + foundRange = stringData.range; + return false; + } + } + }); + + if (jsConfig) { + // Eval the config + quoteMatch = quoteRegExp.exec(jsConfig); + quote = (quoteMatch && quoteMatch[2]) || '"'; + foundConfig = eval('(' + jsConfig + ')'); + } + + return { + config: foundConfig, + range: foundRange, + quote: quote + }; + }; + + /** Returns the node for the object literal assigned to require/requirejs, + * for holding a declarative config. + */ + parse.getRequireObjectLiteral = function (node) { + if (node.id && node.id.type === 'Identifier' && + (node.id.name === 'require' || node.id.name === 'requirejs') && + node.init && node.init.type === 'ObjectExpression') { + return node.init; + } + }; + + /** + * Renames require/requirejs/define calls to be ns + '.' + require/requirejs/define + * Does *not* do .config calls though. See pragma.namespace for the complete + * set of namespace transforms. This function is used because require calls + * inside a define() call should not be renamed, so a simple regexp is not + * good enough. + * @param {String} fileContents the contents to transform. + * @param {String} ns the namespace, *not* including trailing dot. + * @return {String} the fileContents with the namespace applied + */ + parse.renameNamespace = function (fileContents, ns) { + var lines, + locs = [], + astRoot = esprima.parse(fileContents, { + loc: true + }); + + parse.recurse(astRoot, function (callName, config, name, deps, node) { + locs.push(node.loc); + //Do not recurse into define functions, they should be using + //local defines. + return callName !== 'define'; + }, {}); + + if (locs.length) { + lines = fileContents.split('\n'); + + //Go backwards through the found locs, adding in the namespace name + //in front. + locs.reverse(); + locs.forEach(function (loc) { + var startIndex = loc.start.column, + //start.line is 1-based, not 0 based. + lineIndex = loc.start.line - 1, + line = lines[lineIndex]; + + lines[lineIndex] = line.substring(0, startIndex) + + ns + '.' + + line.substring(startIndex, + line.length); + }); + + fileContents = lines.join('\n'); + } + + return fileContents; + }; + + /** + * Finds all dependencies specified in dependency arrays and inside + * simplified commonjs wrappers. + * @param {String} fileName + * @param {String} fileContents + * + * @returns {Array} an array of dependency strings. The dependencies + * have not been normalized, they may be relative IDs. + */ + parse.findDependencies = function (fileName, fileContents, options) { + var dependencies = [], + astRoot = esprima.parse(fileContents); + + parse.recurse(astRoot, function (callName, config, name, deps) { + if (deps) { + dependencies = dependencies.concat(deps); + } + }, options); + + return dependencies; + }; + + /** + * Finds only CJS dependencies, ones that are the form + * require('stringLiteral') + */ + parse.findCjsDependencies = function (fileName, fileContents) { + var dependencies = []; + + traverse(esprima.parse(fileContents), function (node) { + var arg; + + if (node && node.type === 'CallExpression' && node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'require' && node[argPropName] && + node[argPropName].length === 1) { + arg = node[argPropName][0]; + if (arg.type === 'Literal') { + dependencies.push(arg.value); + } + } + }); + + return dependencies; + }; + + //function define() {} + parse.hasDefDefine = function (node) { + return node.type === 'FunctionDeclaration' && node.id && + node.id.type === 'Identifier' && node.id.name === 'define'; + }; + + //define.amd = ... + parse.hasDefineAmd = function (node) { + return node && node.type === 'AssignmentExpression' && + node.left && node.left.type === 'MemberExpression' && + node.left.object && node.left.object.name === 'define' && + node.left.property && node.left.property.name === 'amd'; + }; + + //define.amd reference, as in: if (define.amd) + parse.refsDefineAmd = function (node) { + return node && node.type === 'MemberExpression' && + node.object && node.object.name === 'define' && + node.object.type === 'Identifier' && + node.property && node.property.name === 'amd' && + node.property.type === 'Identifier'; + }; + + //require(), requirejs(), require.config() and requirejs.config() + parse.hasRequire = function (node) { + var callName, + c = node && node.callee; + + if (node && node.type === 'CallExpression' && c) { + if (c.type === 'Identifier' && + (c.name === 'require' || + c.name === 'requirejs')) { + //A require/requirejs({}, ...) call + callName = c.name; + } else if (c.type === 'MemberExpression' && + c.object && + c.object.type === 'Identifier' && + (c.object.name === 'require' || + c.object.name === 'requirejs') && + c.property && c.property.name === 'config') { + // require/requirejs.config({}) call + callName = c.object.name + 'Config'; + } + } + + return callName; + }; + + //define() + parse.hasDefine = function (node) { + return node && node.type === 'CallExpression' && node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'define'; + }; + + /** + * If there is a named define in the file, returns the name. Does not + * scan for mulitple names, just the first one. + */ + parse.getNamedDefine = function (fileContents) { + var name; + traverse(esprima.parse(fileContents), function (node) { + if (node && node.type === 'CallExpression' && node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'define' && + node[argPropName] && node[argPropName][0] && + node[argPropName][0].type === 'Literal') { + name = node[argPropName][0].value; + return false; + } + }); + + return name; + }; + + /** + * Determines if define(), require({}|[]) or requirejs was called in the + * file. Also finds out if define() is declared and if define.amd is called. + */ + parse.usesAmdOrRequireJs = function (fileName, fileContents) { + var uses; + + traverse(esprima.parse(fileContents), function (node) { + var type, callName, arg; + + if (parse.hasDefDefine(node)) { + //function define() {} + type = 'declaresDefine'; + } else if (parse.hasDefineAmd(node)) { + type = 'defineAmd'; + } else { + callName = parse.hasRequire(node); + if (callName) { + arg = node[argPropName] && node[argPropName][0]; + if (arg && (arg.type === 'ObjectExpression' || + arg.type === 'ArrayExpression')) { + type = callName; + } + } else if (parse.hasDefine(node)) { + type = 'define'; + } + } + + if (type) { + if (!uses) { + uses = {}; + } + uses[type] = true; + } + }); + + return uses; + }; + + /** + * Determines if require(''), exports.x =, module.exports =, + * __dirname, __filename are used. So, not strictly traditional CommonJS, + * also checks for Node variants. + */ + parse.usesCommonJs = function (fileName, fileContents) { + var uses = null, + assignsExports = false; + + + traverse(esprima.parse(fileContents), function (node) { + var type, + exp = node.expression || node.init; + + if (node.type === 'Identifier' && + (node.name === '__dirname' || node.name === '__filename')) { + type = node.name.substring(2); + } else if (node.type === 'VariableDeclarator' && node.id && + node.id.type === 'Identifier' && + node.id.name === 'exports') { + //Hmm, a variable assignment for exports, so does not use cjs + //exports. + type = 'varExports'; + } else if (exp && exp.type === 'AssignmentExpression' && exp.left && + exp.left.type === 'MemberExpression' && exp.left.object) { + if (exp.left.object.name === 'module' && exp.left.property && + exp.left.property.name === 'exports') { + type = 'moduleExports'; + } else if (exp.left.object.name === 'exports' && + exp.left.property) { + type = 'exports'; + } + + } else if (node && node.type === 'CallExpression' && node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'require' && node[argPropName] && + node[argPropName].length === 1 && + node[argPropName][0].type === 'Literal') { + type = 'require'; + } + + if (type) { + if (type === 'varExports') { + assignsExports = true; + } else if (type !== 'exports' || !assignsExports) { + if (!uses) { + uses = {}; + } + uses[type] = true; + } + } + }); + + return uses; + }; + + + parse.findRequireDepNames = function (node, deps) { + traverse(node, function (node) { + var arg; + + if (node && node.type === 'CallExpression' && node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'require' && + node[argPropName] && node[argPropName].length === 1) { + + arg = node[argPropName][0]; + if (arg.type === 'Literal') { + deps.push(arg.value); + } + } + }); + }; + + /** + * Determines if a specific node is a valid require or define/require.def + * call. + * @param {Array} node + * @param {Function} onMatch a function to call when a match is found. + * It is passed the match name, and the config, name, deps possible args. + * The config, name and deps args are not normalized. + * + * @returns {String} a JS source string with the valid require/define call. + * Otherwise null. + */ + parse.parseNode = function (node, onMatch) { + var name, deps, cjsDeps, arg, factory, exp, refsDefine, bodyNode, + args = node && node[argPropName], + callName = parse.hasRequire(node); + + if (callName === 'require' || callName === 'requirejs') { + //A plain require/requirejs call + arg = node[argPropName] && node[argPropName][0]; + if (arg.type !== 'ArrayExpression') { + if (arg.type === 'ObjectExpression') { + //A config call, try the second arg. + arg = node[argPropName][1]; + } + } + + deps = getValidDeps(arg); + if (!deps) { + return; + } + + return onMatch("require", null, null, deps, node); + } else if (parse.hasDefine(node) && args && args.length) { + name = args[0]; + deps = args[1]; + factory = args[2]; + + if (name.type === 'ArrayExpression') { + //No name, adjust args + factory = deps; + deps = name; + name = null; + } else if (name.type === 'FunctionExpression') { + //Just the factory, no name or deps + factory = name; + name = deps = null; + } else if (name.type !== 'Literal') { + //An object literal, just null out + name = deps = factory = null; + } + + if (name && name.type === 'Literal' && deps) { + if (deps.type === 'FunctionExpression') { + //deps is the factory + factory = deps; + deps = null; + } else if (deps.type === 'ObjectExpression') { + //deps is object literal, null out + deps = factory = null; + } else if (deps.type === 'Identifier' && args.length === 2) { + // define('id', factory) + deps = factory = null; + } + } + + if (deps && deps.type === 'ArrayExpression') { + deps = getValidDeps(deps); + } else if (factory && factory.type === 'FunctionExpression') { + //If no deps and a factory function, could be a commonjs sugar + //wrapper, scan the function for dependencies. + cjsDeps = parse.getAnonDepsFromNode(factory); + if (cjsDeps.length) { + deps = cjsDeps; + } + } else if (deps || factory) { + //Does not match the shape of an AMD call. + return; + } + + //Just save off the name as a string instead of an AST object. + if (name && name.type === 'Literal') { + name = name.value; + } + + return onMatch("define", null, name, deps, node); + } else if (node.type === 'CallExpression' && node.callee && + node.callee.type === 'FunctionExpression' && + node.callee.body && node.callee.body.body && + node.callee.body.body.length === 1 && + node.callee.body.body[0].type === 'IfStatement') { + bodyNode = node.callee.body.body[0]; + //Look for a define(Identifier) case, but only if inside an + //if that has a define.amd test + if (bodyNode.consequent && bodyNode.consequent.body) { + exp = bodyNode.consequent.body[0]; + if (exp.type === 'ExpressionStatement' && exp.expression && + parse.hasDefine(exp.expression) && + exp.expression.arguments && + exp.expression.arguments.length === 1 && + exp.expression.arguments[0].type === 'Identifier') { + + //Calls define(Identifier) as first statement in body. + //Confirm the if test references define.amd + traverse(bodyNode.test, function (node) { + if (parse.refsDefineAmd(node)) { + refsDefine = true; + return false; + } + }); + + if (refsDefine) { + return onMatch("define", null, null, null, exp.expression); + } + } + } + } + }; + + /** + * Converts an AST node into a JS source string by extracting + * the node's location from the given contents string. Assumes + * esprima.parse() with loc was done. + * @param {String} contents + * @param {Object} node + * @returns {String} a JS source string. + */ + parse.nodeToString = function (contents, node) { + var extracted, + loc = node.loc, + lines = contents.split('\n'), + firstLine = loc.start.line > 1 ? + lines.slice(0, loc.start.line - 1).join('\n') + '\n' : + '', + preamble = firstLine + + lines[loc.start.line - 1].substring(0, loc.start.column); + + if (loc.start.line === loc.end.line) { + extracted = lines[loc.start.line - 1].substring(loc.start.column, + loc.end.column); + } else { + extracted = lines[loc.start.line - 1].substring(loc.start.column) + + '\n' + + lines.slice(loc.start.line, loc.end.line - 1).join('\n') + + '\n' + + lines[loc.end.line - 1].substring(0, loc.end.column); + } + + return { + value: extracted, + range: [ + preamble.length, + preamble.length + extracted.length + ] + }; + }; + + /** + * Extracts license comments from JS text. + * @param {String} fileName + * @param {String} contents + * @returns {String} a string of license comments. + */ + parse.getLicenseComments = function (fileName, contents) { + var commentNode, refNode, subNode, value, i, j, + //xpconnect's Reflect does not support comment or range, but + //prefer continued operation vs strict parity of operation, + //as license comments can be expressed in other ways, like + //via wrap args, or linked via sourcemaps. + ast = esprima.parse(contents, { + comment: true, + range: true + }), + result = '', + existsMap = {}, + lineEnd = contents.indexOf('\r') === -1 ? '\n' : '\r\n'; + + if (ast.comments) { + for (i = 0; i < ast.comments.length; i++) { + commentNode = ast.comments[i]; + + if (commentNode.type === 'Line') { + value = '//' + commentNode.value + lineEnd; + refNode = commentNode; + + if (i + 1 >= ast.comments.length) { + value += lineEnd; + } else { + //Look for immediately adjacent single line comments + //since it could from a multiple line comment made out + //of single line comments. Like this comment. + for (j = i + 1; j < ast.comments.length; j++) { + subNode = ast.comments[j]; + if (subNode.type === 'Line' && + subNode.range[0] === refNode.range[1] + 1) { + //Adjacent single line comment. Collect it. + value += '//' + subNode.value + lineEnd; + refNode = subNode; + } else { + //No more single line comment blocks. Break out + //and continue outer looping. + break; + } + } + value += lineEnd; + i = j - 1; + } + } else { + value = '/*' + commentNode.value + '*/' + lineEnd + lineEnd; + } + + if (!existsMap[value] && (value.indexOf('license') !== -1 || + (commentNode.type === 'Block' && + value.indexOf('/*!') === 0) || + value.indexOf('opyright') !== -1 || + value.indexOf('(c)') !== -1)) { + + result += value; + existsMap[value] = true; + } + + } + } + + return result; + }; + + return parse; +}); +/** + * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*global define */ + +define('transform', [ './esprimaAdapter', './parse', 'logger', 'lang'], +function (esprima, parse, logger, lang) { + 'use strict'; + var transform, + baseIndentRegExp = /^([ \t]+)/, + indentRegExp = /\{[\r\n]+([ \t]+)/, + keyRegExp = /^[_A-Za-z]([A-Za-z\d_]*)$/, + bulkIndentRegExps = { + '\n': /\n/g, + '\r\n': /\r\n/g + }; + + function applyIndent(str, indent, lineReturn) { + var regExp = bulkIndentRegExps[lineReturn]; + return str.replace(regExp, '$&' + indent); + } + + transform = { + toTransport: function (namespace, moduleName, path, contents, onFound, options) { + options = options || {}; + + var astRoot, contentLines, modLine, + foundAnon, + scanCount = 0, + scanReset = false, + defineInfos = []; + + try { + astRoot = esprima.parse(contents, { + loc: true + }); + } catch (e) { + logger.trace('toTransport skipping ' + path + ': ' + + e.toString()); + return contents; + } + + //Find the define calls and their position in the files. + parse.traverseBroad(astRoot, function (node) { + var args, firstArg, firstArgLoc, factoryNode, + needsId, depAction, foundId, + sourceUrlData, range, + namespaceExists = false; + + namespaceExists = namespace && + node.type === 'CallExpression' && + node.callee && node.callee.object && + node.callee.object.type === 'Identifier' && + node.callee.object.name === namespace && + node.callee.property.type === 'Identifier' && + node.callee.property.name === 'define'; + + if (namespaceExists || parse.isDefineNodeWithArgs(node)) { + //The arguments are where its at. + args = node.arguments; + if (!args || !args.length) { + return; + } + + firstArg = args[0]; + firstArgLoc = firstArg.loc; + + if (args.length === 1) { + if (firstArg.type === 'Identifier') { + //The define(factory) case, but + //only allow it if one Identifier arg, + //to limit impact of false positives. + needsId = true; + depAction = 'empty'; + } else if (firstArg.type === 'FunctionExpression') { + //define(function(){}) + factoryNode = firstArg; + needsId = true; + depAction = 'scan'; + } else if (firstArg.type === 'ObjectExpression') { + //define({}); + needsId = true; + depAction = 'skip'; + } else if (firstArg.type === 'Literal' && + typeof firstArg.value === 'number') { + //define('12345'); + needsId = true; + depAction = 'skip'; + } else if (firstArg.type === 'UnaryExpression' && + firstArg.operator === '-' && + firstArg.argument && + firstArg.argument.type === 'Literal' && + typeof firstArg.argument.value === 'number') { + //define('-12345'); + needsId = true; + depAction = 'skip'; + } else if (firstArg.type === 'MemberExpression' && + firstArg.object && + firstArg.property && + firstArg.property.type === 'Identifier') { + //define(this.key); + needsId = true; + depAction = 'empty'; + } + } else if (firstArg.type === 'ArrayExpression') { + //define([], ...); + needsId = true; + depAction = 'skip'; + } else if (firstArg.type === 'Literal' && + typeof firstArg.value === 'string') { + //define('string', ....) + //Already has an ID. + needsId = false; + if (args.length === 2 && + args[1].type === 'FunctionExpression') { + //Needs dependency scanning. + factoryNode = args[1]; + depAction = 'scan'; + } else { + depAction = 'skip'; + } + } else { + //Unknown define entity, keep looking, even + //in the subtree for this node. + return; + } + + range = { + foundId: foundId, + needsId: needsId, + depAction: depAction, + namespaceExists: namespaceExists, + node: node, + defineLoc: node.loc, + firstArgLoc: firstArgLoc, + factoryNode: factoryNode, + sourceUrlData: sourceUrlData + }; + + //Only transform ones that do not have IDs. If it has an + //ID but no dependency array, assume it is something like + //a phonegap implementation, that has its own internal + //define that cannot handle dependency array constructs, + //and if it is a named module, then it means it has been + //set for transport form. + if (range.needsId) { + if (foundAnon) { + logger.trace(path + ' has more than one anonymous ' + + 'define. May be a built file from another ' + + 'build system like, Ender. Skipping normalization.'); + defineInfos = []; + return false; + } else { + foundAnon = range; + defineInfos.push(range); + } + } else if (depAction === 'scan') { + scanCount += 1; + if (scanCount > 1) { + //Just go back to an array that just has the + //anon one, since this is an already optimized + //file like the phonegap one. + if (!scanReset) { + defineInfos = foundAnon ? [foundAnon] : []; + scanReset = true; + } + } else { + defineInfos.push(range); + } + } + } + }); + + if (!defineInfos.length) { + return contents; + } + + //Reverse the matches, need to start from the bottom of + //the file to modify it, so that the ranges are still true + //further up. + defineInfos.reverse(); + + contentLines = contents.split('\n'); + + modLine = function (loc, contentInsertion) { + var startIndex = loc.start.column, + //start.line is 1-based, not 0 based. + lineIndex = loc.start.line - 1, + line = contentLines[lineIndex]; + contentLines[lineIndex] = line.substring(0, startIndex) + + contentInsertion + + line.substring(startIndex, + line.length); + }; + + defineInfos.forEach(function (info) { + var deps, + contentInsertion = '', + depString = ''; + + //Do the modifications "backwards", in other words, start with the + //one that is farthest down and work up, so that the ranges in the + //defineInfos still apply. So that means deps, id, then namespace. + if (info.needsId && moduleName) { + contentInsertion += "'" + moduleName + "',"; + } + + if (info.depAction === 'scan') { + deps = parse.getAnonDepsFromNode(info.factoryNode); + + if (deps.length) { + depString = '[' + deps.map(function (dep) { + return "'" + dep + "'"; + }) + ']'; + } else { + depString = '[]'; + } + depString += ','; + + if (info.factoryNode) { + //Already have a named module, need to insert the + //dependencies after the name. + modLine(info.factoryNode.loc, depString); + } else { + contentInsertion += depString; + } + } + + if (contentInsertion) { + modLine(info.firstArgLoc, contentInsertion); + } + + //Do namespace last so that ui does not mess upthe parenRange + //used above. + if (namespace && !info.namespaceExists) { + modLine(info.defineLoc, namespace + '.'); + } + + //Notify any listener for the found info + if (onFound) { + onFound(info); + } + }); + + contents = contentLines.join('\n'); + + if (options.useSourceUrl) { + contents = 'eval("' + lang.jsEscape(contents) + + '\\n//# sourceURL=' + (path.indexOf('/') === 0 ? '' : '/') + + path + + '");\n'; + } + + return contents; + }, + + /** + * Modify the contents of a require.config/requirejs.config call. This + * call will LOSE any existing comments that are in the config string. + * + * @param {String} fileContents String that may contain a config call + * @param {Function} onConfig Function called when the first config + * call is found. It will be passed an Object which is the current + * config, and the onConfig function should return an Object to use + * as the config. + * @return {String} the fileContents with the config changes applied. + */ + modifyConfig: function (fileContents, onConfig) { + var details = parse.findConfig(fileContents), + config = details.config; + + if (config) { + config = onConfig(config); + if (config) { + return transform.serializeConfig(config, + fileContents, + details.range[0], + details.range[1], + { + quote: details.quote + }); + } + } + + return fileContents; + }, + + serializeConfig: function (config, fileContents, start, end, options) { + //Calculate base level of indent + var indent, match, configString, outDentRegExp, + baseIndent = '', + startString = fileContents.substring(0, start), + existingConfigString = fileContents.substring(start, end), + lineReturn = existingConfigString.indexOf('\r') === -1 ? '\n' : '\r\n', + lastReturnIndex = startString.lastIndexOf('\n'); + + //Get the basic amount of indent for the require config call. + if (lastReturnIndex === -1) { + lastReturnIndex = 0; + } + + match = baseIndentRegExp.exec(startString.substring(lastReturnIndex + 1, start)); + if (match && match[1]) { + baseIndent = match[1]; + } + + //Calculate internal indentation for config + match = indentRegExp.exec(existingConfigString); + if (match && match[1]) { + indent = match[1]; + } + + if (!indent || indent.length < baseIndent) { + indent = ' '; + } else { + indent = indent.substring(baseIndent.length); + } + + outDentRegExp = new RegExp('(' + lineReturn + ')' + indent, 'g'); + + configString = transform.objectToString(config, { + indent: indent, + lineReturn: lineReturn, + outDentRegExp: outDentRegExp, + quote: options && options.quote + }); + + //Add in the base indenting level. + configString = applyIndent(configString, baseIndent, lineReturn); + + return startString + configString + fileContents.substring(end); + }, + + /** + * Tries converting a JS object to a string. This will likely suck, and + * is tailored to the type of config expected in a loader config call. + * So, hasOwnProperty fields, strings, numbers, arrays and functions, + * no weird recursively referenced stuff. + * @param {Object} obj the object to convert + * @param {Object} options options object with the following values: + * {String} indent the indentation to use for each level + * {String} lineReturn the type of line return to use + * {outDentRegExp} outDentRegExp the regexp to use to outdent functions + * {String} quote the quote type to use, ' or ". Optional. Default is " + * @param {String} totalIndent the total indent to print for this level + * @return {String} a string representation of the object. + */ + objectToString: function (obj, options, totalIndent) { + var startBrace, endBrace, nextIndent, + first = true, + value = '', + lineReturn = options.lineReturn, + indent = options.indent, + outDentRegExp = options.outDentRegExp, + quote = options.quote || '"'; + + totalIndent = totalIndent || ''; + nextIndent = totalIndent + indent; + + if (obj === null) { + value = 'null'; + } else if (obj === undefined) { + value = 'undefined'; + } else if (typeof obj === 'number' || typeof obj === 'boolean') { + value = obj; + } else if (typeof obj === 'string') { + //Use double quotes in case the config may also work as JSON. + value = quote + lang.jsEscape(obj) + quote; + } else if (lang.isArray(obj)) { + lang.each(obj, function (item, i) { + value += (i !== 0 ? ',' + lineReturn : '' ) + + nextIndent + + transform.objectToString(item, + options, + nextIndent); + }); + + startBrace = '['; + endBrace = ']'; + } else if (lang.isFunction(obj) || lang.isRegExp(obj)) { + //The outdent regexp just helps pretty up the conversion + //just in node. Rhino strips comments and does a different + //indent scheme for Function toString, so not really helpful + //there. + value = obj.toString().replace(outDentRegExp, '$1'); + } else { + //An object + lang.eachProp(obj, function (v, prop) { + value += (first ? '': ',' + lineReturn) + + nextIndent + + (keyRegExp.test(prop) ? prop : quote + lang.jsEscape(prop) + quote )+ + ': ' + + transform.objectToString(v, + options, + nextIndent); + first = false; + }); + startBrace = '{'; + endBrace = '}'; + } + + if (startBrace) { + value = startBrace + + lineReturn + + value + + lineReturn + totalIndent + + endBrace; + } + + return value; + } + }; + + return transform; +}); +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint regexp: true, plusplus: true */ +/*global define: false */ + +define('pragma', ['parse', 'logger'], function (parse, logger) { + 'use strict'; + function Temp() {} + + function create(obj, mixin) { + Temp.prototype = obj; + var temp = new Temp(), prop; + + //Avoid any extra memory hanging around + Temp.prototype = null; + + if (mixin) { + for (prop in mixin) { + if (mixin.hasOwnProperty(prop) && !temp.hasOwnProperty(prop)) { + temp[prop] = mixin[prop]; + } + } + } + + return temp; // Object + } + + var pragma = { + conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/, + useStrictRegExp: /['"]use strict['"];/g, + hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\s*\)/g, + configRegExp: /(^|[^\.])(requirejs|require)(\.config)\s*\(/g, + nsWrapRegExp: /\/\*requirejs namespace: true \*\//, + apiDefRegExp: /var requirejs,\s*require,\s*define;/, + defineCheckRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd/g, + defineStringCheckRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\[\s*["']amd["']\s*\]/g, + defineTypeFirstCheckRegExp: /\s*["']function["']\s*==(=?)\s*typeof\s+define\s*&&\s*define\s*\.\s*amd/g, + defineJQueryRegExp: /typeof\s+define\s*===\s*["']function["']\s*&&\s*define\s*\.\s*amd\s*&&\s*define\s*\.\s*amd\s*\.\s*jQuery/g, + defineHasRegExp: /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g, + defineTernaryRegExp: /typeof\s+define\s*===\s*['"]function["']\s*&&\s*define\s*\.\s*amd\s*\?\s*define/, + amdefineRegExp: /if\s*\(\s*typeof define\s*\!==\s*'function'\s*\)\s*\{\s*[^\{\}]+amdefine[^\{\}]+\}/g, + + removeStrict: function (contents, config) { + return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, ''); + }, + + namespace: function (fileContents, ns, onLifecycleName) { + if (ns) { + //Namespace require/define calls + fileContents = fileContents.replace(pragma.configRegExp, '$1' + ns + '.$2$3('); + + + fileContents = parse.renameNamespace(fileContents, ns); + + //Namespace define ternary use: + fileContents = fileContents.replace(pragma.defineTernaryRegExp, + "typeof " + ns + ".define === 'function' && " + ns + ".define.amd ? " + ns + ".define"); + + //Namespace define jquery use: + fileContents = fileContents.replace(pragma.defineJQueryRegExp, + "typeof " + ns + ".define === 'function' && " + ns + ".define.amd && " + ns + ".define.amd.jQuery"); + + //Namespace has.js define use: + fileContents = fileContents.replace(pragma.defineHasRegExp, + "typeof " + ns + ".define === 'function' && typeof " + ns + ".define.amd === 'object' && " + ns + ".define.amd"); + + //Namespace define checks. + //Do these ones last, since they are a subset of the more specific + //checks above. + fileContents = fileContents.replace(pragma.defineCheckRegExp, + "typeof " + ns + ".define === 'function' && " + ns + ".define.amd"); + fileContents = fileContents.replace(pragma.defineStringCheckRegExp, + "typeof " + ns + ".define === 'function' && " + ns + ".define['amd']"); + fileContents = fileContents.replace(pragma.defineTypeFirstCheckRegExp, + "'function' === typeof " + ns + ".define && " + ns + ".define.amd"); + + //Check for require.js with the require/define definitions + if (pragma.apiDefRegExp.test(fileContents) && + fileContents.indexOf("if (!" + ns + " || !" + ns + ".requirejs)") === -1) { + //Wrap the file contents in a typeof check, and a function + //to contain the API globals. + fileContents = "var " + ns + ";(function () { if (!" + ns + " || !" + ns + ".requirejs) {\n" + + "if (!" + ns + ") { " + ns + ' = {}; } else { require = ' + ns + '; }\n' + + fileContents + + "\n" + + ns + ".requirejs = requirejs;" + + ns + ".require = require;" + + ns + ".define = define;\n" + + "}\n}());"; + } + + //Finally, if the file wants a special wrapper because it ties + //in to the requirejs internals in a way that would not fit + //the above matches, do that. Look for /*requirejs namespace: true*/ + if (pragma.nsWrapRegExp.test(fileContents)) { + //Remove the pragma. + fileContents = fileContents.replace(pragma.nsWrapRegExp, ''); + + //Alter the contents. + fileContents = '(function () {\n' + + 'var require = ' + ns + '.require,' + + 'requirejs = ' + ns + '.requirejs,' + + 'define = ' + ns + '.define;\n' + + fileContents + + '\n}());'; + } + } + + return fileContents; + }, + + /** + * processes the fileContents for some //>> conditional statements + */ + process: function (fileName, fileContents, config, onLifecycleName, pluginCollector) { + /*jslint evil: true */ + var foundIndex = -1, startIndex = 0, lineEndIndex, conditionLine, + matches, type, marker, condition, isTrue, endRegExp, endMatches, + endMarkerIndex, shouldInclude, startLength, lifecycleHas, deps, + i, dep, moduleName, collectorMod, + lifecyclePragmas, pragmas = config.pragmas, hasConfig = config.has, + //Legacy arg defined to help in dojo conversion script. Remove later + //when dojo no longer needs conversion: + kwArgs = pragmas; + + //Mix in a specific lifecycle scoped object, to allow targeting + //some pragmas/has tests to only when files are saved, or at different + //lifecycle events. Do not bother with kwArgs in this section, since + //the old dojo kwArgs were for all points in the build lifecycle. + if (onLifecycleName) { + lifecyclePragmas = config['pragmas' + onLifecycleName]; + lifecycleHas = config['has' + onLifecycleName]; + + if (lifecyclePragmas) { + pragmas = create(pragmas || {}, lifecyclePragmas); + } + + if (lifecycleHas) { + hasConfig = create(hasConfig || {}, lifecycleHas); + } + } + + //Replace has references if desired + if (hasConfig) { + fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) { + if (hasConfig.hasOwnProperty(test)) { + return !!hasConfig[test]; + } + return match; + }); + } + + if (!config.skipPragmas) { + + while ((foundIndex = fileContents.indexOf("//>>", startIndex)) !== -1) { + //Found a conditional. Get the conditional line. + lineEndIndex = fileContents.indexOf("\n", foundIndex); + if (lineEndIndex === -1) { + lineEndIndex = fileContents.length - 1; + } + + //Increment startIndex past the line so the next conditional search can be done. + startIndex = lineEndIndex + 1; + + //Break apart the conditional. + conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1); + matches = conditionLine.match(pragma.conditionalRegExp); + if (matches) { + type = matches[1]; + marker = matches[2]; + condition = matches[3]; + isTrue = false; + //See if the condition is true. + try { + isTrue = !!eval("(" + condition + ")"); + } catch (e) { + throw "Error in file: " + + fileName + + ". Conditional comment: " + + conditionLine + + " failed with this error: " + e; + } + + //Find the endpoint marker. + endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g"); + endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length)); + if (endMatches) { + endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length; + + //Find the next line return based on the match position. + lineEndIndex = fileContents.indexOf("\n", endMarkerIndex); + if (lineEndIndex === -1) { + lineEndIndex = fileContents.length - 1; + } + + //Should we include the segment? + shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue)); + + //Remove the conditional comments, and optionally remove the content inside + //the conditional comments. + startLength = startIndex - foundIndex; + fileContents = fileContents.substring(0, foundIndex) + + (shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") + + fileContents.substring(lineEndIndex + 1, fileContents.length); + + //Move startIndex to foundIndex, since that is the new position in the file + //where we need to look for more conditionals in the next while loop pass. + startIndex = foundIndex; + } else { + throw "Error in file: " + + fileName + + ". Cannot find end marker for conditional comment: " + + conditionLine; + + } + } + } + } + + //If need to find all plugin resources to optimize, do that now, + //before namespacing, since the namespacing will change the API + //names. + //If there is a plugin collector, scan the file for plugin resources. + if (config.optimizeAllPluginResources && pluginCollector) { + try { + deps = parse.findDependencies(fileName, fileContents); + if (deps.length) { + for (i = 0; i < deps.length; i++) { + dep = deps[i]; + if (dep.indexOf('!') !== -1) { + moduleName = dep.split('!')[0]; + collectorMod = pluginCollector[moduleName]; + if (!collectorMod) { + collectorMod = pluginCollector[moduleName] = []; + } + collectorMod.push(dep); + } + } + } + } catch (eDep) { + logger.error('Parse error looking for plugin resources in ' + + fileName + ', skipping.'); + } + } + + //Strip amdefine use for node-shared modules. + fileContents = fileContents.replace(pragma.amdefineRegExp, ''); + + //Do namespacing + if (onLifecycleName === 'OnSave' && config.namespace) { + fileContents = pragma.namespace(fileContents, config.namespace, onLifecycleName); + } + + + return pragma.removeStrict(fileContents, config); + } + }; + + return pragma; +}); +if(env === 'browser') { +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false */ + +define('browser/optimize', {}); + +} + +if(env === 'node') { +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint strict: false */ +/*global define: false */ + +define('node/optimize', {}); + +} + +if(env === 'rhino') { +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint sloppy: true, plusplus: true */ +/*global define, java, Packages, com */ + +define('rhino/optimize', ['logger', 'env!env/file'], function (logger, file) { + + //Add .reduce to Rhino so UglifyJS can run in Rhino, + //inspired by https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce + //but rewritten for brevity, and to be good enough for use by UglifyJS. + if (!Array.prototype.reduce) { + Array.prototype.reduce = function (fn /*, initialValue */) { + var i = 0, + length = this.length, + accumulator; + + if (arguments.length >= 2) { + accumulator = arguments[1]; + } else { + if (length) { + while (!(i in this)) { + i++; + } + accumulator = this[i++]; + } + } + + for (; i < length; i++) { + if (i in this) { + accumulator = fn.call(undefined, accumulator, this[i], i, this); + } + } + + return accumulator; + }; + } + + var JSSourceFilefromCode, optimize, + mapRegExp = /"file":"[^"]+"/; + + //Bind to Closure compiler, but if it is not available, do not sweat it. + try { + JSSourceFilefromCode = java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode', [java.lang.String, java.lang.String]); + } catch (e) {} + + //Helper for closure compiler, because of weird Java-JavaScript interactions. + function closurefromCode(filename, content) { + return JSSourceFilefromCode.invoke(null, [filename, content]); + } + + + function getFileWriter(fileName, encoding) { + var outFile = new java.io.File(fileName), outWriter, parentDir; + + parentDir = outFile.getAbsoluteFile().getParentFile(); + if (!parentDir.exists()) { + if (!parentDir.mkdirs()) { + throw "Could not create directory: " + parentDir.getAbsolutePath(); + } + } + + if (encoding) { + outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding); + } else { + outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile)); + } + + return new java.io.BufferedWriter(outWriter); + } + + optimize = { + closure: function (fileName, fileContents, outFileName, keepLines, config) { + config = config || {}; + var result, mappings, optimized, compressed, baseName, writer, + outBaseName, outFileNameMap, outFileNameMapContent, + srcOutFileName, concatNameMap, + jscomp = Packages.com.google.javascript.jscomp, + flags = Packages.com.google.common.flags, + //Set up source input + jsSourceFile = closurefromCode(String(fileName), String(fileContents)), + sourceListArray = new java.util.ArrayList(), + options, option, FLAG_compilation_level, compiler, + Compiler = Packages.com.google.javascript.jscomp.Compiler, + CommandLineRunner = Packages.com.google.javascript.jscomp.CommandLineRunner; + + logger.trace("Minifying file: " + fileName); + + baseName = (new java.io.File(fileName)).getName(); + + //Set up options + options = new jscomp.CompilerOptions(); + for (option in config.CompilerOptions) { + // options are false by default and jslint wanted an if statement in this for loop + if (config.CompilerOptions[option]) { + options[option] = config.CompilerOptions[option]; + } + + } + options.prettyPrint = keepLines || options.prettyPrint; + + FLAG_compilation_level = jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS']; + FLAG_compilation_level.setOptionsForCompilationLevel(options); + + if (config.generateSourceMaps) { + mappings = new java.util.ArrayList(); + + mappings.add(new com.google.javascript.jscomp.SourceMap.LocationMapping(fileName, baseName + ".src.js")); + options.setSourceMapLocationMappings(mappings); + options.setSourceMapOutputPath(fileName + ".map"); + } + + //Trigger the compiler + Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']); + compiler = new Compiler(); + + //fill the sourceArrrayList; we need the ArrayList because the only overload of compile + //accepting the getDefaultExterns return value (a List) also wants the sources as a List + sourceListArray.add(jsSourceFile); + + result = compiler.compile(CommandLineRunner.getDefaultExterns(), sourceListArray, options); + if (result.success) { + optimized = String(compiler.toSource()); + + if (config.generateSourceMaps && result.sourceMap && outFileName) { + outBaseName = (new java.io.File(outFileName)).getName(); + + srcOutFileName = outFileName + ".src.js"; + outFileNameMap = outFileName + ".map"; + + //If previous .map file exists, move it to the ".src.js" + //location. Need to update the sourceMappingURL part in the + //src.js file too. + if (file.exists(outFileNameMap)) { + concatNameMap = outFileNameMap.replace(/\.map$/, '.src.js.map'); + file.saveFile(concatNameMap, file.readFile(outFileNameMap)); + file.saveFile(srcOutFileName, + fileContents.replace(/\/\# sourceMappingURL=(.+).map/, + '/# sourceMappingURL=$1.src.js.map')); + } else { + file.saveUtf8File(srcOutFileName, fileContents); + } + + writer = getFileWriter(outFileNameMap, "utf-8"); + result.sourceMap.appendTo(writer, outFileName); + writer.close(); + + //Not sure how better to do this, but right now the .map file + //leaks the full OS path in the "file" property. Manually + //modify it to not do that. + file.saveFile(outFileNameMap, + file.readFile(outFileNameMap).replace(mapRegExp, '"file":"' + baseName + '"')); + + fileContents = optimized + "\n//# sourceMappingURL=" + outBaseName + ".map"; + } else { + fileContents = optimized; + } + return fileContents; + } else { + throw new Error('Cannot closure compile file: ' + fileName + '. Skipping it.'); + } + + return fileContents; + } + }; + + return optimize; +}); +} + +if(env === 'xpconnect') { +define('xpconnect/optimize', {}); +} +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint plusplus: true, nomen: true, regexp: true */ +/*global define: false */ + +define('optimize', [ 'lang', 'logger', 'env!env/optimize', 'env!env/file', 'parse', + 'pragma', 'uglifyjs/index', 'uglifyjs2', + 'source-map'], +function (lang, logger, envOptimize, file, parse, + pragma, uglify, uglify2, + sourceMap) { + 'use strict'; + + var optimize, + cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/ig, + cssCommentImportRegExp = /\/\*[^\*]*@import[^\*]*\*\//g, + cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g, + SourceMapGenerator = sourceMap.SourceMapGenerator, + SourceMapConsumer =sourceMap.SourceMapConsumer; + + /** + * If an URL from a CSS url value contains start/end quotes, remove them. + * This is not done in the regexp, since my regexp fu is not that strong, + * and the CSS spec allows for ' and " in the URL if they are backslash escaped. + * @param {String} url + */ + function cleanCssUrlQuotes(url) { + //Make sure we are not ending in whitespace. + //Not very confident of the css regexps above that there will not be ending + //whitespace. + url = url.replace(/\s+$/, ""); + + if (url.charAt(0) === "'" || url.charAt(0) === "\"") { + url = url.substring(1, url.length - 1); + } + + return url; + } + + function fixCssUrlPaths(fileName, path, contents, cssPrefix) { + return contents.replace(cssUrlRegExp, function (fullMatch, urlMatch) { + var colonIndex, parts, i, + fixedUrlMatch = cleanCssUrlQuotes(urlMatch); + + fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/"); + + //Only do the work for relative URLs. Skip things that start with / or have + //a protocol. + colonIndex = fixedUrlMatch.indexOf(":"); + if (fixedUrlMatch.charAt(0) !== "/" && (colonIndex === -1 || colonIndex > fixedUrlMatch.indexOf("/"))) { + //It is a relative URL, tack on the cssPrefix and path prefix + urlMatch = cssPrefix + path + fixedUrlMatch; + + } else { + logger.trace(fileName + "\n URL not a relative URL, skipping: " + urlMatch); + } + + //Collapse .. and . + parts = urlMatch.split("/"); + for (i = parts.length - 1; i > 0; i--) { + if (parts[i] === ".") { + parts.splice(i, 1); + } else if (parts[i] === "..") { + if (i !== 0 && parts[i - 1] !== "..") { + parts.splice(i - 1, 2); + i -= 1; + } + } + } + + return "url(" + parts.join("/") + ")"; + }); + } + + /** + * Inlines nested stylesheets that have @import calls in them. + * @param {String} fileName the file name + * @param {String} fileContents the file contents + * @param {String} cssImportIgnore comma delimited string of files to ignore + * @param {String} cssPrefix string to be prefixed before relative URLs + * @param {Object} included an object used to track the files already imported + */ + function flattenCss(fileName, fileContents, cssImportIgnore, cssPrefix, included, topLevel) { + //Find the last slash in the name. + fileName = fileName.replace(lang.backSlashRegExp, "/"); + var endIndex = fileName.lastIndexOf("/"), + //Make a file path based on the last slash. + //If no slash, so must be just a file name. Use empty string then. + filePath = (endIndex !== -1) ? fileName.substring(0, endIndex + 1) : "", + //store a list of merged files + importList = [], + skippedList = []; + + //First make a pass by removing any commented out @import calls. + fileContents = fileContents.replace(cssCommentImportRegExp, ''); + + //Make sure we have a delimited ignore list to make matching faster + if (cssImportIgnore && cssImportIgnore.charAt(cssImportIgnore.length - 1) !== ",") { + cssImportIgnore += ","; + } + + fileContents = fileContents.replace(cssImportRegExp, function (fullMatch, urlStart, importFileName, urlEnd, mediaTypes) { + //Only process media type "all" or empty media type rules. + if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) { + skippedList.push(fileName); + return fullMatch; + } + + importFileName = cleanCssUrlQuotes(importFileName); + + //Ignore the file import if it is part of an ignore list. + if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) { + return fullMatch; + } + + //Make sure we have a unix path for the rest of the operation. + importFileName = importFileName.replace(lang.backSlashRegExp, "/"); + + try { + //if a relative path, then tack on the filePath. + //If it is not a relative path, then the readFile below will fail, + //and we will just skip that import. + var fullImportFileName = importFileName.charAt(0) === "/" ? importFileName : filePath + importFileName, + importContents = file.readFile(fullImportFileName), + importEndIndex, importPath, flat; + + //Skip the file if it has already been included. + if (included[fullImportFileName]) { + return ''; + } + included[fullImportFileName] = true; + + //Make sure to flatten any nested imports. + flat = flattenCss(fullImportFileName, importContents, cssImportIgnore, cssPrefix, included); + importContents = flat.fileContents; + + if (flat.importList.length) { + importList.push.apply(importList, flat.importList); + } + if (flat.skippedList.length) { + skippedList.push.apply(skippedList, flat.skippedList); + } + + //Make the full import path + importEndIndex = importFileName.lastIndexOf("/"); + + //Make a file path based on the last slash. + //If no slash, so must be just a file name. Use empty string then. + importPath = (importEndIndex !== -1) ? importFileName.substring(0, importEndIndex + 1) : ""; + + //fix url() on relative import (#5) + importPath = importPath.replace(/^\.\//, ''); + + //Modify URL paths to match the path represented by this file. + importContents = fixCssUrlPaths(importFileName, importPath, importContents, cssPrefix); + + importList.push(fullImportFileName); + return importContents; + } catch (e) { + logger.warn(fileName + "\n Cannot inline css import, skipping: " + importFileName); + return fullMatch; + } + }); + + if (cssPrefix && topLevel) { + //Modify URL paths to match the path represented by this file. + fileContents = fixCssUrlPaths(fileName, '', fileContents, cssPrefix); + } + + return { + importList : importList, + skippedList: skippedList, + fileContents : fileContents + }; + } + + optimize = { + /** + * Optimizes a file that contains JavaScript content. Optionally collects + * plugin resources mentioned in a file, and then passes the content + * through an minifier if one is specified via config.optimize. + * + * @param {String} fileName the name of the file to optimize + * @param {String} fileContents the contents to optimize. If this is + * a null value, then fileName will be used to read the fileContents. + * @param {String} outFileName the name of the file to use for the + * saved optimized content. + * @param {Object} config the build config object. + * @param {Array} [pluginCollector] storage for any plugin resources + * found. + */ + jsFile: function (fileName, fileContents, outFileName, config, pluginCollector) { + if (!fileContents) { + fileContents = file.readFile(fileName); + } + + fileContents = optimize.js(fileName, fileContents, outFileName, config, pluginCollector); + + file.saveUtf8File(outFileName, fileContents); + }, + + /** + * Optimizes a file that contains JavaScript content. Optionally collects + * plugin resources mentioned in a file, and then passes the content + * through an minifier if one is specified via config.optimize. + * + * @param {String} fileName the name of the file that matches the + * fileContents. + * @param {String} fileContents the string of JS to optimize. + * @param {Object} [config] the build config object. + * @param {Array} [pluginCollector] storage for any plugin resources + * found. + */ + js: function (fileName, fileContents, outFileName, config, pluginCollector) { + var optFunc, optConfig, + parts = (String(config.optimize)).split('.'), + optimizerName = parts[0], + keepLines = parts[1] === 'keepLines', + licenseContents = ''; + + config = config || {}; + + //Apply pragmas/namespace renaming + fileContents = pragma.process(fileName, fileContents, config, 'OnSave', pluginCollector); + + //Optimize the JS files if asked. + if (optimizerName && optimizerName !== 'none') { + optFunc = envOptimize[optimizerName] || optimize.optimizers[optimizerName]; + if (!optFunc) { + throw new Error('optimizer with name of "' + + optimizerName + + '" not found for this environment'); + } + + optConfig = config[optimizerName] || {}; + if (config.generateSourceMaps) { + optConfig.generateSourceMaps = !!config.generateSourceMaps; + } + + try { + if (config.preserveLicenseComments) { + //Pull out any license comments for prepending after optimization. + try { + licenseContents = parse.getLicenseComments(fileName, fileContents); + } catch (e) { + throw new Error('Cannot parse file: ' + fileName + ' for comments. Skipping it. Error is:\n' + e.toString()); + } + } + + fileContents = licenseContents + optFunc(fileName, + fileContents, + outFileName, + keepLines, + optConfig); + } catch (e) { + if (config.throwWhen && config.throwWhen.optimize) { + throw e; + } else { + logger.error(e); + } + } + } + + return fileContents; + }, + + /** + * Optimizes one CSS file, inlining @import calls, stripping comments, and + * optionally removes line returns. + * @param {String} fileName the path to the CSS file to optimize + * @param {String} outFileName the path to save the optimized file. + * @param {Object} config the config object with the optimizeCss and + * cssImportIgnore options. + */ + cssFile: function (fileName, outFileName, config) { + + //Read in the file. Make sure we have a JS string. + var originalFileContents = file.readFile(fileName), + flat = flattenCss(fileName, originalFileContents, config.cssImportIgnore, config.cssPrefix, {}, true), + //Do not use the flattened CSS if there was one that was skipped. + fileContents = flat.skippedList.length ? originalFileContents : flat.fileContents, + startIndex, endIndex, buildText, comment; + + if (flat.skippedList.length) { + logger.warn('Cannot inline @imports for ' + fileName + + ',\nthe following files had media queries in them:\n' + + flat.skippedList.join('\n')); + } + + //Do comment removal. + try { + if (config.optimizeCss.indexOf(".keepComments") === -1) { + startIndex = 0; + //Get rid of comments. + while ((startIndex = fileContents.indexOf("/*", startIndex)) !== -1) { + endIndex = fileContents.indexOf("*/", startIndex + 2); + if (endIndex === -1) { + throw "Improper comment in CSS file: " + fileName; + } + comment = fileContents.substring(startIndex, endIndex); + + if (config.preserveLicenseComments && + (comment.indexOf('license') !== -1 || + comment.indexOf('opyright') !== -1 || + comment.indexOf('(c)') !== -1)) { + //Keep the comment, just increment the startIndex + startIndex = endIndex; + } else { + fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length); + startIndex = 0; + } + } + } + //Get rid of newlines. + if (config.optimizeCss.indexOf(".keepLines") === -1) { + fileContents = fileContents.replace(/[\r\n]/g, " "); + fileContents = fileContents.replace(/\s+/g, " "); + fileContents = fileContents.replace(/\{\s/g, "{"); + fileContents = fileContents.replace(/\s\}/g, "}"); + } else { + //Remove multiple empty lines. + fileContents = fileContents.replace(/(\r\n)+/g, "\r\n"); + fileContents = fileContents.replace(/(\n)+/g, "\n"); + } + } catch (e) { + fileContents = originalFileContents; + logger.error("Could not optimized CSS file: " + fileName + ", error: " + e); + } + + file.saveUtf8File(outFileName, fileContents); + + //text output to stdout and/or written to build.txt file + buildText = "\n"+ outFileName.replace(config.dir, "") +"\n----------------\n"; + flat.importList.push(fileName); + buildText += flat.importList.map(function(path){ + return path.replace(config.dir, ""); + }).join("\n"); + + return { + importList: flat.importList, + buildText: buildText +"\n" + }; + }, + + /** + * Optimizes CSS files, inlining @import calls, stripping comments, and + * optionally removes line returns. + * @param {String} startDir the path to the top level directory + * @param {Object} config the config object with the optimizeCss and + * cssImportIgnore options. + */ + css: function (startDir, config) { + var buildText = "", + importList = [], + shouldRemove = config.dir && config.removeCombined, + i, fileName, result, fileList; + if (config.optimizeCss.indexOf("standard") !== -1) { + fileList = file.getFilteredFileList(startDir, /\.css$/, true); + if (fileList) { + for (i = 0; i < fileList.length; i++) { + fileName = fileList[i]; + logger.trace("Optimizing (" + config.optimizeCss + ") CSS file: " + fileName); + result = optimize.cssFile(fileName, fileName, config); + buildText += result.buildText; + if (shouldRemove) { + result.importList.pop(); + importList = importList.concat(result.importList); + } + } + } + + if (shouldRemove) { + importList.forEach(function (path) { + if (file.exists(path)) { + file.deleteFile(path); + } + }); + } + } + return buildText; + }, + + optimizers: { + uglify: function (fileName, fileContents, outFileName, keepLines, config) { + var parser = uglify.parser, + processor = uglify.uglify, + ast, errMessage, errMatch; + + config = config || {}; + + logger.trace("Uglifying file: " + fileName); + + try { + ast = parser.parse(fileContents, config.strict_semicolons); + if (config.no_mangle !== true) { + ast = processor.ast_mangle(ast, config); + } + ast = processor.ast_squeeze(ast, config); + + fileContents = processor.gen_code(ast, config); + + if (config.max_line_length) { + fileContents = processor.split_lines(fileContents, config.max_line_length); + } + + //Add trailing semicolon to match uglifyjs command line version + fileContents += ';'; + } catch (e) { + errMessage = e.toString(); + errMatch = /\nError(\r)?\n/.exec(errMessage); + if (errMatch) { + errMessage = errMessage.substring(0, errMatch.index); + } + throw new Error('Cannot uglify file: ' + fileName + '. Skipping it. Error is:\n' + errMessage); + } + return fileContents; + }, + uglify2: function (fileName, fileContents, outFileName, keepLines, config) { + var result, existingMap, resultMap, finalMap, sourceIndex, + uconfig = {}, + existingMapPath = outFileName + '.map', + baseName = fileName && fileName.split('/').pop(); + + config = config || {}; + + lang.mixin(uconfig, config, true); + + uconfig.fromString = true; + + if (config.generateSourceMaps && outFileName) { + uconfig.outSourceMap = baseName; + + if (file.exists(existingMapPath)) { + uconfig.inSourceMap = existingMapPath; + existingMap = JSON.parse(file.readFile(existingMapPath)); + } + } + + logger.trace("Uglify2 file: " + fileName); + + try { + //var tempContents = fileContents.replace(/\/\/\# sourceMappingURL=.*$/, ''); + result = uglify2.minify(fileContents, uconfig, baseName + '.src.js'); + if (uconfig.outSourceMap && result.map) { + resultMap = result.map; + if (existingMap) { + resultMap = JSON.parse(resultMap); + finalMap = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(resultMap)); + finalMap.applySourceMap(new SourceMapConsumer(existingMap)); + resultMap = finalMap.toString(); + } else { + file.saveFile(outFileName + '.src.js', fileContents); + } + file.saveFile(outFileName + '.map', resultMap); + fileContents = result.code + "\n//# sourceMappingURL=" + baseName + ".map"; + } else { + fileContents = result.code; + } + } catch (e) { + throw new Error('Cannot uglify2 file: ' + fileName + '. Skipping it. Error is:\n' + e.toString()); + } + return fileContents; + } + } + }; + + return optimize; +}); +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ +/* + * This file patches require.js to communicate with the build system. + */ + +//Using sloppy since this uses eval for some code like plugins, +//which may not be strict mode compliant. So if use strict is used +//below they will have strict rules applied and may cause an error. +/*jslint sloppy: true, nomen: true, plusplus: true, regexp: true */ +/*global require, define: true */ + +//NOT asking for require as a dependency since the goal is to modify the +//global require below +define('requirePatch', [ 'env!env/file', 'pragma', 'parse', 'lang', 'logger', 'commonJs', 'prim'], function ( + file, + pragma, + parse, + lang, + logger, + commonJs, + prim +) { + + var allowRun = true, + hasProp = lang.hasProp, + falseProp = lang.falseProp, + getOwn = lang.getOwn; + + //This method should be called when the patches to require should take hold. + return function () { + if (!allowRun) { + return; + } + allowRun = false; + + var layer, + pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/, + oldNewContext = require.s.newContext, + oldDef, + + //create local undefined values for module and exports, + //so that when files are evaled in this function they do not + //see the node values used for r.js + exports, + module; + + /** + * Reset "global" build caches that are kept around between + * build layer builds. Useful to do when there are multiple + * top level requirejs.optimize() calls. + */ + require._cacheReset = function () { + //Stored raw text caches, used by browser use. + require._cachedRawText = {}; + //Stored cached file contents for reuse in other layers. + require._cachedFileContents = {}; + //Store which cached files contain a require definition. + require._cachedDefinesRequireUrls = {}; + }; + require._cacheReset(); + + /** + * Makes sure the URL is something that can be supported by the + * optimization tool. + * @param {String} url + * @returns {Boolean} + */ + require._isSupportedBuildUrl = function (url) { + //Ignore URLs with protocols, hosts or question marks, means either network + //access is needed to fetch it or it is too dynamic. Note that + //on Windows, full paths are used for some urls, which include + //the drive, like c:/something, so need to test for something other + //than just a colon. + if (url.indexOf("://") === -1 && url.indexOf("?") === -1 && + url.indexOf('empty:') !== 0 && url.indexOf('//') !== 0) { + return true; + } else { + if (!layer.ignoredUrls[url]) { + if (url.indexOf('empty:') === -1) { + logger.info('Cannot optimize network URL, skipping: ' + url); + } + layer.ignoredUrls[url] = true; + } + return false; + } + }; + + function normalizeUrlWithBase(context, moduleName, url) { + //Adjust the URL if it was not transformed to use baseUrl. + if (require.jsExtRegExp.test(moduleName)) { + url = (context.config.dir || context.config.dirBaseUrl) + url; + } + return url; + } + + //Overrides the new context call to add existing tracking features. + require.s.newContext = function (name) { + var context = oldNewContext(name), + oldEnable = context.enable, + moduleProto = context.Module.prototype, + oldInit = moduleProto.init, + oldCallPlugin = moduleProto.callPlugin; + + //Only do this for the context used for building. + if (name === '_') { + //For build contexts, do everything sync + context.nextTick = function (fn) { + fn(); + }; + + context.needFullExec = {}; + context.fullExec = {}; + context.plugins = {}; + context.buildShimExports = {}; + + //Override the shim exports function generator to just + //spit out strings that can be used in the stringified + //build output. + context.makeShimExports = function (value) { + function fn() { + return '(function (global) {\n' + + ' return function () {\n' + + ' var ret, fn;\n' + + (value.init ? + (' fn = ' + value.init.toString() + ';\n' + + ' ret = fn.apply(global, arguments);\n') : '') + + (value.exports ? + ' return ret || global.' + value.exports + ';\n' : + ' return ret;\n') + + ' };\n' + + '}(this))'; + } + + return fn; + }; + + context.enable = function (depMap, parent) { + var id = depMap.id, + parentId = parent && parent.map.id, + needFullExec = context.needFullExec, + fullExec = context.fullExec, + mod = getOwn(context.registry, id); + + if (mod && !mod.defined) { + if (parentId && getOwn(needFullExec, parentId)) { + needFullExec[id] = true; + } + + } else if ((getOwn(needFullExec, id) && falseProp(fullExec, id)) || + (parentId && getOwn(needFullExec, parentId) && + falseProp(fullExec, id))) { + context.require.undef(id); + } + + return oldEnable.apply(context, arguments); + }; + + //Override load so that the file paths can be collected. + context.load = function (moduleName, url) { + /*jslint evil: true */ + var contents, pluginBuilderMatch, builderName, + shim, shimExports; + + //Do not mark the url as fetched if it is + //not an empty: URL, used by the optimizer. + //In that case we need to be sure to call + //load() for each module that is mapped to + //empty: so that dependencies are satisfied + //correctly. + if (url.indexOf('empty:') === 0) { + delete context.urlFetched[url]; + } + + //Only handle urls that can be inlined, so that means avoiding some + //URLs like ones that require network access or may be too dynamic, + //like JSONP + if (require._isSupportedBuildUrl(url)) { + //Adjust the URL if it was not transformed to use baseUrl. + url = normalizeUrlWithBase(context, moduleName, url); + + //Save the module name to path and path to module name mappings. + layer.buildPathMap[moduleName] = url; + layer.buildFileToModule[url] = moduleName; + + if (hasProp(context.plugins, moduleName)) { + //plugins need to have their source evaled as-is. + context.needFullExec[moduleName] = true; + } + + prim().start(function () { + if (hasProp(require._cachedFileContents, url) && + (falseProp(context.needFullExec, moduleName) || + getOwn(context.fullExec, moduleName))) { + contents = require._cachedFileContents[url]; + + //If it defines require, mark it so it can be hoisted. + //Done here and in the else below, before the + //else block removes code from the contents. + //Related to #263 + if (!layer.existingRequireUrl && require._cachedDefinesRequireUrls[url]) { + layer.existingRequireUrl = url; + } + } else { + //Load the file contents, process for conditionals, then + //evaluate it. + return require._cacheReadAsync(url).then(function (text) { + contents = text; + + if (context.config.cjsTranslate && + (!context.config.shim || !lang.hasProp(context.config.shim, moduleName))) { + contents = commonJs.convert(url, contents); + } + + //If there is a read filter, run it now. + if (context.config.onBuildRead) { + contents = context.config.onBuildRead(moduleName, url, contents); + } + + contents = pragma.process(url, contents, context.config, 'OnExecute'); + + //Find out if the file contains a require() definition. Need to know + //this so we can inject plugins right after it, but before they are needed, + //and to make sure this file is first, so that define calls work. + try { + if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) { + layer.existingRequireUrl = url; + require._cachedDefinesRequireUrls[url] = true; + } + } catch (e1) { + throw new Error('Parse error using esprima ' + + 'for file: ' + url + '\n' + e1); + } + }).then(function () { + if (hasProp(context.plugins, moduleName)) { + //This is a loader plugin, check to see if it has a build extension, + //otherwise the plugin will act as the plugin builder too. + pluginBuilderMatch = pluginBuilderRegExp.exec(contents); + if (pluginBuilderMatch) { + //Load the plugin builder for the plugin contents. + builderName = context.makeModuleMap(pluginBuilderMatch[3], + context.makeModuleMap(moduleName), + null, + true).id; + return require._cacheReadAsync(context.nameToUrl(builderName)); + } + } + return contents; + }).then(function (text) { + contents = text; + + //Parse out the require and define calls. + //Do this even for plugins in case they have their own + //dependencies that may be separate to how the pluginBuilder works. + try { + if (falseProp(context.needFullExec, moduleName)) { + contents = parse(moduleName, url, contents, { + insertNeedsDefine: true, + has: context.config.has, + findNestedDependencies: context.config.findNestedDependencies + }); + } + } catch (e2) { + throw new Error('Parse error using esprima ' + + 'for file: ' + url + '\n' + e2); + } + + require._cachedFileContents[url] = contents; + }); + } + }).then(function () { + if (contents) { + eval(contents); + } + + try { + //If have a string shim config, and this is + //a fully executed module, try to see if + //it created a variable in this eval scope + if (getOwn(context.needFullExec, moduleName)) { + shim = getOwn(context.config.shim, moduleName); + if (shim && shim.exports) { + shimExports = eval(shim.exports); + if (typeof shimExports !== 'undefined') { + context.buildShimExports[moduleName] = shimExports; + } + } + } + + //Need to close out completion of this module + //so that listeners will get notified that it is available. + context.completeLoad(moduleName); + } catch (e) { + //Track which module could not complete loading. + if (!e.moduleTree) { + e.moduleTree = []; + } + e.moduleTree.push(moduleName); + throw e; + } + }).then(null, function (eOuter) { + + if (!eOuter.fileName) { + eOuter.fileName = url; + } + throw eOuter; + }).end(); + } else { + //With unsupported URLs still need to call completeLoad to + //finish loading. + context.completeLoad(moduleName); + } + }; + + //Marks module has having a name, and optionally executes the + //callback, but only if it meets certain criteria. + context.execCb = function (name, cb, args, exports) { + var buildShimExports = getOwn(layer.context.buildShimExports, name); + + if (buildShimExports) { + return buildShimExports; + } else if (cb.__requireJsBuild || getOwn(layer.context.needFullExec, name)) { + return cb.apply(exports, args); + } + return undefined; + }; + + moduleProto.init = function (depMaps) { + if (context.needFullExec[this.map.id]) { + lang.each(depMaps, lang.bind(this, function (depMap) { + if (typeof depMap === 'string') { + depMap = context.makeModuleMap(depMap, + (this.map.isDefine ? this.map : this.map.parentMap)); + } + + if (!context.fullExec[depMap.id]) { + context.require.undef(depMap.id); + } + })); + } + + return oldInit.apply(this, arguments); + }; + + moduleProto.callPlugin = function () { + var map = this.map, + pluginMap = context.makeModuleMap(map.prefix), + pluginId = pluginMap.id, + pluginMod = getOwn(context.registry, pluginId); + + context.plugins[pluginId] = true; + context.needFullExec[pluginId] = true; + + //If the module is not waiting to finish being defined, + //undef it and start over, to get full execution. + if (falseProp(context.fullExec, pluginId) && (!pluginMod || pluginMod.defined)) { + context.require.undef(pluginMap.id); + } + + return oldCallPlugin.apply(this, arguments); + }; + } + + return context; + }; + + //Clear up the existing context so that the newContext modifications + //above will be active. + delete require.s.contexts._; + + /** Reset state for each build layer pass. */ + require._buildReset = function () { + var oldContext = require.s.contexts._; + + //Clear up the existing context. + delete require.s.contexts._; + + //Set up new context, so the layer object can hold onto it. + require({}); + + layer = require._layer = { + buildPathMap: {}, + buildFileToModule: {}, + buildFilePaths: [], + pathAdded: {}, + modulesWithNames: {}, + needsDefine: {}, + existingRequireUrl: "", + ignoredUrls: {}, + context: require.s.contexts._ + }; + + //Return the previous context in case it is needed, like for + //the basic config object. + return oldContext; + }; + + require._buildReset(); + + //Override define() to catch modules that just define an object, so that + //a dummy define call is not put in the build file for them. They do + //not end up getting defined via context.execCb, so we need to catch them + //at the define call. + oldDef = define; + + //This function signature does not have to be exact, just match what we + //are looking for. + define = function (name) { + if (typeof name === "string" && falseProp(layer.needsDefine, name)) { + layer.modulesWithNames[name] = true; + } + return oldDef.apply(require, arguments); + }; + + define.amd = oldDef.amd; + + //Add some utilities for plugins + require._readFile = file.readFile; + require._fileExists = function (path) { + return file.exists(path); + }; + + //Called when execManager runs for a dependency. Used to figure out + //what order of execution. + require.onResourceLoad = function (context, map) { + var id = map.id, + url; + + //If build needed a full execution, indicate it + //has been done now. But only do it if the context is tracking + //that. Only valid for the context used in a build, not for + //other contexts being run, like for useLib, plain requirejs + //use in node/rhino. + if (context.needFullExec && getOwn(context.needFullExec, id)) { + context.fullExec[id] = true; + } + + //A plugin. + if (map.prefix) { + if (falseProp(layer.pathAdded, id)) { + layer.buildFilePaths.push(id); + //For plugins the real path is not knowable, use the name + //for both module to file and file to module mappings. + layer.buildPathMap[id] = id; + layer.buildFileToModule[id] = id; + layer.modulesWithNames[id] = true; + layer.pathAdded[id] = true; + } + } else if (map.url && require._isSupportedBuildUrl(map.url)) { + //If the url has not been added to the layer yet, and it + //is from an actual file that was loaded, add it now. + url = normalizeUrlWithBase(context, id, map.url); + if (!layer.pathAdded[url] && getOwn(layer.buildPathMap, id)) { + //Remember the list of dependencies for this layer. + layer.buildFilePaths.push(url); + layer.pathAdded[url] = true; + } + } + }; + + //Called by output of the parse() function, when a file does not + //explicitly call define, probably just require, but the parse() + //function normalizes on define() for dependency mapping and file + //ordering works correctly. + require.needsDefine = function (moduleName) { + layer.needsDefine[moduleName] = true; + }; + }; +}); +/** + * @license RequireJS Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint */ +/*global define: false, console: false */ + +define('commonJs', ['env!env/file', 'parse'], function (file, parse) { + 'use strict'; + var commonJs = { + //Set to false if you do not want this file to log. Useful in environments + //like node where you want the work to happen without noise. + useLog: true, + + convertDir: function (commonJsPath, savePath) { + var fileList, i, + jsFileRegExp = /\.js$/, + fileName, convertedFileName, fileContents; + + //Get list of files to convert. + fileList = file.getFilteredFileList(commonJsPath, /\w/, true); + + //Normalize on front slashes and make sure the paths do not end in a slash. + commonJsPath = commonJsPath.replace(/\\/g, "/"); + savePath = savePath.replace(/\\/g, "/"); + if (commonJsPath.charAt(commonJsPath.length - 1) === "/") { + commonJsPath = commonJsPath.substring(0, commonJsPath.length - 1); + } + if (savePath.charAt(savePath.length - 1) === "/") { + savePath = savePath.substring(0, savePath.length - 1); + } + + //Cycle through all the JS files and convert them. + if (!fileList || !fileList.length) { + if (commonJs.useLog) { + if (commonJsPath === "convert") { + //A request just to convert one file. + console.log('\n\n' + commonJs.convert(savePath, file.readFile(savePath))); + } else { + console.log("No files to convert in directory: " + commonJsPath); + } + } + } else { + for (i = 0; i < fileList.length; i++) { + fileName = fileList[i]; + convertedFileName = fileName.replace(commonJsPath, savePath); + + //Handle JS files. + if (jsFileRegExp.test(fileName)) { + fileContents = file.readFile(fileName); + fileContents = commonJs.convert(fileName, fileContents); + file.saveUtf8File(convertedFileName, fileContents); + } else { + //Just copy the file over. + file.copyFile(fileName, convertedFileName, true); + } + } + } + }, + + /** + * Does the actual file conversion. + * + * @param {String} fileName the name of the file. + * + * @param {String} fileContents the contents of a file :) + * + * @returns {String} the converted contents + */ + convert: function (fileName, fileContents) { + //Strip out comments. + try { + var preamble = '', + commonJsProps = parse.usesCommonJs(fileName, fileContents); + + //First see if the module is not already RequireJS-formatted. + if (parse.usesAmdOrRequireJs(fileName, fileContents) || !commonJsProps) { + return fileContents; + } + + if (commonJsProps.dirname || commonJsProps.filename) { + preamble = 'var __filename = module.uri || "", ' + + '__dirname = __filename.substring(0, __filename.lastIndexOf("/") + 1); '; + } + + //Construct the wrapper boilerplate. + fileContents = 'define(function (require, exports, module) {' + + preamble + + fileContents + + '\n});\n'; + + } catch (e) { + console.log("commonJs.convert: COULD NOT CONVERT: " + fileName + ", so skipping it. Error was: " + e); + return fileContents; + } + + return fileContents; + } + }; + + return commonJs; +}); +/** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/*jslint plusplus: true, nomen: true, regexp: true */ +/*global define, requirejs */ + + +define('build', function (require) { + 'use strict'; + + var build, buildBaseConfig, + lang = require('lang'), + prim = require('prim'), + logger = require('logger'), + file = require('env!env/file'), + parse = require('parse'), + optimize = require('optimize'), + pragma = require('pragma'), + transform = require('transform'), + requirePatch = require('requirePatch'), + env = require('env'), + commonJs = require('commonJs'), + SourceMapGenerator = require('source-map/source-map-generator'), + hasProp = lang.hasProp, + getOwn = lang.getOwn, + falseProp = lang.falseProp, + endsWithSemiColonRegExp = /;\s*$/, + resourceIsModuleIdRegExp = /^[\w\/\\\.]+$/; + + prim.nextTick = function (fn) { + fn(); + }; + + //Now map require to the outermost requirejs, now that we have + //local dependencies for this module. The rest of the require use is + //manipulating the requirejs loader. + require = requirejs; + + //Caching function for performance. Attached to + //require so it can be reused in requirePatch.js. _cachedRawText + //set up by requirePatch.js + require._cacheReadAsync = function (path, encoding) { + var d; + + if (lang.hasProp(require._cachedRawText, path)) { + d = prim(); + d.resolve(require._cachedRawText[path]); + return d.promise; + } else { + return file.readFileAsync(path, encoding).then(function (text) { + require._cachedRawText[path] = text; + return text; + }); + } + }; + + buildBaseConfig = { + appDir: "", + pragmas: {}, + paths: {}, + optimize: "uglify", + optimizeCss: "standard.keepLines", + inlineText: true, + isBuild: true, + optimizeAllPluginResources: false, + findNestedDependencies: false, + preserveLicenseComments: true, + //By default, all files/directories are copied, unless + //they match this regexp, by default just excludes .folders + dirExclusionRegExp: file.dirExclusionRegExp, + _buildPathToModuleIndex: {} + }; + + /** + * Some JS may not be valid if concatenated with other JS, in particular + * the style of omitting semicolons and rely on ASI. Add a semicolon in + * those cases. + */ + function addSemiColon(text, config) { + if (config.skipSemiColonInsertion || endsWithSemiColonRegExp.test(text)) { + return text; + } else { + return text + ";"; + } + } + + function endsWithSlash(dirName) { + if (dirName.charAt(dirName.length - 1) !== "/") { + dirName += "/"; + } + return dirName; + } + + //Method used by plugin writeFile calls, defined up here to avoid + //jslint warning about "making a function in a loop". + function makeWriteFile(namespace, layer) { + function writeFile(name, contents) { + logger.trace('Saving plugin-optimized file: ' + name); + file.saveUtf8File(name, contents); + } + + writeFile.asModule = function (moduleName, fileName, contents) { + writeFile(fileName, + build.toTransport(namespace, moduleName, fileName, contents, layer)); + }; + + return writeFile; + } + + /** + * Main API entry point into the build. The args argument can either be + * an array of arguments (like the onese passed on a command-line), + * or it can be a JavaScript object that has the format of a build profile + * file. + * + * If it is an object, then in addition to the normal properties allowed in + * a build profile file, the object should contain one other property: + * + * The object could also contain a "buildFile" property, which is a string + * that is the file path to a build profile that contains the rest + * of the build profile directives. + * + * This function does not return a status, it should throw an error if + * there is a problem completing the build. + */ + build = function (args) { + var buildFile, cmdConfig, errorMsg, errorStack, stackMatch, errorTree, + i, j, errorMod, + stackRegExp = /( {4}at[^\n]+)\n/, + standardIndent = ' '; + + return prim().start(function () { + if (!args || lang.isArray(args)) { + if (!args || args.length < 1) { + logger.error("build.js buildProfile.js\n" + + "where buildProfile.js is the name of the build file (see example.build.js for hints on how to make a build file)."); + return undefined; + } + + //Next args can include a build file path as well as other build args. + //build file path comes first. If it does not contain an = then it is + //a build file path. Otherwise, just all build args. + if (args[0].indexOf("=") === -1) { + buildFile = args[0]; + args.splice(0, 1); + } + + //Remaining args are options to the build + cmdConfig = build.convertArrayToObject(args); + cmdConfig.buildFile = buildFile; + } else { + cmdConfig = args; + } + + return build._run(cmdConfig); + }).then(null, function (e) { + var err; + + errorMsg = e.toString(); + errorTree = e.moduleTree; + stackMatch = stackRegExp.exec(errorMsg); + + if (stackMatch) { + errorMsg += errorMsg.substring(0, stackMatch.index + stackMatch[0].length + 1); + } + + //If a module tree that shows what module triggered the error, + //print it out. + if (errorTree && errorTree.length > 0) { + errorMsg += '\nIn module tree:\n'; + + for (i = errorTree.length - 1; i > -1; i--) { + errorMod = errorTree[i]; + if (errorMod) { + for (j = errorTree.length - i; j > -1; j--) { + errorMsg += standardIndent; + } + errorMsg += errorMod + '\n'; + } + } + + logger.error(errorMsg); + } + + errorStack = e.stack; + + if (typeof args === 'string' && args.indexOf('stacktrace=true') !== -1) { + errorMsg += '\n' + errorStack; + } else { + if (!stackMatch && errorStack) { + //Just trim out the first "at" in the stack. + stackMatch = stackRegExp.exec(errorStack); + if (stackMatch) { + errorMsg += '\n' + stackMatch[0] || ''; + } + } + } + + err = new Error(errorMsg); + err.originalError = e; + throw err; + }); + }; + + build._run = function (cmdConfig) { + var buildPaths, fileName, fileNames, + paths, i, + baseConfig, config, + modules, srcPath, buildContext, + destPath, moduleMap, parentModuleMap, context, + resources, resource, plugin, fileContents, + pluginProcessed = {}, + buildFileContents = "", + pluginCollector = {}; + + return prim().start(function () { + var prop; + + //Can now run the patches to require.js to allow it to be used for + //build generation. Do it here instead of at the top of the module + //because we want normal require behavior to load the build tool + //then want to switch to build mode. + requirePatch(); + + config = build.createConfig(cmdConfig); + paths = config.paths; + + //Remove the previous build dir, in case it contains source transforms, + //like the ones done with onBuildRead and onBuildWrite. + if (config.dir && !config.keepBuildDir && file.exists(config.dir)) { + file.deleteFile(config.dir); + } + + if (!config.out && !config.cssIn) { + //This is not just a one-off file build but a full build profile, with + //lots of files to process. + + //First copy all the baseUrl content + file.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true); + + //Adjust baseUrl if config.appDir is in play, and set up build output paths. + buildPaths = {}; + if (config.appDir) { + //All the paths should be inside the appDir, so just adjust + //the paths to use the dirBaseUrl + for (prop in paths) { + if (hasProp(paths, prop)) { + buildPaths[prop] = paths[prop].replace(config.appDir, config.dir); + } + } + } else { + //If no appDir, then make sure to copy the other paths to this directory. + for (prop in paths) { + if (hasProp(paths, prop)) { + //Set up build path for each path prefix, but only do so + //if the path falls out of the current baseUrl + if (paths[prop].indexOf(config.baseUrl) === 0) { + buildPaths[prop] = paths[prop].replace(config.baseUrl, config.dirBaseUrl); + } else { + buildPaths[prop] = paths[prop] === 'empty:' ? 'empty:' : prop.replace(/\./g, "/"); + + //Make sure source path is fully formed with baseUrl, + //if it is a relative URL. + srcPath = paths[prop]; + if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) { + srcPath = config.baseUrl + srcPath; + } + + destPath = config.dirBaseUrl + buildPaths[prop]; + + //Skip empty: paths + if (srcPath !== 'empty:') { + //If the srcPath is a directory, copy the whole directory. + if (file.exists(srcPath) && file.isDirectory(srcPath)) { + //Copy files to build area. Copy all files (the /\w/ regexp) + file.copyDir(srcPath, destPath, /\w/, true); + } else { + //Try a .js extension + srcPath += '.js'; + destPath += '.js'; + file.copyFile(srcPath, destPath); + } + } + } + } + } + } + } + + //Figure out source file location for each module layer. Do this by seeding require + //with source area configuration. This is needed so that later the module layers + //can be manually copied over to the source area, since the build may be + //require multiple times and the above copyDir call only copies newer files. + require({ + baseUrl: config.baseUrl, + paths: paths, + packagePaths: config.packagePaths, + packages: config.packages + }); + buildContext = require.s.contexts._; + modules = config.modules; + + if (modules) { + modules.forEach(function (module) { + if (module.name) { + module._sourcePath = buildContext.nameToUrl(module.name); + //If the module does not exist, and this is not a "new" module layer, + //as indicated by a true "create" property on the module, and + //it is not a plugin-loaded resource, and there is no + //'rawText' containing the module's source then throw an error. + if (!file.exists(module._sourcePath) && !module.create && + module.name.indexOf('!') === -1 && + (!config.rawText || !lang.hasProp(config.rawText, module.name))) { + throw new Error("ERROR: module path does not exist: " + + module._sourcePath + " for module named: " + module.name + + ". Path is relative to: " + file.absPath('.')); + } + } + }); + } + + if (config.out) { + //Just set up the _buildPath for the module layer. + require(config); + if (!config.cssIn) { + config.modules[0]._buildPath = typeof config.out === 'function' ? + 'FUNCTION' : config.out; + } + } else if (!config.cssIn) { + //Now set up the config for require to use the build area, and calculate the + //build file locations. Pass along any config info too. + baseConfig = { + baseUrl: config.dirBaseUrl, + paths: buildPaths + }; + + lang.mixin(baseConfig, config); + require(baseConfig); + + if (modules) { + modules.forEach(function (module) { + if (module.name) { + module._buildPath = buildContext.nameToUrl(module.name, null); + if (!module.create) { + file.copyFile(module._sourcePath, module._buildPath); + } + } + }); + } + } + + //Run CSS optimizations before doing JS module tracing, to allow + //things like text loader plugins loading CSS to get the optimized + //CSS. + if (config.optimizeCss && config.optimizeCss !== "none" && config.dir) { + buildFileContents += optimize.css(config.dir, config); + } + }).then(function() { + baseConfig = lang.deeplikeCopy(require.s.contexts._.config); + }).then(function () { + var actions = []; + + if (modules) { + actions = modules.map(function (module, i) { + return function () { + //Save off buildPath to module index in a hash for quicker + //lookup later. + config._buildPathToModuleIndex[file.normalize(module._buildPath)] = i; + + //Call require to calculate dependencies. + return build.traceDependencies(module, config, baseConfig) + .then(function (layer) { + module.layer = layer; + }); + }; + }); + + return prim.serial(actions); + } + }).then(function () { + var actions; + + if (modules) { + //Now build up shadow layers for anything that should be excluded. + //Do this after tracing dependencies for each module, in case one + //of those modules end up being one of the excluded values. + actions = modules.map(function (module) { + return function () { + if (module.exclude) { + module.excludeLayers = []; + return prim.serial(module.exclude.map(function (exclude, i) { + return function () { + //See if it is already in the list of modules. + //If not trace dependencies for it. + var found = build.findBuildModule(exclude, modules); + if (found) { + module.excludeLayers[i] = found; + } else { + return build.traceDependencies({name: exclude}, config, baseConfig) + .then(function (layer) { + module.excludeLayers[i] = { layer: layer }; + }); + } + }; + })); + } + }; + }); + + return prim.serial(actions); + } + }).then(function () { + if (modules) { + return prim.serial(modules.map(function (module) { + return function () { + if (module.exclude) { + //module.exclude is an array of module names. For each one, + //get the nested dependencies for it via a matching entry + //in the module.excludeLayers array. + module.exclude.forEach(function (excludeModule, i) { + var excludeLayer = module.excludeLayers[i].layer, + map = excludeLayer.buildFileToModule; + excludeLayer.buildFilePaths.forEach(function(filePath){ + build.removeModulePath(map[filePath], filePath, module.layer); + }); + }); + } + if (module.excludeShallow) { + //module.excludeShallow is an array of module names. + //shallow exclusions are just that module itself, and not + //its nested dependencies. + module.excludeShallow.forEach(function (excludeShallowModule) { + var path = getOwn(module.layer.buildPathMap, excludeShallowModule); + if (path) { + build.removeModulePath(excludeShallowModule, path, module.layer); + } + }); + } + + //Flatten them and collect the build output for each module. + return build.flattenModule(module, module.layer, config).then(function (builtModule) { + var finalText, baseName; + //Save it to a temp file for now, in case there are other layers that + //contain optimized content that should not be included in later + //layer optimizations. See issue #56. + if (module._buildPath === 'FUNCTION') { + module._buildText = builtModule.text; + module._buildSourceMap = builtModule.sourceMap; + } else { + finalText = builtModule.text; + if (builtModule.sourceMap) { + baseName = module._buildPath.split('/'); + baseName = baseName.pop(); + finalText += '\n//# sourceMappingURL=' + baseName + '.map'; + file.saveUtf8File(module._buildPath + '.map', builtModule.sourceMap); + } + file.saveUtf8File(module._buildPath + '-temp', finalText); + + } + buildFileContents += builtModule.buildText; + }); + }; + })); + } + }).then(function () { + var moduleName; + if (modules) { + //Now move the build layers to their final position. + modules.forEach(function (module) { + var finalPath = module._buildPath; + if (finalPath !== 'FUNCTION') { + if (file.exists(finalPath)) { + file.deleteFile(finalPath); + } + file.renameFile(finalPath + '-temp', finalPath); + + //And finally, if removeCombined is specified, remove + //any of the files that were used in this layer. + //Be sure not to remove other build layers. + if (config.removeCombined && !config.out) { + module.layer.buildFilePaths.forEach(function (path) { + var isLayer = modules.some(function (mod) { + return mod._buildPath === path; + }), + relPath = build.makeRelativeFilePath(config.dir, path); + + if (file.exists(path) && + // not a build layer target + !isLayer && + // not outside the build directory + relPath.indexOf('..') !== 0) { + file.deleteFile(path); + } + }); + } + } + + //Signal layer is done + if (config.onModuleBundleComplete) { + config.onModuleBundleComplete(module.onCompleteData); + } + }); + } + + //If removeCombined in play, remove any empty directories that + //may now exist because of its use + if (config.removeCombined && !config.out && config.dir) { + file.deleteEmptyDirs(config.dir); + } + + //Do other optimizations. + if (config.out && !config.cssIn) { + //Just need to worry about one JS file. + fileName = config.modules[0]._buildPath; + if (fileName === 'FUNCTION') { + config.modules[0]._buildText = optimize.js(fileName, + config.modules[0]._buildText, + null, + config); + } else { + optimize.jsFile(fileName, null, fileName, config); + } + } else if (!config.cssIn) { + //Normal optimizations across modules. + + //JS optimizations. + fileNames = file.getFilteredFileList(config.dir, /\.js$/, true); + fileNames.forEach(function (fileName) { + var cfg, override, moduleIndex; + + //Generate the module name from the config.dir root. + moduleName = fileName.replace(config.dir, ''); + //Get rid of the extension + moduleName = moduleName.substring(0, moduleName.length - 3); + + //If there is an override for a specific layer build module, + //and this file is that module, mix in the override for use + //by optimize.jsFile. + moduleIndex = getOwn(config._buildPathToModuleIndex, fileName); + //Normalize, since getOwn could have returned undefined + moduleIndex = moduleIndex === 0 || moduleIndex > 0 ? moduleIndex : -1; + + //Try to avoid extra work if the other files do not need to + //be read. Build layers should be processed at the very + //least for optimization. + if (moduleIndex > -1 || !config.skipDirOptimize || + config.normalizeDirDefines === "all" || + config.cjsTranslate) { + //Convert the file to transport format, but without a name + //inserted (by passing null for moduleName) since the files are + //standalone, one module per file. + fileContents = file.readFile(fileName); + + + //For builds, if wanting cjs translation, do it now, so that + //the individual modules can be loaded cross domain via + //plain script tags. + if (config.cjsTranslate && + (!config.shim || !lang.hasProp(config.shim, moduleName))) { + fileContents = commonJs.convert(fileName, fileContents); + } + + if (moduleIndex === -1) { + if (config.onBuildRead) { + fileContents = config.onBuildRead(moduleName, + fileName, + fileContents); + } + + //Only do transport normalization if this is not a build + //layer (since it was already normalized) and if + //normalizeDirDefines indicated all should be done. + if (config.normalizeDirDefines === "all") { + fileContents = build.toTransport(config.namespace, + null, + fileName, + fileContents); + } + + if (config.onBuildWrite) { + fileContents = config.onBuildWrite(moduleName, + fileName, + fileContents); + } + } + + override = moduleIndex > -1 ? + config.modules[moduleIndex].override : null; + if (override) { + cfg = build.createOverrideConfig(config, override); + } else { + cfg = config; + } + + if (moduleIndex > -1 || !config.skipDirOptimize) { + optimize.jsFile(fileName, fileContents, fileName, cfg, pluginCollector); + } + } + }); + + //Normalize all the plugin resources. + context = require.s.contexts._; + + for (moduleName in pluginCollector) { + if (hasProp(pluginCollector, moduleName)) { + parentModuleMap = context.makeModuleMap(moduleName); + resources = pluginCollector[moduleName]; + for (i = 0; i < resources.length; i++) { + resource = resources[i]; + moduleMap = context.makeModuleMap(resource, parentModuleMap); + if (falseProp(context.plugins, moduleMap.prefix)) { + //Set the value in context.plugins so it + //will be evaluated as a full plugin. + context.plugins[moduleMap.prefix] = true; + + //Do not bother if the plugin is not available. + if (!file.exists(require.toUrl(moduleMap.prefix + '.js'))) { + continue; + } + + //Rely on the require in the build environment + //to be synchronous + context.require([moduleMap.prefix]); + + //Now that the plugin is loaded, redo the moduleMap + //since the plugin will need to normalize part of the path. + moduleMap = context.makeModuleMap(resource, parentModuleMap); + } + + //Only bother with plugin resources that can be handled + //processed by the plugin, via support of the writeFile + //method. + if (falseProp(pluginProcessed, moduleMap.id)) { + //Only do the work if the plugin was really loaded. + //Using an internal access because the file may + //not really be loaded. + plugin = getOwn(context.defined, moduleMap.prefix); + if (plugin && plugin.writeFile) { + plugin.writeFile( + moduleMap.prefix, + moduleMap.name, + require, + makeWriteFile( + config.namespace + ), + context.config + ); + } + + pluginProcessed[moduleMap.id] = true; + } + } + + } + } + + //console.log('PLUGIN COLLECTOR: ' + JSON.stringify(pluginCollector, null, " ")); + + + //All module layers are done, write out the build.txt file. + file.saveUtf8File(config.dir + "build.txt", buildFileContents); + } + + //If just have one CSS file to optimize, do that here. + if (config.cssIn) { + buildFileContents += optimize.cssFile(config.cssIn, config.out, config).buildText; + } + + if (typeof config.out === 'function') { + config.out(config.modules[0]._buildText); + } + + //Print out what was built into which layers. + if (buildFileContents) { + logger.info(buildFileContents); + return buildFileContents; + } + + return ''; + }); + }; + + /** + * Converts command line args like "paths.foo=../some/path" + * result.paths = { foo: '../some/path' } where prop = paths, + * name = paths.foo and value = ../some/path, so it assumes the + * name=value splitting has already happened. + */ + function stringDotToObj(result, name, value) { + var parts = name.split('.'); + + parts.forEach(function (prop, i) { + if (i === parts.length - 1) { + result[prop] = value; + } else { + if (falseProp(result, prop)) { + result[prop] = {}; + } + result = result[prop]; + } + + }); + } + + build.objProps = { + paths: true, + wrap: true, + pragmas: true, + pragmasOnSave: true, + has: true, + hasOnSave: true, + uglify: true, + uglify2: true, + closure: true, + map: true, + throwWhen: true + }; + + build.hasDotPropMatch = function (prop) { + var dotProp, + index = prop.indexOf('.'); + + if (index !== -1) { + dotProp = prop.substring(0, index); + return hasProp(build.objProps, dotProp); + } + return false; + }; + + /** + * Converts an array that has String members of "name=value" + * into an object, where the properties on the object are the names in the array. + * Also converts the strings "true" and "false" to booleans for the values. + * member name/value pairs, and converts some comma-separated lists into + * arrays. + * @param {Array} ary + */ + build.convertArrayToObject = function (ary) { + var result = {}, i, separatorIndex, prop, value, + needArray = { + "include": true, + "exclude": true, + "excludeShallow": true, + "insertRequire": true, + "stubModules": true, + "deps": true + }; + + for (i = 0; i < ary.length; i++) { + separatorIndex = ary[i].indexOf("="); + if (separatorIndex === -1) { + throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value"; + } + + value = ary[i].substring(separatorIndex + 1, ary[i].length); + if (value === "true") { + value = true; + } else if (value === "false") { + value = false; + } + + prop = ary[i].substring(0, separatorIndex); + + //Convert to array if necessary + if (getOwn(needArray, prop)) { + value = value.split(","); + } + + if (build.hasDotPropMatch(prop)) { + stringDotToObj(result, prop, value); + } else { + result[prop] = value; + } + } + return result; //Object + }; + + build.makeAbsPath = function (path, absFilePath) { + if (!absFilePath) { + return path; + } + + //Add abspath if necessary. If path starts with a slash or has a colon, + //then already is an abolute path. + if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) { + path = absFilePath + + (absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') + + path; + path = file.normalize(path); + } + return path.replace(lang.backSlashRegExp, '/'); + }; + + build.makeAbsObject = function (props, obj, absFilePath) { + var i, prop; + if (obj) { + for (i = 0; i < props.length; i++) { + prop = props[i]; + if (hasProp(obj, prop) && typeof obj[prop] === 'string') { + obj[prop] = build.makeAbsPath(obj[prop], absFilePath); + } + } + } + }; + + /** + * For any path in a possible config, make it absolute relative + * to the absFilePath passed in. + */ + build.makeAbsConfig = function (config, absFilePath) { + var props, prop, i; + + props = ["appDir", "dir", "baseUrl"]; + for (i = 0; i < props.length; i++) { + prop = props[i]; + + if (getOwn(config, prop)) { + //Add abspath if necessary, make sure these paths end in + //slashes + if (prop === "baseUrl") { + config.originalBaseUrl = config.baseUrl; + if (config.appDir) { + //If baseUrl with an appDir, the baseUrl is relative to + //the appDir, *not* the absFilePath. appDir and dir are + //made absolute before baseUrl, so this will work. + config.baseUrl = build.makeAbsPath(config.originalBaseUrl, config.appDir); + } else { + //The dir output baseUrl is same as regular baseUrl, both + //relative to the absFilePath. + config.baseUrl = build.makeAbsPath(config[prop], absFilePath); + } + } else { + config[prop] = build.makeAbsPath(config[prop], absFilePath); + } + + config[prop] = endsWithSlash(config[prop]); + } + } + + build.makeAbsObject(["out", "cssIn"], config, absFilePath); + build.makeAbsObject(["startFile", "endFile"], config.wrap, absFilePath); + }; + + /** + * Creates a relative path to targetPath from refPath. + * Only deals with file paths, not folders. If folders, + * make sure paths end in a trailing '/'. + */ + build.makeRelativeFilePath = function (refPath, targetPath) { + var i, dotLength, finalParts, length, + refParts = refPath.split('/'), + targetParts = targetPath.split('/'), + //Pull off file name + targetName = targetParts.pop(), + dotParts = []; + + //Also pop off the ref file name to make the matches against + //targetParts equivalent. + refParts.pop(); + + length = refParts.length; + + for (i = 0; i < length; i += 1) { + if (refParts[i] !== targetParts[i]) { + break; + } + } + + //Now i is the index in which they diverge. + finalParts = targetParts.slice(i); + + dotLength = length - i; + for (i = 0; i > -1 && i < dotLength; i += 1) { + dotParts.push('..'); + } + + return dotParts.join('/') + (dotParts.length ? '/' : '') + + finalParts.join('/') + (finalParts.length ? '/' : '') + + targetName; + }; + + build.nestedMix = { + paths: true, + has: true, + hasOnSave: true, + pragmas: true, + pragmasOnSave: true + }; + + /** + * Mixes additional source config into target config, and merges some + * nested config, like paths, correctly. + */ + function mixConfig(target, source) { + var prop, value; + + for (prop in source) { + if (hasProp(source, prop)) { + //If the value of the property is a plain object, then + //allow a one-level-deep mixing of it. + value = source[prop]; + if (typeof value === 'object' && value && + !lang.isArray(value) && !lang.isFunction(value) && + !lang.isRegExp(value)) { + target[prop] = lang.mixin({}, target[prop], value, true); + } else { + target[prop] = value; + } + } + } + + //Set up log level since it can affect if errors are thrown + //or caught and passed to errbacks while doing config setup. + if (lang.hasProp(target, 'logLevel')) { + logger.logLevel(target.logLevel); + } + } + + /** + * Converts a wrap.startFile or endFile to be start/end as a string. + * the startFile/endFile values can be arrays. + */ + function flattenWrapFile(wrap, keyName, absFilePath) { + var keyFileName = keyName + 'File'; + + if (typeof wrap[keyName] !== 'string' && wrap[keyFileName]) { + wrap[keyName] = ''; + if (typeof wrap[keyFileName] === 'string') { + wrap[keyFileName] = [wrap[keyFileName]]; + } + wrap[keyFileName].forEach(function (fileName) { + wrap[keyName] += (wrap[keyName] ? '\n' : '') + + file.readFile(build.makeAbsPath(fileName, absFilePath)); + }); + } else if (wrap[keyName] === null || wrap[keyName] === undefined) { + //Allow missing one, just set to empty string. + wrap[keyName] = ''; + } else if (typeof wrap[keyName] !== 'string') { + throw new Error('wrap.' + keyName + ' or wrap.' + keyFileName + ' malformed'); + } + } + + function normalizeWrapConfig(config, absFilePath) { + //Get any wrap text. + try { + if (config.wrap) { + if (config.wrap === true) { + //Use default values. + config.wrap = { + start: '(function () {', + end: '}());' + }; + } else { + flattenWrapFile(config.wrap, 'start', absFilePath); + flattenWrapFile(config.wrap, 'end', absFilePath); + } + } + } catch (wrapError) { + throw new Error('Malformed wrap config: ' + wrapError.toString()); + } + } + + /** + * Creates a config object for an optimization build. + * It will also read the build profile if it is available, to create + * the configuration. + * + * @param {Object} cfg config options that take priority + * over defaults and ones in the build file. These options could + * be from a command line, for instance. + * + * @param {Object} the created config object. + */ + build.createConfig = function (cfg) { + /*jslint evil: true */ + var config = {}, buildFileContents, buildFileConfig, mainConfig, + mainConfigFile, mainConfigPath, buildFile, absFilePath; + + //Make sure all paths are relative to current directory. + absFilePath = file.absPath('.'); + build.makeAbsConfig(cfg, absFilePath); + build.makeAbsConfig(buildBaseConfig, absFilePath); + + lang.mixin(config, buildBaseConfig); + lang.mixin(config, cfg, true); + + //Set up log level early since it can affect if errors are thrown + //or caught and passed to errbacks, even while constructing config. + if (lang.hasProp(config, 'logLevel')) { + logger.logLevel(config.logLevel); + } + + if (config.buildFile) { + //A build file exists, load it to get more config. + buildFile = file.absPath(config.buildFile); + + //Find the build file, and make sure it exists, if this is a build + //that has a build profile, and not just command line args with an in=path + if (!file.exists(buildFile)) { + throw new Error("ERROR: build file does not exist: " + buildFile); + } + + absFilePath = config.baseUrl = file.absPath(file.parent(buildFile)); + + //Load build file options. + buildFileContents = file.readFile(buildFile); + try { + buildFileConfig = eval("(" + buildFileContents + ")"); + build.makeAbsConfig(buildFileConfig, absFilePath); + + //Mix in the config now so that items in mainConfigFile can + //be resolved relative to them if necessary, like if appDir + //is set here, but the baseUrl is in mainConfigFile. Will + //re-mix in the same build config later after mainConfigFile + //is processed, since build config should take priority. + mixConfig(config, buildFileConfig); + } catch (e) { + throw new Error("Build file " + buildFile + " is malformed: " + e); + } + } + + mainConfigFile = config.mainConfigFile || (buildFileConfig && buildFileConfig.mainConfigFile); + if (mainConfigFile) { + mainConfigFile = build.makeAbsPath(mainConfigFile, absFilePath); + if (!file.exists(mainConfigFile)) { + throw new Error(mainConfigFile + ' does not exist.'); + } + try { + mainConfig = parse.findConfig(file.readFile(mainConfigFile)).config; + } catch (configError) { + throw new Error('The config in mainConfigFile ' + + mainConfigFile + + ' cannot be used because it cannot be evaluated' + + ' correctly while running in the optimizer. Try only' + + ' using a config that is also valid JSON, or do not use' + + ' mainConfigFile and instead copy the config values needed' + + ' into a build file or command line arguments given to the optimizer.\n' + + 'Source error from parsing: ' + mainConfigFile + ': ' + configError); + } + if (mainConfig) { + mainConfigPath = mainConfigFile.substring(0, mainConfigFile.lastIndexOf('/')); + + //Add in some existing config, like appDir, since they can be + //used inside the mainConfigFile -- paths and baseUrl are + //relative to them. + if (config.appDir && !mainConfig.appDir) { + mainConfig.appDir = config.appDir; + } + + //If no baseUrl, then use the directory holding the main config. + if (!mainConfig.baseUrl) { + mainConfig.baseUrl = mainConfigPath; + } + + build.makeAbsConfig(mainConfig, mainConfigPath); + mixConfig(config, mainConfig); + } + } + + //Mix in build file config, but only after mainConfig has been mixed in. + if (buildFileConfig) { + mixConfig(config, buildFileConfig); + } + + //Re-apply the override config values. Command line + //args should take precedence over build file values. + mixConfig(config, cfg); + + //Fix paths to full paths so that they can be adjusted consistently + //lately to be in the output area. + lang.eachProp(config.paths, function (value, prop) { + if (lang.isArray(value)) { + throw new Error('paths fallback not supported in optimizer. ' + + 'Please provide a build config path override ' + + 'for ' + prop); + } + config.paths[prop] = build.makeAbsPath(value, config.baseUrl); + }); + + //Set final output dir + if (hasProp(config, "baseUrl")) { + if (config.appDir) { + config.dirBaseUrl = build.makeAbsPath(config.originalBaseUrl, config.dir); + } else { + config.dirBaseUrl = config.dir || config.baseUrl; + } + //Make sure dirBaseUrl ends in a slash, since it is + //concatenated with other strings. + config.dirBaseUrl = endsWithSlash(config.dirBaseUrl); + } + + //Check for errors in config + if (config.main) { + throw new Error('"main" passed as an option, but the ' + + 'supported option is called "name".'); + } + if (config.out && !config.name && !config.modules && !config.include && + !config.cssIn) { + throw new Error('Missing either a "name", "include" or "modules" ' + + 'option'); + } + if (config.cssIn) { + if (config.dir || config.appDir) { + throw new Error('cssIn is only for the output of single file ' + + 'CSS optimizations and is not compatible with "dir" or "appDir" configuration.'); + } + if (!config.out) { + throw new Error('"out" option missing.'); + } + } + if (!config.cssIn && !config.baseUrl) { + //Just use the current directory as the baseUrl + config.baseUrl = './'; + } + if (!config.out && !config.dir) { + throw new Error('Missing either an "out" or "dir" config value. ' + + 'If using "appDir" for a full project optimization, ' + + 'use "dir". If you want to optimize to one file, ' + + 'use "out".'); + } + if (config.appDir && config.out) { + throw new Error('"appDir" is not compatible with "out". Use "dir" ' + + 'instead. appDir is used to copy whole projects, ' + + 'where "out" with "baseUrl" is used to just ' + + 'optimize to one file.'); + } + if (config.out && config.dir) { + throw new Error('The "out" and "dir" options are incompatible.' + + ' Use "out" if you are targeting a single file for' + + ' for optimization, and "dir" if you want the appDir' + + ' or baseUrl directories optimized.'); + } + + if (config.dir) { + // Make sure the output dir is not set to a parent of the + // source dir or the same dir, as it will result in source + // code deletion. + if (config.dir === config.baseUrl || + config.dir === config.appDir || + (config.baseUrl && build.makeRelativeFilePath(config.dir, + config.baseUrl).indexOf('..') !== 0) || + (config.appDir && + build.makeRelativeFilePath(config.dir, config.appDir).indexOf('..') !== 0)) { + throw new Error('"dir" is set to a parent or same directory as' + + ' "appDir" or "baseUrl". This can result in' + + ' the deletion of source code. Stopping.'); + } + } + + if (config.insertRequire && !lang.isArray(config.insertRequire)) { + throw new Error('insertRequire should be a list of module IDs' + + ' to insert in to a require([]) call.'); + } + + if (config.generateSourceMaps) { + if (config.preserveLicenseComments && config.optimize !== 'none') { + throw new Error('Cannot use preserveLicenseComments and ' + + 'generateSourceMaps together. Either explcitly set ' + + 'preserveLicenseComments to false (default is true) or ' + + 'turn off generateSourceMaps. If you want source maps with ' + + 'license comments, see: ' + + 'http://requirejs.org/docs/errors.html#sourcemapcomments'); + } else if (config.optimize !== 'none' && + config.optimize !== 'closure' && + config.optimize !== 'uglify2') { + //Allow optimize: none to pass, since it is useful when toggling + //minification on and off to debug something, and it implicitly + //works, since it does not need a source map. + throw new Error('optimize: "' + config.optimize + + '" does not support generateSourceMaps.'); + } + } + + if ((config.name || config.include) && !config.modules) { + //Just need to build one file, but may be part of a whole appDir/ + //baseUrl copy, but specified on the command line, so cannot do + //the modules array setup. So create a modules section in that + //case. + config.modules = [ + { + name: config.name, + out: config.out, + create: config.create, + include: config.include, + exclude: config.exclude, + excludeShallow: config.excludeShallow, + insertRequire: config.insertRequire, + stubModules: config.stubModules + } + ]; + delete config.stubModules; + } else if (config.modules && config.out) { + throw new Error('If the "modules" option is used, then there ' + + 'should be a "dir" option set and "out" should ' + + 'not be used since "out" is only for single file ' + + 'optimization output.'); + } else if (config.modules && config.name) { + throw new Error('"name" and "modules" options are incompatible. ' + + 'Either use "name" if doing a single file ' + + 'optimization, or "modules" if you want to target ' + + 'more than one file for optimization.'); + } + + if (config.out && !config.cssIn) { + //Just one file to optimize. + + //Does not have a build file, so set up some defaults. + //Optimizing CSS should not be allowed, unless explicitly + //asked for on command line. In that case the only task is + //to optimize a CSS file. + if (!cfg.optimizeCss) { + config.optimizeCss = "none"; + } + } + + //Normalize cssPrefix + if (config.cssPrefix) { + //Make sure cssPrefix ends in a slash + config.cssPrefix = endsWithSlash(config.cssPrefix); + } else { + config.cssPrefix = ''; + } + + //Cycle through modules and combine any local stubModules with + //global values. + if (config.modules && config.modules.length) { + config.modules.forEach(function (mod) { + if (config.stubModules) { + mod.stubModules = config.stubModules.concat(mod.stubModules || []); + } + + //Create a hash lookup for the stubModules config to make lookup + //cheaper later. + if (mod.stubModules) { + mod.stubModules._byName = {}; + mod.stubModules.forEach(function (id) { + mod.stubModules._byName[id] = true; + }); + } + + //Allow wrap config in overrides, but normalize it. + if (mod.override) { + normalizeWrapConfig(mod.override, absFilePath); + } + }); + } + + normalizeWrapConfig(config, absFilePath); + + //Do final input verification + if (config.context) { + throw new Error('The build argument "context" is not supported' + + ' in a build. It should only be used in web' + + ' pages.'); + } + + //Set up normalizeDirDefines. If not explicitly set, if optimize "none", + //set to "skip" otherwise set to "all". + if (!hasProp(config, 'normalizeDirDefines')) { + if (config.optimize === 'none' || config.skipDirOptimize) { + config.normalizeDirDefines = 'skip'; + } else { + config.normalizeDirDefines = 'all'; + } + } + + //Set file.fileExclusionRegExp if desired + if (hasProp(config, 'fileExclusionRegExp')) { + if (typeof config.fileExclusionRegExp === "string") { + file.exclusionRegExp = new RegExp(config.fileExclusionRegExp); + } else { + file.exclusionRegExp = config.fileExclusionRegExp; + } + } else if (hasProp(config, 'dirExclusionRegExp')) { + //Set file.dirExclusionRegExp if desired, this is the old + //name for fileExclusionRegExp before 1.0.2. Support for backwards + //compatibility + file.exclusionRegExp = config.dirExclusionRegExp; + } + + //Remove things that may cause problems in the build. + delete config.jQuery; + delete config.enforceDefine; + delete config.urlArgs; + + return config; + }; + + /** + * finds the module being built/optimized with the given moduleName, + * or returns null. + * @param {String} moduleName + * @param {Array} modules + * @returns {Object} the module object from the build profile, or null. + */ + build.findBuildModule = function (moduleName, modules) { + var i, module; + for (i = 0; i < modules.length; i++) { + module = modules[i]; + if (module.name === moduleName) { + return module; + } + } + return null; + }; + + /** + * Removes a module name and path from a layer, if it is supposed to be + * excluded from the layer. + * @param {String} moduleName the name of the module + * @param {String} path the file path for the module + * @param {Object} layer the layer to remove the module/path from + */ + build.removeModulePath = function (module, path, layer) { + var index = layer.buildFilePaths.indexOf(path); + if (index !== -1) { + layer.buildFilePaths.splice(index, 1); + } + }; + + /** + * Uses the module build config object to trace the dependencies for the + * given module. + * + * @param {Object} module the module object from the build config info. + * @param {Object} config the build config object. + * @param {Object} [baseLoaderConfig] the base loader config to use for env resets. + * + * @returns {Object} layer information about what paths and modules should + * be in the flattened module. + */ + build.traceDependencies = function (module, config, baseLoaderConfig) { + var include, override, layer, context, oldContext, + rawTextByIds, + syncChecks = { + rhino: true, + node: true, + xpconnect: true + }, + deferred = prim(); + + //Reset some state set up in requirePatch.js, and clean up require's + //current context. + oldContext = require._buildReset(); + + //Grab the reset layer and context after the reset, but keep the + //old config to reuse in the new context. + layer = require._layer; + context = layer.context; + + //Put back basic config, use a fresh object for it. + if (baseLoaderConfig) { + require(lang.deeplikeCopy(baseLoaderConfig)); + } + + logger.trace("\nTracing dependencies for: " + (module.name || + (typeof module.out === 'function' ? 'FUNCTION' : module.out))); + include = module.name && !module.create ? [module.name] : []; + if (module.include) { + include = include.concat(module.include); + } + + //If there are overrides to basic config, set that up now.; + if (module.override) { + if (baseLoaderConfig) { + override = build.createOverrideConfig(baseLoaderConfig, module.override); + } else { + override = lang.deeplikeCopy(module.override); + } + require(override); + } + + //Now, populate the rawText cache with any values explicitly passed in + //via config. + rawTextByIds = require.s.contexts._.config.rawText; + if (rawTextByIds) { + lang.eachProp(rawTextByIds, function (contents, id) { + var url = require.toUrl(id) + '.js'; + require._cachedRawText[url] = contents; + }); + } + + + //Configure the callbacks to be called. + deferred.reject.__requireJsBuild = true; + + //Use a wrapping function so can check for errors. + function includeFinished(value) { + //If a sync build environment, check for errors here, instead of + //in the then callback below, since some errors, like two IDs pointed + //to same URL but only one anon ID will leave the loader in an + //unresolved state since a setTimeout cannot be used to check for + //timeout. + var hasError = false; + if (syncChecks[env.get()]) { + try { + build.checkForErrors(context); + } catch (e) { + hasError = true; + deferred.reject(e); + } + } + + if (!hasError) { + deferred.resolve(value); + } + } + includeFinished.__requireJsBuild = true; + + //Figure out module layer dependencies by calling require to do the work. + require(include, includeFinished, deferred.reject); + + // If a sync env, then with the "two IDs to same anon module path" + // issue, the require never completes, need to check for errors + // here. + if (syncChecks[env.get()]) { + build.checkForErrors(context); + } + + return deferred.promise.then(function () { + //Reset config + if (module.override && baseLoaderConfig) { + require(lang.deeplikeCopy(baseLoaderConfig)); + } + + build.checkForErrors(context); + + return layer; + }); + }; + + build.checkForErrors = function (context) { + //Check to see if it all loaded. If not, then throw, and give + //a message on what is left. + var id, prop, mod, idParts, pluginId, + errMessage = '', + failedPluginMap = {}, + failedPluginIds = [], + errIds = [], + errUrlMap = {}, + errUrlConflicts = {}, + hasErrUrl = false, + hasUndefined = false, + defined = context.defined, + registry = context.registry; + + function populateErrUrlMap(id, errUrl, skipNew) { + if (!skipNew) { + errIds.push(id); + } + + if (errUrlMap[errUrl]) { + hasErrUrl = true; + //This error module has the same URL as another + //error module, could be misconfiguration. + if (!errUrlConflicts[errUrl]) { + errUrlConflicts[errUrl] = []; + //Store the original module that had the same URL. + errUrlConflicts[errUrl].push(errUrlMap[errUrl]); + } + errUrlConflicts[errUrl].push(id); + } else if (!skipNew) { + errUrlMap[errUrl] = id; + } + } + + for (id in registry) { + if (hasProp(registry, id) && id.indexOf('_@r') !== 0) { + hasUndefined = true; + mod = getOwn(registry, id); + + if (id.indexOf('_unnormalized') === -1 && mod && mod.enabled) { + populateErrUrlMap(id, mod.map.url); + } + + //Look for plugins that did not call load() + idParts = id.split('!'); + pluginId = idParts[0]; + if (idParts.length > 1 && falseProp(failedPluginMap, pluginId)) { + failedPluginIds.push(pluginId); + failedPluginMap[pluginId] = true; + } + } + } + + // If have some modules that are not defined/stuck in the registry, + // then check defined modules for URL overlap. + if (hasUndefined) { + for (id in defined) { + if (hasProp(defined, id) && id.indexOf('!') === -1) { + populateErrUrlMap(id, require.toUrl(id) + '.js', true); + } + } + } + + if (errIds.length || failedPluginIds.length) { + if (failedPluginIds.length) { + errMessage += 'Loader plugin' + + (failedPluginIds.length === 1 ? '' : 's') + + ' did not call ' + + 'the load callback in the build: ' + + failedPluginIds.join(', ') + '\n'; + } + errMessage += 'Module loading did not complete for: ' + errIds.join(', '); + + if (hasErrUrl) { + errMessage += '\nThe following modules share the same URL. This ' + + 'could be a misconfiguration if that URL only has ' + + 'one anonymous module in it:'; + for (prop in errUrlConflicts) { + if (hasProp(errUrlConflicts, prop)) { + errMessage += '\n' + prop + ': ' + + errUrlConflicts[prop].join(', '); + } + } + } + throw new Error(errMessage); + } + }; + + build.createOverrideConfig = function (config, override) { + var cfg = lang.deeplikeCopy(config), + oride = lang.deeplikeCopy(override); + + lang.eachProp(oride, function (value, prop) { + if (hasProp(build.objProps, prop)) { + //An object property, merge keys. Start a new object + //so that source object in config does not get modified. + cfg[prop] = {}; + lang.mixin(cfg[prop], config[prop], true); + lang.mixin(cfg[prop], override[prop], true); + } else { + cfg[prop] = override[prop]; + } + }); + + return cfg; + }; + + /** + * Uses the module build config object to create an flattened version + * of the module, with deep dependencies included. + * + * @param {Object} module the module object from the build config info. + * + * @param {Object} layer the layer object returned from build.traceDependencies. + * + * @param {Object} the build config object. + * + * @returns {Object} with two properties: "text", the text of the flattened + * module, and "buildText", a string of text representing which files were + * included in the flattened module text. + */ + build.flattenModule = function (module, layer, config) { + var fileContents, sourceMapGenerator, + sourceMapBase, + buildFileContents = ''; + + return prim().start(function () { + var reqIndex, currContents, + moduleName, shim, packageConfig, nonPackageName, + parts, builder, writeApi, + namespace, namespaceWithDot, stubModulesByName, + context = layer.context, + onLayerEnds = [], + onLayerEndAdded = {}; + + //Use override settings, particularly for pragmas + //Do this before the var readings since it reads config values. + if (module.override) { + config = build.createOverrideConfig(config, module.override); + } + + namespace = config.namespace || ''; + namespaceWithDot = namespace ? namespace + '.' : ''; + stubModulesByName = (module.stubModules && module.stubModules._byName) || {}; + + //Start build output for the module. + module.onCompleteData = { + name: module.name, + path: (config.dir ? module._buildPath.replace(config.dir, "") : module._buildPath), + included: [] + }; + + buildFileContents += "\n" + + module.onCompleteData.path + + "\n----------------\n"; + + //If there was an existing file with require in it, hoist to the top. + if (layer.existingRequireUrl) { + reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl); + if (reqIndex !== -1) { + layer.buildFilePaths.splice(reqIndex, 1); + layer.buildFilePaths.unshift(layer.existingRequireUrl); + } + } + + if (config.generateSourceMaps) { + sourceMapBase = config.dir || config.baseUrl; + sourceMapGenerator = new SourceMapGenerator.SourceMapGenerator({ + file: module._buildPath.replace(sourceMapBase, '') + }); + } + + //Write the built module to disk, and build up the build output. + fileContents = ""; + return prim.serial(layer.buildFilePaths.map(function (path) { + return function () { + var lineCount, + singleContents = ''; + + moduleName = layer.buildFileToModule[path]; + //If the moduleName is for a package main, then update it to the + //real main value. + packageConfig = layer.context.config.pkgs && + getOwn(layer.context.config.pkgs, moduleName); + if (packageConfig) { + nonPackageName = moduleName; + moduleName += '/' + packageConfig.main; + } + + return prim().start(function () { + //Figure out if the module is a result of a build plugin, and if so, + //then delegate to that plugin. + parts = context.makeModuleMap(moduleName); + builder = parts.prefix && getOwn(context.defined, parts.prefix); + if (builder) { + if (builder.onLayerEnd && falseProp(onLayerEndAdded, parts.prefix)) { + onLayerEnds.push(builder); + onLayerEndAdded[parts.prefix] = true; + } + + if (builder.write) { + writeApi = function (input) { + singleContents += "\n" + addSemiColon(input, config); + if (config.onBuildWrite) { + singleContents = config.onBuildWrite(moduleName, path, singleContents); + } + }; + writeApi.asModule = function (moduleName, input) { + singleContents += "\n" + + addSemiColon(build.toTransport(namespace, moduleName, path, input, layer, { + useSourceUrl: layer.context.config.useSourceUrl + }), config); + if (config.onBuildWrite) { + singleContents = config.onBuildWrite(moduleName, path, singleContents); + } + }; + builder.write(parts.prefix, parts.name, writeApi); + } + return; + } else { + return prim().start(function () { + if (hasProp(stubModulesByName, moduleName)) { + //Just want to insert a simple module definition instead + //of the source module. Useful for plugins that inline + //all their resources. + if (hasProp(layer.context.plugins, moduleName)) { + //Slightly different content for plugins, to indicate + //that dynamic loading will not work. + return 'define({load: function(id){throw new Error("Dynamic load not allowed: " + id);}});'; + } else { + return 'define({});'; + } + } else { + return require._cacheReadAsync(path); + } + }).then(function (text) { + var hasPackageName; + + currContents = text; + + if (config.cjsTranslate && + (!config.shim || !lang.hasProp(config.shim, moduleName))) { + currContents = commonJs.convert(path, currContents); + } + + if (config.onBuildRead) { + currContents = config.onBuildRead(moduleName, path, currContents); + } + + if (packageConfig) { + hasPackageName = (nonPackageName === parse.getNamedDefine(currContents)); + } + + if (namespace) { + currContents = pragma.namespace(currContents, namespace); + } + + currContents = build.toTransport(namespace, moduleName, path, currContents, layer, { + useSourceUrl: config.useSourceUrl + }); + + if (packageConfig && !hasPackageName) { + currContents = addSemiColon(currContents, config) + '\n'; + currContents += namespaceWithDot + "define('" + + packageConfig.name + "', ['" + moduleName + + "'], function (main) { return main; });\n"; + } + + if (config.onBuildWrite) { + currContents = config.onBuildWrite(moduleName, path, currContents); + } + + //Semicolon is for files that are not well formed when + //concatenated with other content. + singleContents += "\n" + addSemiColon(currContents, config); + }); + } + }).then(function () { + var refPath, pluginId, resourcePath, + sourceMapPath, sourceMapLineNumber, + shortPath = path.replace(config.dir, ""); + + module.onCompleteData.included.push(shortPath); + buildFileContents += shortPath + "\n"; + + //Some files may not have declared a require module, and if so, + //put in a placeholder call so the require does not try to load them + //after the module is processed. + //If we have a name, but no defined module, then add in the placeholder. + if (moduleName && falseProp(layer.modulesWithNames, moduleName) && !config.skipModuleInsertion) { + shim = config.shim && (getOwn(config.shim, moduleName) || (packageConfig && getOwn(config.shim, nonPackageName))); + if (shim) { + singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", ' + + (shim.deps && shim.deps.length ? + build.makeJsArrayString(shim.deps) + ', ' : '') + + (shim.exportsFn ? shim.exportsFn() : 'function(){}') + + ');\n'; + } else { + singleContents += '\n' + namespaceWithDot + 'define("' + moduleName + '", function(){});\n'; + } + } + + //Add to the source map + if (sourceMapGenerator) { + refPath = config.out ? config.baseUrl : module._buildPath; + parts = path.split('!'); + if (parts.length === 1) { + //Not a plugin resource, fix the path + sourceMapPath = build.makeRelativeFilePath(refPath, path); + } else { + //Plugin resource. If it looks like just a plugin + //followed by a module ID, pull off the plugin + //and put it at the end of the name, otherwise + //just leave it alone. + pluginId = parts.shift(); + resourcePath = parts.join('!'); + if (resourceIsModuleIdRegExp.test(resourcePath)) { + sourceMapPath = build.makeRelativeFilePath(refPath, require.toUrl(resourcePath)) + + '!' + pluginId; + } else { + sourceMapPath = path; + } + } + + sourceMapLineNumber = fileContents.split('\n').length - 1; + lineCount = singleContents.split('\n').length; + for (var i = 1; i <= lineCount; i += 1) { + sourceMapGenerator.addMapping({ + generated: { + line: sourceMapLineNumber + i, + column: 0 + }, + original: { + line: i, + column: 0 + }, + source: sourceMapPath + }); + } + + //Store the content of the original in the source + //map since other transforms later like minification + //can mess up translating back to the original + //source. + sourceMapGenerator.setSourceContent(sourceMapPath, singleContents); + } + + //Add the file to the final contents + fileContents += singleContents; + }); + }; + })).then(function () { + if (onLayerEnds.length) { + onLayerEnds.forEach(function (builder) { + var path; + if (typeof module.out === 'string') { + path = module.out; + } else if (typeof module._buildPath === 'string') { + path = module._buildPath; + } + builder.onLayerEnd(function (input) { + fileContents += "\n" + addSemiColon(input, config); + }, { + name: module.name, + path: path + }); + }); + } + + if (module.create) { + //The ID is for a created layer. Write out + //a module definition for it in case the + //built file is used with enforceDefine + //(#432) + fileContents += '\n' + namespaceWithDot + 'define("' + module.name + '", function(){});\n'; + } + + //Add a require at the end to kick start module execution, if that + //was desired. Usually this is only specified when using small shim + //loaders like almond. + if (module.insertRequire) { + fileContents += '\n' + namespaceWithDot + 'require(["' + module.insertRequire.join('", "') + '"]);\n'; + } + }); + }).then(function () { + return { + text: config.wrap ? + config.wrap.start + fileContents + config.wrap.end : + fileContents, + buildText: buildFileContents, + sourceMap: sourceMapGenerator ? + JSON.stringify(sourceMapGenerator.toJSON(), null, ' ') : + undefined + }; + }); + }; + + //Converts an JS array of strings to a string representation. + //Not using JSON.stringify() for Rhino's sake. + build.makeJsArrayString = function (ary) { + return '["' + ary.map(function (item) { + //Escape any double quotes, backslashes + return lang.jsEscape(item); + }).join('","') + '"]'; + }; + + build.toTransport = function (namespace, moduleName, path, contents, layer, options) { + var baseUrl = layer && layer.context.config.baseUrl; + + function onFound(info) { + //Only mark this module as having a name if not a named module, + //or if a named module and the name matches expectations. + if (layer && (info.needsId || info.foundId === moduleName)) { + layer.modulesWithNames[moduleName] = true; + } + } + + //Convert path to be a local one to the baseUrl, useful for + //useSourceUrl. + if (baseUrl) { + path = path.replace(baseUrl, ''); + } + + return transform.toTransport(namespace, moduleName, path, contents, onFound, options); + }; + + return build; +}); + + } + + + /** + * Sets the default baseUrl for requirejs to be directory of top level + * script. + */ + function setBaseUrl(fileName) { + //Use the file name's directory as the baseUrl if available. + dir = fileName.replace(/\\/g, '/'); + if (dir.indexOf('/') !== -1) { + dir = dir.split('/'); + dir.pop(); + dir = dir.join('/'); + //Make sure dir is JS-escaped, since it will be part of a JS string. + exec("require({baseUrl: '" + dir.replace(/[\\"']/g, '\\$&') + "'});"); + } + } + + function createRjsApi() { + //Create a method that will run the optimzer given an object + //config. + requirejs.optimize = function (config, callback, errback) { + if (!loadedOptimizedLib) { + loadLib(); + loadedOptimizedLib = true; + } + + //Create the function that will be called once build modules + //have been loaded. + var runBuild = function (build, logger, quit) { + //Make sure config has a log level, and if not, + //make it "silent" by default. + config.logLevel = config.hasOwnProperty('logLevel') ? + config.logLevel : logger.SILENT; + + //Reset build internals first in case this is part + //of a long-running server process that could have + //exceptioned out in a bad state. It is only defined + //after the first call though. + if (requirejs._buildReset) { + requirejs._buildReset(); + requirejs._cacheReset(); + } + + function done(result) { + //And clean up, in case something else triggers + //a build in another pathway. + if (requirejs._buildReset) { + requirejs._buildReset(); + requirejs._cacheReset(); + } + + // Ensure errors get propagated to the errback + if (result instanceof Error) { + throw result; + } + + return result; + } + + errback = errback || function (err) { + // Using console here since logger may have + // turned off error logging. Since quit is + // called want to be sure a message is printed. + console.log(err); + quit(1); + }; + + build(config).then(done, done).then(callback, errback); + }; + + requirejs({ + context: 'build' + }, ['build', 'logger', 'env!env/quit'], runBuild); + }; + + requirejs.tools = { + useLib: function (contextName, callback) { + if (!callback) { + callback = contextName; + contextName = 'uselib'; + } + + if (!useLibLoaded[contextName]) { + loadLib(); + useLibLoaded[contextName] = true; + } + + var req = requirejs({ + context: contextName + }); + + req(['build'], function () { + callback(req); + }); + } + }; + + requirejs.define = define; + } + + //If in Node, and included via a require('requirejs'), just export and + //THROW IT ON THE GROUND! + if (env === 'node' && reqMain !== module) { + setBaseUrl(path.resolve(reqMain ? reqMain.filename : '.')); + + createRjsApi(); + + module.exports = requirejs; + return; + } else if (env === 'browser') { + //Only option is to use the API. + setBaseUrl(location.href); + createRjsApi(); + return; + } else if ((env === 'rhino' || env === 'xpconnect') && + //User sets up requirejsAsLib variable to indicate it is loaded + //via load() to be used as a library. + typeof requirejsAsLib !== 'undefined' && requirejsAsLib) { + //This script is loaded via rhino's load() method, expose the + //API and get out. + setBaseUrl(fileName); + createRjsApi(); + return; + } + + if (commandOption === 'o') { + //Do the optimizer work. + loadLib(); + + /** + * @license Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ + +/* + * Create a build.js file that has the build options you want and pass that + * build file to this file to do the build. See example.build.js for more information. + */ + +/*jslint strict: false, nomen: false */ +/*global require: false */ + +require({ + baseUrl: require.s.contexts._.config.baseUrl, + //Use a separate context than the default context so that the + //build can use the default context. + context: 'build', + catchError: { + define: true + } +}, ['env!env/args', 'env!env/quit', 'logger', 'build'], +function (args, quit, logger, build) { + build(args).then(function () {}, function (err) { + logger.error(err); + quit(1); + }); +}); + + + } else if (commandOption === 'v') { + console.log('r.js: ' + version + + ', RequireJS: ' + this.requirejsVars.require.version + + ', UglifyJS2: 2.4.0, UglifyJS: 1.3.4'); + } else if (commandOption === 'convert') { + loadLib(); + + this.requirejsVars.require(['env!env/args', 'commonJs', 'env!env/print'], + function (args, commonJs, print) { + + var srcDir, outDir; + srcDir = args[0]; + outDir = args[1]; + + if (!srcDir || !outDir) { + print('Usage: path/to/commonjs/modules output/dir'); + return; + } + + commonJs.convertDir(args[0], args[1]); + }); + } else { + //Just run an app + + //Load the bundled libraries for use in the app. + if (commandOption === 'lib') { + loadLib(); + } + + setBaseUrl(fileName); + + if (exists(fileName)) { + exec(readFile(fileName), fileName); + } else { + showHelp(); + } + } + +}((typeof console !== 'undefined' ? console : undefined), + (typeof Packages !== 'undefined' || (typeof window === 'undefined' && + typeof Components !== 'undefined' && Components.interfaces) ? + Array.prototype.slice.call(arguments, 0) : []), + (typeof readFile !== 'undefined' ? readFile : undefined))); diff --git a/node_modules/requirejs/package.json b/node_modules/requirejs/package.json new file mode 100644 index 00000000..932c4b0a --- /dev/null +++ b/node_modules/requirejs/package.json @@ -0,0 +1,39 @@ +{ + "name": "requirejs", + "description": "Node adapter for RequireJS, for loading AMD modules. Includes RequireJS optimizer", + "version": "2.1.9", + "homepage": "http://github.com/jrburke/r.js", + "author": { + "name": "James Burke", + "email": "jrburke@gmail.com", + "url": "http://github.com/jrburke" + }, + "licenses": [ + { + "type": "BSD", + "url": "https://github.com/jrburke/r.js/blob/master/LICENSE" + }, + { + "type": "MIT", + "url": "https://github.com/jrburke/r.js/blob/master/LICENSE" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/jrburke/r.js.git" + }, + "main": "./bin/r.js", + "bin": { + "r.js": "./bin/r.js" + }, + "engines": { + "node": ">=0.4.0" + }, + "readme": "# requirejs\n\nRequireJS for use in Node. includes:\n\n* r.js: the RequireJS optimizer, and AMD runtime for use in Node.\n* require.js: The browser-based AMD loader.\n\nMore information at http://requirejs.org\n\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/jrburke/r.js/issues" + }, + "_id": "requirejs@2.1.9", + "_from": "requirejs@~2.1" +} diff --git a/node_modules/requirejs/require.js b/node_modules/requirejs/require.js new file mode 100644 index 00000000..2ce09b5e --- /dev/null +++ b/node_modules/requirejs/require.js @@ -0,0 +1,2054 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license RequireJS 2.1.9 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ +//Not using strict: uneven strict support in browsers, #392, and causes +//problems with requirejs.exec()/transpiler plugins that may not be strict. +/*jslint regexp: true, nomen: true, sloppy: true */ +/*global window, navigator, document, importScripts, setTimeout, opera */ + +var requirejs, require, define; +(function (global) { + var req, s, head, baseElement, dataMain, src, + interactiveScript, currentlyAddingScript, mainScript, subPath, + version = '2.1.9', + commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, + cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, + jsSuffixRegExp = /\.js$/, + currDirRegExp = /^\.\//, + op = Object.prototype, + ostring = op.toString, + hasOwn = op.hasOwnProperty, + ap = Array.prototype, + apsp = ap.splice, + isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document), + isWebWorker = !isBrowser && typeof importScripts !== 'undefined', + //PS3 indicates loaded and complete, but need to wait for complete + //specifically. Sequence is 'loading', 'loaded', execution, + // then 'complete'. The UA check is unfortunate, but not sure how + //to feature test w/o causing perf issues. + readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? + /^complete$/ : /^(complete|loaded)$/, + defContextName = '_', + //Oh the tragedy, detecting opera. See the usage of isOpera for reason. + isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]', + contexts = {}, + cfg = {}, + globalDefQueue = [], + useInteractive = false; + + function isFunction(it) { + return ostring.call(it) === '[object Function]'; + } + + function isArray(it) { + return ostring.call(it) === '[object Array]'; + } + + /** + * Helper function for iterating over an array. If the func returns + * a true value, it will break out of the loop. + */ + function each(ary, func) { + if (ary) { + var i; + for (i = 0; i < ary.length; i += 1) { + if (ary[i] && func(ary[i], i, ary)) { + break; + } + } + } + } + + /** + * Helper function for iterating over an array backwards. If the func + * returns a true value, it will break out of the loop. + */ + function eachReverse(ary, func) { + if (ary) { + var i; + for (i = ary.length - 1; i > -1; i -= 1) { + if (ary[i] && func(ary[i], i, ary)) { + break; + } + } + } + } + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + function getOwn(obj, prop) { + return hasProp(obj, prop) && obj[prop]; + } + + /** + * Cycles over properties in an object and calls a function for each + * property value. If the function returns a truthy value, then the + * iteration is stopped. + */ + function eachProp(obj, func) { + var prop; + for (prop in obj) { + if (hasProp(obj, prop)) { + if (func(obj[prop], prop)) { + break; + } + } + } + } + + /** + * Simple function to mix in properties from source into target, + * but only if target does not already have a property of the same name. + */ + function mixin(target, source, force, deepStringMixin) { + if (source) { + eachProp(source, function (value, prop) { + if (force || !hasProp(target, prop)) { + if (deepStringMixin && typeof value !== 'string') { + if (!target[prop]) { + target[prop] = {}; + } + mixin(target[prop], value, force, deepStringMixin); + } else { + target[prop] = value; + } + } + }); + } + return target; + } + + //Similar to Function.prototype.bind, but the 'this' object is specified + //first, since it is easier to read/figure out what 'this' will be. + function bind(obj, fn) { + return function () { + return fn.apply(obj, arguments); + }; + } + + function scripts() { + return document.getElementsByTagName('script'); + } + + function defaultOnError(err) { + throw err; + } + + //Allow getting a global that expressed in + //dot notation, like 'a.b.c'. + function getGlobal(value) { + if (!value) { + return value; + } + var g = global; + each(value.split('.'), function (part) { + g = g[part]; + }); + return g; + } + + /** + * Constructs an error with a pointer to an URL with more information. + * @param {String} id the error ID that maps to an ID on a web page. + * @param {String} message human readable error. + * @param {Error} [err] the original error, if there is one. + * + * @returns {Error} + */ + function makeError(id, msg, err, requireModules) { + var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); + e.requireType = id; + e.requireModules = requireModules; + if (err) { + e.originalError = err; + } + return e; + } + + if (typeof define !== 'undefined') { + //If a define is already in play via another AMD loader, + //do not overwrite. + return; + } + + if (typeof requirejs !== 'undefined') { + if (isFunction(requirejs)) { + //Do not overwrite and existing requirejs instance. + return; + } + cfg = requirejs; + requirejs = undefined; + } + + //Allow for a require config object + if (typeof require !== 'undefined' && !isFunction(require)) { + //assume it is a config object. + cfg = require; + require = undefined; + } + + function newContext(contextName) { + var inCheckLoaded, Module, context, handlers, + checkLoadedTimeoutId, + config = { + //Defaults. Do not set a default for map + //config to speed up normalize(), which + //will run faster if there is no default. + waitSeconds: 7, + baseUrl: './', + paths: {}, + pkgs: {}, + shim: {}, + config: {} + }, + registry = {}, + //registry of just enabled modules, to speed + //cycle breaking code when lots of modules + //are registered, but not activated. + enabledRegistry = {}, + undefEvents = {}, + defQueue = [], + defined = {}, + urlFetched = {}, + requireCounter = 1, + unnormalizedCounter = 1; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i += 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @param {Boolean} applyMap apply the map config to the value. Should + * only be done if this normalization is for a dependency ID. + * @returns {String} normalized name + */ + function normalize(name, baseName, applyMap) { + var pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment, + foundMap, foundI, foundStarMap, starI, + baseParts = baseName && baseName.split('/'), + normalizedBaseParts = baseParts, + map = config.map, + starMap = map && map['*']; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + if (getOwn(config.pkgs, baseName)) { + //If the baseName is a package name, then just treat it as one + //name to concat the name with. + normalizedBaseParts = baseParts = [baseName]; + } else { + //Convert baseName to array, and lop off the last part, + //so that . matches that 'directory' and not name of the baseName's + //module. For instance, baseName of 'one/two/three', maps to + //'one/two/three.js', but we want the directory, 'one/two' for + //this normalization. + normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); + } + + name = normalizedBaseParts.concat(name.split('/')); + trimDots(name); + + //Some use of packages may use a . path to reference the + //'main' module name, so normalize for that. + pkgConfig = getOwn(config.pkgs, (pkgName = name[0])); + name = name.join('/'); + if (pkgConfig && name === pkgName + '/' + pkgConfig.main) { + name = pkgName; + } + } else if (name.indexOf('./') === 0) { + // No baseName, so this is ID is resolved relative + // to baseUrl, pull off the leading dot. + name = name.substring(2); + } + } + + //Apply map config if available. + if (applyMap && map && (baseParts || starMap)) { + nameParts = name.split('/'); + + for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join('/'); + + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = getOwn(map, baseParts.slice(0, j).join('/')); + + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = getOwn(mapValue, nameSegment); + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break; + } + } + } + } + + if (foundMap) { + break; + } + + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) { + foundStarMap = getOwn(starMap, nameSegment); + starI = i; + } + } + + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } + } + + return name; + } + + function removeScript(name) { + if (isBrowser) { + each(scripts(), function (scriptNode) { + if (scriptNode.getAttribute('data-requiremodule') === name && + scriptNode.getAttribute('data-requirecontext') === context.contextName) { + scriptNode.parentNode.removeChild(scriptNode); + return true; + } + }); + } + } + + function hasPathFallback(id) { + var pathConfig = getOwn(config.paths, id); + if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) { + //Pop off the first array value, since it failed, and + //retry + pathConfig.shift(); + context.require.undef(id); + context.require([id]); + return true; + } + } + + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; + } + + /** + * Creates a module mapping that includes plugin prefix, module + * name, and path. If parentModuleMap is provided it will + * also normalize the name via require.normalize() + * + * @param {String} name the module name + * @param {String} [parentModuleMap] parent module map + * for the module name, used to resolve relative names. + * @param {Boolean} isNormalized: is the ID already normalized. + * This is true if this call is done for a define() module ID. + * @param {Boolean} applyMap: apply the map config to the ID. + * Should only be true if this map is for a dependency. + * + * @returns {Object} + */ + function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { + var url, pluginModule, suffix, nameParts, + prefix = null, + parentName = parentModuleMap ? parentModuleMap.name : null, + originalName = name, + isDefine = true, + normalizedName = ''; + + //If no name, then it means it is a require call, generate an + //internal name. + if (!name) { + isDefine = false; + name = '_@r' + (requireCounter += 1); + } + + nameParts = splitPrefix(name); + prefix = nameParts[0]; + name = nameParts[1]; + + if (prefix) { + prefix = normalize(prefix, parentName, applyMap); + pluginModule = getOwn(defined, prefix); + } + + //Account for relative paths if there is a base name. + if (name) { + if (prefix) { + if (pluginModule && pluginModule.normalize) { + //Plugin is loaded, use its normalize method. + normalizedName = pluginModule.normalize(name, function (name) { + return normalize(name, parentName, applyMap); + }); + } else { + normalizedName = normalize(name, parentName, applyMap); + } + } else { + //A regular module. + normalizedName = normalize(name, parentName, applyMap); + + //Normalized name may be a plugin ID due to map config + //application in normalize. The map config values must + //already be normalized, so do not need to redo that part. + nameParts = splitPrefix(normalizedName); + prefix = nameParts[0]; + normalizedName = nameParts[1]; + isNormalized = true; + + url = context.nameToUrl(normalizedName); + } + } + + //If the id is a plugin id that cannot be determined if it needs + //normalization, stamp it with a unique ID so two matching relative + //ids that may conflict can be separate. + suffix = prefix && !pluginModule && !isNormalized ? + '_unnormalized' + (unnormalizedCounter += 1) : + ''; + + return { + prefix: prefix, + name: normalizedName, + parentMap: parentModuleMap, + unnormalized: !!suffix, + url: url, + originalName: originalName, + isDefine: isDefine, + id: (prefix ? + prefix + '!' + normalizedName : + normalizedName) + suffix + }; + } + + function getModule(depMap) { + var id = depMap.id, + mod = getOwn(registry, id); + + if (!mod) { + mod = registry[id] = new context.Module(depMap); + } + + return mod; + } + + function on(depMap, name, fn) { + var id = depMap.id, + mod = getOwn(registry, id); + + if (hasProp(defined, id) && + (!mod || mod.defineEmitComplete)) { + if (name === 'defined') { + fn(defined[id]); + } + } else { + mod = getModule(depMap); + if (mod.error && name === 'error') { + fn(mod.error); + } else { + mod.on(name, fn); + } + } + } + + function onError(err, errback) { + var ids = err.requireModules, + notified = false; + + if (errback) { + errback(err); + } else { + each(ids, function (id) { + var mod = getOwn(registry, id); + if (mod) { + //Set error on module, so it skips timeout checks. + mod.error = err; + if (mod.events.error) { + notified = true; + mod.emit('error', err); + } + } + }); + + if (!notified) { + req.onError(err); + } + } + } + + /** + * Internal method to transfer globalQueue items to this context's + * defQueue. + */ + function takeGlobalQueue() { + //Push all the globalDefQueue items into the context's defQueue + if (globalDefQueue.length) { + //Array splice in the values since the context code has a + //local var ref to defQueue, so cannot just reassign the one + //on context. + apsp.apply(defQueue, + [defQueue.length - 1, 0].concat(globalDefQueue)); + globalDefQueue = []; + } + } + + handlers = { + 'require': function (mod) { + if (mod.require) { + return mod.require; + } else { + return (mod.require = context.makeRequire(mod.map)); + } + }, + 'exports': function (mod) { + mod.usingExports = true; + if (mod.map.isDefine) { + if (mod.exports) { + return mod.exports; + } else { + return (mod.exports = defined[mod.map.id] = {}); + } + } + }, + 'module': function (mod) { + if (mod.module) { + return mod.module; + } else { + return (mod.module = { + id: mod.map.id, + uri: mod.map.url, + config: function () { + var c, + pkg = getOwn(config.pkgs, mod.map.id); + // For packages, only support config targeted + // at the main module. + c = pkg ? getOwn(config.config, mod.map.id + '/' + pkg.main) : + getOwn(config.config, mod.map.id); + return c || {}; + }, + exports: defined[mod.map.id] + }); + } + } + }; + + function cleanRegistry(id) { + //Clean up machinery used for waiting modules. + delete registry[id]; + delete enabledRegistry[id]; + } + + function breakCycle(mod, traced, processed) { + var id = mod.map.id; + + if (mod.error) { + mod.emit('error', mod.error); + } else { + traced[id] = true; + each(mod.depMaps, function (depMap, i) { + var depId = depMap.id, + dep = getOwn(registry, depId); + + //Only force things that have not completed + //being defined, so still in the registry, + //and only if it has not been matched up + //in the module already. + if (dep && !mod.depMatched[i] && !processed[depId]) { + if (getOwn(traced, depId)) { + mod.defineDep(i, defined[depId]); + mod.check(); //pass false? + } else { + breakCycle(dep, traced, processed); + } + } + }); + processed[id] = true; + } + } + + function checkLoaded() { + var map, modId, err, usingPathFallback, + waitInterval = config.waitSeconds * 1000, + //It is possible to disable the wait interval by using waitSeconds of 0. + expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), + noLoads = [], + reqCalls = [], + stillLoading = false, + needCycleCheck = true; + + //Do not bother if this call was a result of a cycle break. + if (inCheckLoaded) { + return; + } + + inCheckLoaded = true; + + //Figure out the state of all the modules. + eachProp(enabledRegistry, function (mod) { + map = mod.map; + modId = map.id; + + //Skip things that are not enabled or in error state. + if (!mod.enabled) { + return; + } + + if (!map.isDefine) { + reqCalls.push(mod); + } + + if (!mod.error) { + //If the module should be executed, and it has not + //been inited and time is up, remember it. + if (!mod.inited && expired) { + if (hasPathFallback(modId)) { + usingPathFallback = true; + stillLoading = true; + } else { + noLoads.push(modId); + removeScript(modId); + } + } else if (!mod.inited && mod.fetched && map.isDefine) { + stillLoading = true; + if (!map.prefix) { + //No reason to keep looking for unfinished + //loading. If the only stillLoading is a + //plugin resource though, keep going, + //because it may be that a plugin resource + //is waiting on a non-plugin cycle. + return (needCycleCheck = false); + } + } + } + }); + + if (expired && noLoads.length) { + //If wait time expired, throw error of unloaded modules. + err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads); + err.contextName = context.contextName; + return onError(err); + } + + //Not expired, check for a cycle. + if (needCycleCheck) { + each(reqCalls, function (mod) { + breakCycle(mod, {}, {}); + }); + } + + //If still waiting on loads, and the waiting load is something + //other than a plugin resource, or there are still outstanding + //scripts, then just try back later. + if ((!expired || usingPathFallback) && stillLoading) { + //Something is still waiting to load. Wait for it, but only + //if a timeout is not already in effect. + if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { + checkLoadedTimeoutId = setTimeout(function () { + checkLoadedTimeoutId = 0; + checkLoaded(); + }, 50); + } + } + + inCheckLoaded = false; + } + + Module = function (map) { + this.events = getOwn(undefEvents, map.id) || {}; + this.map = map; + this.shim = getOwn(config.shim, map.id); + this.depExports = []; + this.depMaps = []; + this.depMatched = []; + this.pluginMaps = {}; + this.depCount = 0; + + /* this.exports this.factory + this.depMaps = [], + this.enabled, this.fetched + */ + }; + + Module.prototype = { + init: function (depMaps, factory, errback, options) { + options = options || {}; + + //Do not do more inits if already done. Can happen if there + //are multiple define calls for the same module. That is not + //a normal, common case, but it is also not unexpected. + if (this.inited) { + return; + } + + this.factory = factory; + + if (errback) { + //Register for errors on this module. + this.on('error', errback); + } else if (this.events.error) { + //If no errback already, but there are error listeners + //on this module, set up an errback to pass to the deps. + errback = bind(this, function (err) { + this.emit('error', err); + }); + } + + //Do a copy of the dependency array, so that + //source inputs are not modified. For example + //"shim" deps are passed in here directly, and + //doing a direct modification of the depMaps array + //would affect that config. + this.depMaps = depMaps && depMaps.slice(0); + + this.errback = errback; + + //Indicate this module has be initialized + this.inited = true; + + this.ignore = options.ignore; + + //Could have option to init this module in enabled mode, + //or could have been previously marked as enabled. However, + //the dependencies are not known until init is called. So + //if enabled previously, now trigger dependencies as enabled. + if (options.enabled || this.enabled) { + //Enable this module and dependencies. + //Will call this.check() + this.enable(); + } else { + this.check(); + } + }, + + defineDep: function (i, depExports) { + //Because of cycles, defined callback for a given + //export can be called more than once. + if (!this.depMatched[i]) { + this.depMatched[i] = true; + this.depCount -= 1; + this.depExports[i] = depExports; + } + }, + + fetch: function () { + if (this.fetched) { + return; + } + this.fetched = true; + + context.startTime = (new Date()).getTime(); + + var map = this.map; + + //If the manager is for a plugin managed resource, + //ask the plugin to load it now. + if (this.shim) { + context.makeRequire(this.map, { + enableBuildCallback: true + })(this.shim.deps || [], bind(this, function () { + return map.prefix ? this.callPlugin() : this.load(); + })); + } else { + //Regular dependency. + return map.prefix ? this.callPlugin() : this.load(); + } + }, + + load: function () { + var url = this.map.url; + + //Regular dependency. + if (!urlFetched[url]) { + urlFetched[url] = true; + context.load(this.map.id, url); + } + }, + + /** + * Checks if the module is ready to define itself, and if so, + * define it. + */ + check: function () { + if (!this.enabled || this.enabling) { + return; + } + + var err, cjsModule, + id = this.map.id, + depExports = this.depExports, + exports = this.exports, + factory = this.factory; + + if (!this.inited) { + this.fetch(); + } else if (this.error) { + this.emit('error', this.error); + } else if (!this.defining) { + //The factory could trigger another require call + //that would result in checking this module to + //define itself again. If already in the process + //of doing that, skip this work. + this.defining = true; + + if (this.depCount < 1 && !this.defined) { + if (isFunction(factory)) { + //If there is an error listener, favor passing + //to that instead of throwing an error. However, + //only do it for define()'d modules. require + //errbacks should not be called for failures in + //their callbacks (#699). However if a global + //onError is set, use that. + if ((this.events.error && this.map.isDefine) || + req.onError !== defaultOnError) { + try { + exports = context.execCb(id, factory, depExports, exports); + } catch (e) { + err = e; + } + } else { + exports = context.execCb(id, factory, depExports, exports); + } + + if (this.map.isDefine) { + //If setting exports via 'module' is in play, + //favor that over return value and exports. After that, + //favor a non-undefined return value over exports use. + cjsModule = this.module; + if (cjsModule && + cjsModule.exports !== undefined && + //Make sure it is not already the exports value + cjsModule.exports !== this.exports) { + exports = cjsModule.exports; + } else if (exports === undefined && this.usingExports) { + //exports already set the defined value. + exports = this.exports; + } + } + + if (err) { + err.requireMap = this.map; + err.requireModules = this.map.isDefine ? [this.map.id] : null; + err.requireType = this.map.isDefine ? 'define' : 'require'; + return onError((this.error = err)); + } + + } else { + //Just a literal value + exports = factory; + } + + this.exports = exports; + + if (this.map.isDefine && !this.ignore) { + defined[id] = exports; + + if (req.onResourceLoad) { + req.onResourceLoad(context, this.map, this.depMaps); + } + } + + //Clean up + cleanRegistry(id); + + this.defined = true; + } + + //Finished the define stage. Allow calling check again + //to allow define notifications below in the case of a + //cycle. + this.defining = false; + + if (this.defined && !this.defineEmitted) { + this.defineEmitted = true; + this.emit('defined', this.exports); + this.defineEmitComplete = true; + } + + } + }, + + callPlugin: function () { + var map = this.map, + id = map.id, + //Map already normalized the prefix. + pluginMap = makeModuleMap(map.prefix); + + //Mark this as a dependency for this plugin, so it + //can be traced for cycles. + this.depMaps.push(pluginMap); + + on(pluginMap, 'defined', bind(this, function (plugin) { + var load, normalizedMap, normalizedMod, + name = this.map.name, + parentName = this.map.parentMap ? this.map.parentMap.name : null, + localRequire = context.makeRequire(map.parentMap, { + enableBuildCallback: true + }); + + //If current map is not normalized, wait for that + //normalized name to load instead of continuing. + if (this.map.unnormalized) { + //Normalize the ID if the plugin allows it. + if (plugin.normalize) { + name = plugin.normalize(name, function (name) { + return normalize(name, parentName, true); + }) || ''; + } + + //prefix and name should already be normalized, no need + //for applying map config again either. + normalizedMap = makeModuleMap(map.prefix + '!' + name, + this.map.parentMap); + on(normalizedMap, + 'defined', bind(this, function (value) { + this.init([], function () { return value; }, null, { + enabled: true, + ignore: true + }); + })); + + normalizedMod = getOwn(registry, normalizedMap.id); + if (normalizedMod) { + //Mark this as a dependency for this plugin, so it + //can be traced for cycles. + this.depMaps.push(normalizedMap); + + if (this.events.error) { + normalizedMod.on('error', bind(this, function (err) { + this.emit('error', err); + })); + } + normalizedMod.enable(); + } + + return; + } + + load = bind(this, function (value) { + this.init([], function () { return value; }, null, { + enabled: true + }); + }); + + load.error = bind(this, function (err) { + this.inited = true; + this.error = err; + err.requireModules = [id]; + + //Remove temp unnormalized modules for this module, + //since they will never be resolved otherwise now. + eachProp(registry, function (mod) { + if (mod.map.id.indexOf(id + '_unnormalized') === 0) { + cleanRegistry(mod.map.id); + } + }); + + onError(err); + }); + + //Allow plugins to load other code without having to know the + //context or how to 'complete' the load. + load.fromText = bind(this, function (text, textAlt) { + /*jslint evil: true */ + var moduleName = map.name, + moduleMap = makeModuleMap(moduleName), + hasInteractive = useInteractive; + + //As of 2.1.0, support just passing the text, to reinforce + //fromText only being called once per resource. Still + //support old style of passing moduleName but discard + //that moduleName in favor of the internal ref. + if (textAlt) { + text = textAlt; + } + + //Turn off interactive script matching for IE for any define + //calls in the text, then turn it back on at the end. + if (hasInteractive) { + useInteractive = false; + } + + //Prime the system by creating a module instance for + //it. + getModule(moduleMap); + + //Transfer any config to this other module. + if (hasProp(config.config, id)) { + config.config[moduleName] = config.config[id]; + } + + try { + req.exec(text); + } catch (e) { + return onError(makeError('fromtexteval', + 'fromText eval for ' + id + + ' failed: ' + e, + e, + [id])); + } + + if (hasInteractive) { + useInteractive = true; + } + + //Mark this as a dependency for the plugin + //resource + this.depMaps.push(moduleMap); + + //Support anonymous modules. + context.completeLoad(moduleName); + + //Bind the value of that module to the value for this + //resource ID. + localRequire([moduleName], load); + }); + + //Use parentName here since the plugin's name is not reliable, + //could be some weird string with no path that actually wants to + //reference the parentName's path. + plugin.load(map.name, localRequire, load, config); + })); + + context.enable(pluginMap, this); + this.pluginMaps[pluginMap.id] = pluginMap; + }, + + enable: function () { + enabledRegistry[this.map.id] = this; + this.enabled = true; + + //Set flag mentioning that the module is enabling, + //so that immediate calls to the defined callbacks + //for dependencies do not trigger inadvertent load + //with the depCount still being zero. + this.enabling = true; + + //Enable each dependency + each(this.depMaps, bind(this, function (depMap, i) { + var id, mod, handler; + + if (typeof depMap === 'string') { + //Dependency needs to be converted to a depMap + //and wired up to this module. + depMap = makeModuleMap(depMap, + (this.map.isDefine ? this.map : this.map.parentMap), + false, + !this.skipMap); + this.depMaps[i] = depMap; + + handler = getOwn(handlers, depMap.id); + + if (handler) { + this.depExports[i] = handler(this); + return; + } + + this.depCount += 1; + + on(depMap, 'defined', bind(this, function (depExports) { + this.defineDep(i, depExports); + this.check(); + })); + + if (this.errback) { + on(depMap, 'error', bind(this, this.errback)); + } + } + + id = depMap.id; + mod = registry[id]; + + //Skip special modules like 'require', 'exports', 'module' + //Also, don't call enable if it is already enabled, + //important in circular dependency cases. + if (!hasProp(handlers, id) && mod && !mod.enabled) { + context.enable(depMap, this); + } + })); + + //Enable each plugin that is used in + //a dependency + eachProp(this.pluginMaps, bind(this, function (pluginMap) { + var mod = getOwn(registry, pluginMap.id); + if (mod && !mod.enabled) { + context.enable(pluginMap, this); + } + })); + + this.enabling = false; + + this.check(); + }, + + on: function (name, cb) { + var cbs = this.events[name]; + if (!cbs) { + cbs = this.events[name] = []; + } + cbs.push(cb); + }, + + emit: function (name, evt) { + each(this.events[name], function (cb) { + cb(evt); + }); + if (name === 'error') { + //Now that the error handler was triggered, remove + //the listeners, since this broken Module instance + //can stay around for a while in the registry. + delete this.events[name]; + } + } + }; + + function callGetModule(args) { + //Skip modules already defined. + if (!hasProp(defined, args[0])) { + getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]); + } + } + + function removeListener(node, func, name, ieName) { + //Favor detachEvent because of IE9 + //issue, see attachEvent/addEventListener comment elsewhere + //in this file. + if (node.detachEvent && !isOpera) { + //Probably IE. If not it will throw an error, which will be + //useful to know. + if (ieName) { + node.detachEvent(ieName, func); + } + } else { + node.removeEventListener(name, func, false); + } + } + + /** + * Given an event from a script node, get the requirejs info from it, + * and then removes the event listeners on the node. + * @param {Event} evt + * @returns {Object} + */ + function getScriptData(evt) { + //Using currentTarget instead of target for Firefox 2.0's sake. Not + //all old browsers will be supported, but this one was easy enough + //to support and still makes sense. + var node = evt.currentTarget || evt.srcElement; + + //Remove the listeners once here. + removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange'); + removeListener(node, context.onScriptError, 'error'); + + return { + node: node, + id: node && node.getAttribute('data-requiremodule') + }; + } + + function intakeDefines() { + var args; + + //Any defined modules in the global queue, intake them now. + takeGlobalQueue(); + + //Make sure any remaining defQueue items get properly processed. + while (defQueue.length) { + args = defQueue.shift(); + if (args[0] === null) { + return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1])); + } else { + //args are id, deps, factory. Should be normalized by the + //define() function. + callGetModule(args); + } + } + } + + context = { + config: config, + contextName: contextName, + registry: registry, + defined: defined, + urlFetched: urlFetched, + defQueue: defQueue, + Module: Module, + makeModuleMap: makeModuleMap, + nextTick: req.nextTick, + onError: onError, + + /** + * Set a configuration for the context. + * @param {Object} cfg config object to integrate. + */ + configure: function (cfg) { + //Make sure the baseUrl ends in a slash. + if (cfg.baseUrl) { + if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') { + cfg.baseUrl += '/'; + } + } + + //Save off the paths and packages since they require special processing, + //they are additive. + var pkgs = config.pkgs, + shim = config.shim, + objs = { + paths: true, + config: true, + map: true + }; + + eachProp(cfg, function (value, prop) { + if (objs[prop]) { + if (prop === 'map') { + if (!config.map) { + config.map = {}; + } + mixin(config[prop], value, true, true); + } else { + mixin(config[prop], value, true); + } + } else { + config[prop] = value; + } + }); + + //Merge shim + if (cfg.shim) { + eachProp(cfg.shim, function (value, id) { + //Normalize the structure + if (isArray(value)) { + value = { + deps: value + }; + } + if ((value.exports || value.init) && !value.exportsFn) { + value.exportsFn = context.makeShimExports(value); + } + shim[id] = value; + }); + config.shim = shim; + } + + //Adjust packages if necessary. + if (cfg.packages) { + each(cfg.packages, function (pkgObj) { + var location; + + pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj; + location = pkgObj.location; + + //Create a brand new object on pkgs, since currentPackages can + //be passed in again, and config.pkgs is the internal transformed + //state for all package configs. + pkgs[pkgObj.name] = { + name: pkgObj.name, + location: location || pkgObj.name, + //Remove leading dot in main, so main paths are normalized, + //and remove any trailing .js, since different package + //envs have different conventions: some use a module name, + //some use a file name. + main: (pkgObj.main || 'main') + .replace(currDirRegExp, '') + .replace(jsSuffixRegExp, '') + }; + }); + + //Done with modifications, assing packages back to context config + config.pkgs = pkgs; + } + + //If there are any "waiting to execute" modules in the registry, + //update the maps for them, since their info, like URLs to load, + //may have changed. + eachProp(registry, function (mod, id) { + //If module already has init called, since it is too + //late to modify them, and ignore unnormalized ones + //since they are transient. + if (!mod.inited && !mod.map.unnormalized) { + mod.map = makeModuleMap(id); + } + }); + + //If a deps array or a config callback is specified, then call + //require with those args. This is useful when require is defined as a + //config object before require.js is loaded. + if (cfg.deps || cfg.callback) { + context.require(cfg.deps || [], cfg.callback); + } + }, + + makeShimExports: function (value) { + function fn() { + var ret; + if (value.init) { + ret = value.init.apply(global, arguments); + } + return ret || (value.exports && getGlobal(value.exports)); + } + return fn; + }, + + makeRequire: function (relMap, options) { + options = options || {}; + + function localRequire(deps, callback, errback) { + var id, map, requireMod; + + if (options.enableBuildCallback && callback && isFunction(callback)) { + callback.__requireJsBuild = true; + } + + if (typeof deps === 'string') { + if (isFunction(callback)) { + //Invalid call + return onError(makeError('requireargs', 'Invalid require call'), errback); + } + + //If require|exports|module are requested, get the + //value for them from the special handlers. Caveat: + //this only works while module is being defined. + if (relMap && hasProp(handlers, deps)) { + return handlers[deps](registry[relMap.id]); + } + + //Synchronous access to one module. If require.get is + //available (as in the Node adapter), prefer that. + if (req.get) { + return req.get(context, deps, relMap, localRequire); + } + + //Normalize module name, if it contains . or .. + map = makeModuleMap(deps, relMap, false, true); + id = map.id; + + if (!hasProp(defined, id)) { + return onError(makeError('notloaded', 'Module name "' + + id + + '" has not been loaded yet for context: ' + + contextName + + (relMap ? '' : '. Use require([])'))); + } + return defined[id]; + } + + //Grab defines waiting in the global queue. + intakeDefines(); + + //Mark all the dependencies as needing to be loaded. + context.nextTick(function () { + //Some defines could have been added since the + //require call, collect them. + intakeDefines(); + + requireMod = getModule(makeModuleMap(null, relMap)); + + //Store if map config should be applied to this require + //call for dependencies. + requireMod.skipMap = options.skipMap; + + requireMod.init(deps, callback, errback, { + enabled: true + }); + + checkLoaded(); + }); + + return localRequire; + } + + mixin(localRequire, { + isBrowser: isBrowser, + + /** + * Converts a module name + .extension into an URL path. + * *Requires* the use of a module name. It does not support using + * plain URLs like nameToUrl. + */ + toUrl: function (moduleNamePlusExt) { + var ext, + index = moduleNamePlusExt.lastIndexOf('.'), + segment = moduleNamePlusExt.split('/')[0], + isRelative = segment === '.' || segment === '..'; + + //Have a file extension alias, and it is not the + //dots from a relative path. + if (index !== -1 && (!isRelative || index > 1)) { + ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); + moduleNamePlusExt = moduleNamePlusExt.substring(0, index); + } + + return context.nameToUrl(normalize(moduleNamePlusExt, + relMap && relMap.id, true), ext, true); + }, + + defined: function (id) { + return hasProp(defined, makeModuleMap(id, relMap, false, true).id); + }, + + specified: function (id) { + id = makeModuleMap(id, relMap, false, true).id; + return hasProp(defined, id) || hasProp(registry, id); + } + }); + + //Only allow undef on top level require calls + if (!relMap) { + localRequire.undef = function (id) { + //Bind any waiting define() calls to this context, + //fix for #408 + takeGlobalQueue(); + + var map = makeModuleMap(id, relMap, true), + mod = getOwn(registry, id); + + removeScript(id); + + delete defined[id]; + delete urlFetched[map.url]; + delete undefEvents[id]; + + if (mod) { + //Hold on to listeners in case the + //module will be attempted to be reloaded + //using a different config. + if (mod.events.defined) { + undefEvents[id] = mod.events; + } + + cleanRegistry(id); + } + }; + } + + return localRequire; + }, + + /** + * Called to enable a module if it is still in the registry + * awaiting enablement. A second arg, parent, the parent module, + * is passed in for context, when this method is overriden by + * the optimizer. Not shown here to keep code compact. + */ + enable: function (depMap) { + var mod = getOwn(registry, depMap.id); + if (mod) { + getModule(depMap).enable(); + } + }, + + /** + * Internal method used by environment adapters to complete a load event. + * A load event could be a script load or just a load pass from a synchronous + * load call. + * @param {String} moduleName the name of the module to potentially complete. + */ + completeLoad: function (moduleName) { + var found, args, mod, + shim = getOwn(config.shim, moduleName) || {}, + shExports = shim.exports; + + takeGlobalQueue(); + + while (defQueue.length) { + args = defQueue.shift(); + if (args[0] === null) { + args[0] = moduleName; + //If already found an anonymous module and bound it + //to this name, then this is some other anon module + //waiting for its completeLoad to fire. + if (found) { + break; + } + found = true; + } else if (args[0] === moduleName) { + //Found matching define call for this script! + found = true; + } + + callGetModule(args); + } + + //Do this after the cycle of callGetModule in case the result + //of those calls/init calls changes the registry. + mod = getOwn(registry, moduleName); + + if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) { + if (config.enforceDefine && (!shExports || !getGlobal(shExports))) { + if (hasPathFallback(moduleName)) { + return; + } else { + return onError(makeError('nodefine', + 'No define call for ' + moduleName, + null, + [moduleName])); + } + } else { + //A script that does not call define(), so just simulate + //the call for it. + callGetModule([moduleName, (shim.deps || []), shim.exportsFn]); + } + } + + checkLoaded(); + }, + + /** + * Converts a module name to a file path. Supports cases where + * moduleName may actually be just an URL. + * Note that it **does not** call normalize on the moduleName, + * it is assumed to have already been normalized. This is an + * internal API, not a public one. Use toUrl for the public API. + */ + nameToUrl: function (moduleName, ext, skipExt) { + var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url, + parentPath; + + //If a colon is in the URL, it indicates a protocol is used and it is just + //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?) + //or ends with .js, then assume the user meant to use an url and not a module id. + //The slash is important for protocol-less URLs as well as full paths. + if (req.jsExtRegExp.test(moduleName)) { + //Just a plain path, not module name lookup, so just return it. + //Add extension if it is included. This is a bit wonky, only non-.js things pass + //an extension, this method probably needs to be reworked. + url = moduleName + (ext || ''); + } else { + //A module that needs to be converted to a path. + paths = config.paths; + pkgs = config.pkgs; + + syms = moduleName.split('/'); + //For each module name segment, see if there is a path + //registered for it. Start with most specific name + //and work up from it. + for (i = syms.length; i > 0; i -= 1) { + parentModule = syms.slice(0, i).join('/'); + pkg = getOwn(pkgs, parentModule); + parentPath = getOwn(paths, parentModule); + if (parentPath) { + //If an array, it means there are a few choices, + //Choose the one that is desired + if (isArray(parentPath)) { + parentPath = parentPath[0]; + } + syms.splice(0, i, parentPath); + break; + } else if (pkg) { + //If module name is just the package name, then looking + //for the main module. + if (moduleName === pkg.name) { + pkgPath = pkg.location + '/' + pkg.main; + } else { + pkgPath = pkg.location; + } + syms.splice(0, i, pkgPath); + break; + } + } + + //Join the path parts together, then figure out if baseUrl is needed. + url = syms.join('/'); + url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js')); + url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; + } + + return config.urlArgs ? url + + ((url.indexOf('?') === -1 ? '?' : '&') + + config.urlArgs) : url; + }, + + //Delegates to req.load. Broken out as a separate function to + //allow overriding in the optimizer. + load: function (id, url) { + req.load(context, id, url); + }, + + /** + * Executes a module callback function. Broken out as a separate function + * solely to allow the build system to sequence the files in the built + * layer in the right sequence. + * + * @private + */ + execCb: function (name, callback, args, exports) { + return callback.apply(exports, args); + }, + + /** + * callback for script loads, used to check status of loading. + * + * @param {Event} evt the event from the browser for the script + * that was loaded. + */ + onScriptLoad: function (evt) { + //Using currentTarget instead of target for Firefox 2.0's sake. Not + //all old browsers will be supported, but this one was easy enough + //to support and still makes sense. + if (evt.type === 'load' || + (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) { + //Reset interactive script so a script node is not held onto for + //to long. + interactiveScript = null; + + //Pull out the name of the module and the context. + var data = getScriptData(evt); + context.completeLoad(data.id); + } + }, + + /** + * Callback for script errors. + */ + onScriptError: function (evt) { + var data = getScriptData(evt); + if (!hasPathFallback(data.id)) { + return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id])); + } + } + }; + + context.require = context.makeRequire(); + return context; + } + + /** + * Main entry point. + * + * If the only argument to require is a string, then the module that + * is represented by that string is fetched for the appropriate context. + * + * If the first argument is an array, then it will be treated as an array + * of dependency string names to fetch. An optional function callback can + * be specified to execute when all of those dependencies are available. + * + * Make a local req variable to help Caja compliance (it assumes things + * on a require that are not standardized), and to give a short + * name for minification/local scope use. + */ + req = requirejs = function (deps, callback, errback, optional) { + + //Find the right context, use default + var context, config, + contextName = defContextName; + + // Determine if have config object in the call. + if (!isArray(deps) && typeof deps !== 'string') { + // deps is a config object + config = deps; + if (isArray(callback)) { + // Adjust args if there are dependencies + deps = callback; + callback = errback; + errback = optional; + } else { + deps = []; + } + } + + if (config && config.context) { + contextName = config.context; + } + + context = getOwn(contexts, contextName); + if (!context) { + context = contexts[contextName] = req.s.newContext(contextName); + } + + if (config) { + context.configure(config); + } + + return context.require(deps, callback, errback); + }; + + /** + * Support require.config() to make it easier to cooperate with other + * AMD loaders on globally agreed names. + */ + req.config = function (config) { + return req(config); + }; + + /** + * Execute something after the current tick + * of the event loop. Override for other envs + * that have a better solution than setTimeout. + * @param {Function} fn function to execute later. + */ + req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) { + setTimeout(fn, 4); + } : function (fn) { fn(); }; + + /** + * Export require as a global, but only if it does not already exist. + */ + if (!require) { + require = req; + } + + req.version = version; + + //Used to filter out dependencies that are already paths. + req.jsExtRegExp = /^\/|:|\?|\.js$/; + req.isBrowser = isBrowser; + s = req.s = { + contexts: contexts, + newContext: newContext + }; + + //Create default context. + req({}); + + //Exports some context-sensitive methods on global require. + each([ + 'toUrl', + 'undef', + 'defined', + 'specified' + ], function (prop) { + //Reference from contexts instead of early binding to default context, + //so that during builds, the latest instance of the default context + //with its config gets used. + req[prop] = function () { + var ctx = contexts[defContextName]; + return ctx.require[prop].apply(ctx, arguments); + }; + }); + + if (isBrowser) { + head = s.head = document.getElementsByTagName('head')[0]; + //If BASE tag is in play, using appendChild is a problem for IE6. + //When that browser dies, this can be removed. Details in this jQuery bug: + //http://dev.jquery.com/ticket/2709 + baseElement = document.getElementsByTagName('base')[0]; + if (baseElement) { + head = s.head = baseElement.parentNode; + } + } + + /** + * Any errors that require explicitly generates will be passed to this + * function. Intercept/override it if you want custom error handling. + * @param {Error} err the error object. + */ + req.onError = defaultOnError; + + /** + * Creates the node for the load command. Only used in browser envs. + */ + req.createNode = function (config, moduleName, url) { + var node = config.xhtml ? + document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') : + document.createElement('script'); + node.type = config.scriptType || 'text/javascript'; + node.charset = 'utf-8'; + node.async = true; + return node; + }; + + /** + * Does the request to load a module for the browser case. + * Make this a separate function to allow other environments + * to override it. + * + * @param {Object} context the require context to find state. + * @param {String} moduleName the name of the module. + * @param {Object} url the URL to the module. + */ + req.load = function (context, moduleName, url) { + var config = (context && context.config) || {}, + node; + if (isBrowser) { + //In the browser so use a script tag + node = req.createNode(config, moduleName, url); + + node.setAttribute('data-requirecontext', context.contextName); + node.setAttribute('data-requiremodule', moduleName); + + //Set up load listener. Test attachEvent first because IE9 has + //a subtle issue in its addEventListener and script onload firings + //that do not match the behavior of all other browsers with + //addEventListener support, which fire the onload event for a + //script right after the script execution. See: + //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution + //UNFORTUNATELY Opera implements attachEvent but does not follow the script + //script execution mode. + if (node.attachEvent && + //Check if node.attachEvent is artificially added by custom script or + //natively supported by browser + //read https://github.com/jrburke/requirejs/issues/187 + //if we can NOT find [native code] then it must NOT natively supported. + //in IE8, node.attachEvent does not have toString() + //Note the test for "[native code" with no closing brace, see: + //https://github.com/jrburke/requirejs/issues/273 + !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && + !isOpera) { + //Probably IE. IE (at least 6-8) do not fire + //script onload right after executing the script, so + //we cannot tie the anonymous define call to a name. + //However, IE reports the script as being in 'interactive' + //readyState at the time of the define call. + useInteractive = true; + + node.attachEvent('onreadystatechange', context.onScriptLoad); + //It would be great to add an error handler here to catch + //404s in IE9+. However, onreadystatechange will fire before + //the error handler, so that does not help. If addEventListener + //is used, then IE will fire error before load, but we cannot + //use that pathway given the connect.microsoft.com issue + //mentioned above about not doing the 'script execute, + //then fire the script load event listener before execute + //next script' that other browsers do. + //Best hope: IE10 fixes the issues, + //and then destroys all installs of IE 6-9. + //node.attachEvent('onerror', context.onScriptError); + } else { + node.addEventListener('load', context.onScriptLoad, false); + node.addEventListener('error', context.onScriptError, false); + } + node.src = url; + + //For some cache cases in IE 6-8, the script executes before the end + //of the appendChild execution, so to tie an anonymous define + //call to the module name (which is stored on the node), hold on + //to a reference to this node, but clear after the DOM insertion. + currentlyAddingScript = node; + if (baseElement) { + head.insertBefore(node, baseElement); + } else { + head.appendChild(node); + } + currentlyAddingScript = null; + + return node; + } else if (isWebWorker) { + try { + //In a web worker, use importScripts. This is not a very + //efficient use of importScripts, importScripts will block until + //its script is downloaded and evaluated. However, if web workers + //are in play, the expectation that a build has been done so that + //only one script needs to be loaded anyway. This may need to be + //reevaluated if other use cases become common. + importScripts(url); + + //Account for anonymous modules + context.completeLoad(moduleName); + } catch (e) { + context.onError(makeError('importscripts', + 'importScripts failed for ' + + moduleName + ' at ' + url, + e, + [moduleName])); + } + } + }; + + function getInteractiveScript() { + if (interactiveScript && interactiveScript.readyState === 'interactive') { + return interactiveScript; + } + + eachReverse(scripts(), function (script) { + if (script.readyState === 'interactive') { + return (interactiveScript = script); + } + }); + return interactiveScript; + } + + //Look for a data-main script attribute, which could also adjust the baseUrl. + if (isBrowser && !cfg.skipDataMain) { + //Figure out baseUrl. Get it from the script tag with require.js in it. + eachReverse(scripts(), function (script) { + //Set the 'head' where we can append children by + //using the script's parent. + if (!head) { + head = script.parentNode; + } + + //Look for a data-main attribute to set main script for the page + //to load. If it is there, the path to data main becomes the + //baseUrl, if it is not already set. + dataMain = script.getAttribute('data-main'); + if (dataMain) { + //Preserve dataMain in case it is a path (i.e. contains '?') + mainScript = dataMain; + + //Set final baseUrl if there is not already an explicit one. + if (!cfg.baseUrl) { + //Pull off the directory of data-main for use as the + //baseUrl. + src = mainScript.split('/'); + mainScript = src.pop(); + subPath = src.length ? src.join('/') + '/' : './'; + + cfg.baseUrl = subPath; + } + + //Strip off any trailing .js since mainScript is now + //like a module name. + mainScript = mainScript.replace(jsSuffixRegExp, ''); + + //If mainScript is still a path, fall back to dataMain + if (req.jsExtRegExp.test(mainScript)) { + mainScript = dataMain; + } + + //Put the data-main script in the files to load. + cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; + + return true; + } + }); + } + + /** + * The function that handles definitions of modules. Differs from + * require() in that a string for the module should be the first argument, + * and the function to execute after dependencies are loaded should + * return a value to define the module corresponding to the first argument's + * name. + */ + define = function (name, deps, callback) { + var node, context; + + //Allow for anonymous modules + if (typeof name !== 'string') { + //Adjust args appropriately + callback = deps; + deps = name; + name = null; + } + + //This module may not have dependencies + if (!isArray(deps)) { + callback = deps; + deps = null; + } + + //If no name, and callback is a function, then figure out if it a + //CommonJS thing with dependencies. + if (!deps && isFunction(callback)) { + deps = []; + //Remove comments from the callback string, + //look for require calls, and pull them into the dependencies, + //but only if there are function args. + if (callback.length) { + callback + .toString() + .replace(commentRegExp, '') + .replace(cjsRequireRegExp, function (match, dep) { + deps.push(dep); + }); + + //May be a CommonJS thing even without require calls, but still + //could use exports, and module. Avoid doing exports and module + //work though if it just needs require. + //REQUIRES the function to expect the CommonJS variables in the + //order listed below. + deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps); + } + } + + //If in IE 6-8 and hit an anonymous define() call, do the interactive + //work. + if (useInteractive) { + node = currentlyAddingScript || getInteractiveScript(); + if (node) { + if (!name) { + name = node.getAttribute('data-requiremodule'); + } + context = contexts[node.getAttribute('data-requirecontext')]; + } + } + + //Always save off evaluating the def call until the script onload handler. + //This allows multiple modules to be in a file without prematurely + //tracing dependencies, and allows for anonymous module support, + //where the module name is not known until the script onload event + //occurs. If no context, use the global queue, and get it processed + //in the onscript load callback. + (context ? context.defQueue : globalDefQueue).push([name, deps, callback]); + }; + + define.amd = { + jQuery: true + }; + + + /** + * Executes the text. Normally just uses eval, but can be modified + * to use a better, environment-specific call. Only used for transpiling + * loader plugins, not for plain JS modules. + * @param {String} text the text to execute/evaluate. + */ + req.exec = function (text) { + /*jslint evil: true */ + return eval(text); + }; + + //Set up with config info. + req(cfg); +}(this)); diff --git a/scripts/e2e-test.bat b/scripts/e2e-test.bat new file mode 100644 index 00000000..0b2aee60 --- /dev/null +++ b/scripts/e2e-test.bat @@ -0,0 +1,11 @@ +@echo off + +REM Windows script for running e2e tests +REM You have to run server and capture some browser first +REM +REM Requirements: +REM - NodeJS (http://nodejs.org/) +REM - Karma (npm install -g karma) + +set BASE_DIR=%~dp0 +karma start "%BASE_DIR%\..\config\karma-e2e.conf.js" %* diff --git a/scripts/e2e-test.sh b/scripts/e2e-test.sh new file mode 100755 index 00000000..47fe8275 --- /dev/null +++ b/scripts/e2e-test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +BASE_DIR=`dirname $0` + +echo "" +echo "Starting Karma Server (http://karma-runner.github.io)" +echo $BASE_DIR +echo "-------------------------------------------------------------------" + +$BASE_DIR/../node_modules/karma/bin/karma start $BASE_DIR/../config/karma-e2e.conf.js $* diff --git a/scripts/test.bat b/scripts/test.bat new file mode 100644 index 00000000..6571f8f2 --- /dev/null +++ b/scripts/test.bat @@ -0,0 +1,11 @@ +@echo off + +REM Windows script for running unit tests +REM You have to run server and capture some browser first +REM +REM Requirements: +REM - NodeJS (http://nodejs.org/) +REM - Karma (npm install -g karma) + +set BASE_DIR=%~dp0 +karma start "%BASE_DIR%\..\config\karma.conf.js" %* diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 00000000..f6db7624 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +BASE_DIR=`dirname $0` + +echo "" +echo "Starting Karma Server (http://karma-runner.github.io)" +echo "-------------------------------------------------------------------" + +#$BASE_DIR/../node_modules/karma/bin/karma start $BASE_DIR/../config/karma.conf.js $* +karma start $BASE_DIR/../config/karma.conf.js $* diff --git a/scripts/watchr.rb b/scripts/watchr.rb new file mode 100755 index 00000000..89ef656d --- /dev/null +++ b/scripts/watchr.rb @@ -0,0 +1,19 @@ +#!/usr/bin/env watchr + +# config file for watchr http://github.com/mynyml/watchr +# install: gem install watchr +# run: watch watchr.rb +# note: make sure that you have jstd server running (server.sh) and a browser captured + +log_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log') + +`cd ..` +`touch #{log_file}` + +puts "String watchr... log file: #{log_file}" + +watch( '(app/js|test/unit)' ) do + `echo "\n\ntest run started @ \`date\`" > #{log_file}` + `scripts/test.sh &> #{log_file}` +end + diff --git a/scripts/web-server.js b/scripts/web-server.js new file mode 100755 index 00000000..3f74441e --- /dev/null +++ b/scripts/web-server.js @@ -0,0 +1,244 @@ +#!/usr/bin/env node + +var util = require('util'), + http = require('http'), + fs = require('fs'), + url = require('url'), + events = require('events'); + +var DEFAULT_PORT = 8000; + +function main(argv) { + new HttpServer({ + 'GET': createServlet(StaticServlet), + 'HEAD': createServlet(StaticServlet) + }).start(Number(argv[2]) || DEFAULT_PORT); +} + +function escapeHtml(value) { + return value.toString(). + replace('<', '<'). + replace('>', '>'). + replace('"', '"'); +} + +function createServlet(Class) { + var servlet = new Class(); + return servlet.handleRequest.bind(servlet); +} + +/** + * An Http server implementation that uses a map of methods to decide + * action routing. + * + * @param {Object} Map of method => Handler function + */ +function HttpServer(handlers) { + this.handlers = handlers; + this.server = http.createServer(this.handleRequest_.bind(this)); +} + +HttpServer.prototype.start = function(port) { + this.port = port; + this.server.listen(port); + util.puts('Http Server running at http://localhost:' + port + '/'); +}; + +HttpServer.prototype.parseUrl_ = function(urlString) { + var parsed = url.parse(urlString); + parsed.pathname = url.resolve('/', parsed.pathname); + return url.parse(url.format(parsed), true); +}; + +HttpServer.prototype.handleRequest_ = function(req, res) { + var logEntry = req.method + ' ' + req.url; + if (req.headers['user-agent']) { + logEntry += ' ' + req.headers['user-agent']; + } + util.puts(logEntry); + req.url = this.parseUrl_(req.url); + var handler = this.handlers[req.method]; + if (!handler) { + res.writeHead(501); + res.end(); + } else { + handler.call(this, req, res); + } +}; + +/** + * Handles static content. + */ +function StaticServlet() {} + +StaticServlet.MimeMap = { + 'txt': 'text/plain', + 'html': 'text/html', + 'css': 'text/css', + 'xml': 'application/xml', + 'json': 'application/json', + 'js': 'application/javascript', + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'gif': 'image/gif', + 'png': 'image/png', +  'svg': 'image/svg+xml' +}; + +StaticServlet.prototype.handleRequest = function(req, res) { + var self = this; + var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){ + return String.fromCharCode(parseInt(hex, 16)); + }); + var parts = path.split('/'); + if (parts[parts.length-1].charAt(0) === '.') + return self.sendForbidden_(req, res, path); + fs.stat(path, function(err, stat) { + if (err) + return self.sendMissing_(req, res, path); + if (stat.isDirectory()) + return self.sendDirectory_(req, res, path); + return self.sendFile_(req, res, path); + }); +} + +StaticServlet.prototype.sendError_ = function(req, res, error) { + res.writeHead(500, { + 'Content-Type': 'text/html' + }); + res.write('\n'); + res.write('Internal Server Error\n'); + res.write('

    Internal Server Error

    '); + res.write('
    ' + escapeHtml(util.inspect(error)) + '
    '); + util.puts('500 Internal Server Error'); + util.puts(util.inspect(error)); +}; + +StaticServlet.prototype.sendMissing_ = function(req, res, path) { + path = path.substring(1); + res.writeHead(404, { + 'Content-Type': 'text/html' + }); + res.write('\n'); + res.write('404 Not Found\n'); + res.write('

    Not Found

    '); + res.write( + '

    The requested URL ' + + escapeHtml(path) + + ' was not found on this server.

    ' + ); + res.end(); + util.puts('404 Not Found: ' + path); +}; + +StaticServlet.prototype.sendForbidden_ = function(req, res, path) { + path = path.substring(1); + res.writeHead(403, { + 'Content-Type': 'text/html' + }); + res.write('\n'); + res.write('403 Forbidden\n'); + res.write('

    Forbidden

    '); + res.write( + '

    You do not have permission to access ' + + escapeHtml(path) + ' on this server.

    ' + ); + res.end(); + util.puts('403 Forbidden: ' + path); +}; + +StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) { + res.writeHead(301, { + 'Content-Type': 'text/html', + 'Location': redirectUrl + }); + res.write('\n'); + res.write('301 Moved Permanently\n'); + res.write('

    Moved Permanently

    '); + res.write( + '

    The document has moved here.

    ' + ); + res.end(); + util.puts('301 Moved Permanently: ' + redirectUrl); +}; + +StaticServlet.prototype.sendFile_ = function(req, res, path) { + var self = this; + var file = fs.createReadStream(path); + res.writeHead(200, { + 'Content-Type': StaticServlet. + MimeMap[path.split('.').pop()] || 'text/plain' + }); + if (req.method === 'HEAD') { + res.end(); + } else { + file.on('data', res.write.bind(res)); + file.on('close', function() { + res.end(); + }); + file.on('error', function(error) { + self.sendError_(req, res, error); + }); + } +}; + +StaticServlet.prototype.sendDirectory_ = function(req, res, path) { + var self = this; + if (path.match(/[^\/]$/)) { + req.url.pathname += '/'; + var redirectUrl = url.format(url.parse(url.format(req.url))); + return self.sendRedirect_(req, res, redirectUrl); + } + fs.readdir(path, function(err, files) { + if (err) + return self.sendError_(req, res, error); + + if (!files.length) + return self.writeDirectoryIndex_(req, res, path, []); + + var remaining = files.length; + files.forEach(function(fileName, index) { + fs.stat(path + '/' + fileName, function(err, stat) { + if (err) + return self.sendError_(req, res, err); + if (stat.isDirectory()) { + files[index] = fileName + '/'; + } + if (!(--remaining)) + return self.writeDirectoryIndex_(req, res, path, files); + }); + }); + }); +}; + +StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) { + path = path.substring(1); + res.writeHead(200, { + 'Content-Type': 'text/html' + }); + if (req.method === 'HEAD') { + res.end(); + return; + } + res.write('\n'); + res.write('' + escapeHtml(path) + '\n'); + res.write('\n'); + res.write('

    Directory: ' + escapeHtml(path) + '

    '); + res.write('
      '); + files.forEach(function(fileName) { + if (fileName.charAt(0) !== '.') { + res.write('
    1. ' + + escapeHtml(fileName) + '
    2. '); + } + }); + res.write('
    '); + res.end(); +}; + +// Must be last, +main(process.argv); diff --git a/test/e2e/runner.html b/test/e2e/runner.html new file mode 100644 index 00000000..859c90e3 --- /dev/null +++ b/test/e2e/runner.html @@ -0,0 +1,11 @@ + + + + End2end Test Runner + + + + + + + diff --git a/test/e2e/scenarios.js b/test/e2e/scenarios.js new file mode 100644 index 00000000..a3a22f02 --- /dev/null +++ b/test/e2e/scenarios.js @@ -0,0 +1,45 @@ +'use strict'; + +/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */ + +describe('my app', function() { + + beforeEach(function() { + browser().navigateTo('app/index.html'); + }); + + + it('should automatically redirect to /view1 when location hash/fragment is empty', function() { + expect(browser().location().url()).toBe("/view1"); + }); + + + describe('view1', function() { + + beforeEach(function() { + browser().navigateTo('#/view1'); + }); + + + it('should render view1 when user navigates to /view1', function() { + expect(element('[ng-view] p:first').text()). + toMatch(/partial for view 1/); + }); + + }); + + + describe('view2', function() { + + beforeEach(function() { + browser().navigateTo('#/view2'); + }); + + + it('should render view2 when user navigates to /view2', function() { + expect(element('[ng-view] p:first').text()). + toMatch(/partial for view 2/); + }); + + }); +}); diff --git a/test/lib/angular/angular-mocks.js b/test/lib/angular/angular-mocks.js new file mode 100644 index 00000000..c85e18a9 --- /dev/null +++ b/test/lib/angular/angular-mocks.js @@ -0,0 +1,2115 @@ +/** + * @license AngularJS v1.2.3 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) { + +'use strict'; + +/** + * @ngdoc overview + * @name angular.mock + * @description + * + * Namespace from 'angular-mocks.js' which contains testing related code. + */ +angular.mock = {}; + +/** + * ! This is a private undocumented service ! + * + * @name ngMock.$browser + * + * @description + * This service is a mock implementation of {@link ng.$browser}. It provides fake + * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr, + * cookies, etc... + * + * The api of this service is the same as that of the real {@link ng.$browser $browser}, except + * that there are several helper methods available which can be used in tests. + */ +angular.mock.$BrowserProvider = function() { + this.$get = function() { + return new angular.mock.$Browser(); + }; +}; + +angular.mock.$Browser = function() { + var self = this; + + this.isMock = true; + self.$$url = "http://server/"; + self.$$lastUrl = self.$$url; // used by url polling fn + self.pollFns = []; + + // TODO(vojta): remove this temporary api + self.$$completeOutstandingRequest = angular.noop; + self.$$incOutstandingRequestCount = angular.noop; + + + // register url polling fn + + self.onUrlChange = function(listener) { + self.pollFns.push( + function() { + if (self.$$lastUrl != self.$$url) { + self.$$lastUrl = self.$$url; + listener(self.$$url); + } + } + ); + + return listener; + }; + + self.cookieHash = {}; + self.lastCookieHash = {}; + self.deferredFns = []; + self.deferredNextId = 0; + + self.defer = function(fn, delay) { + delay = delay || 0; + self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId}); + self.deferredFns.sort(function(a,b){ return a.time - b.time;}); + return self.deferredNextId++; + }; + + + /** + * @name ngMock.$browser#defer.now + * @propertyOf ngMock.$browser + * + * @description + * Current milliseconds mock time. + */ + self.defer.now = 0; + + + self.defer.cancel = function(deferId) { + var fnIndex; + + angular.forEach(self.deferredFns, function(fn, index) { + if (fn.id === deferId) fnIndex = index; + }); + + if (fnIndex !== undefined) { + self.deferredFns.splice(fnIndex, 1); + return true; + } + + return false; + }; + + + /** + * @name ngMock.$browser#defer.flush + * @methodOf ngMock.$browser + * + * @description + * Flushes all pending requests and executes the defer callbacks. + * + * @param {number=} number of milliseconds to flush. See {@link #defer.now} + */ + self.defer.flush = function(delay) { + if (angular.isDefined(delay)) { + self.defer.now += delay; + } else { + if (self.deferredFns.length) { + self.defer.now = self.deferredFns[self.deferredFns.length-1].time; + } else { + throw new Error('No deferred tasks to be flushed'); + } + } + + while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) { + self.deferredFns.shift().fn(); + } + }; + + self.$$baseHref = ''; + self.baseHref = function() { + return this.$$baseHref; + }; +}; +angular.mock.$Browser.prototype = { + +/** + * @name ngMock.$browser#poll + * @methodOf ngMock.$browser + * + * @description + * run all fns in pollFns + */ + poll: function poll() { + angular.forEach(this.pollFns, function(pollFn){ + pollFn(); + }); + }, + + addPollFn: function(pollFn) { + this.pollFns.push(pollFn); + return pollFn; + }, + + url: function(url, replace) { + if (url) { + this.$$url = url; + return this; + } + + return this.$$url; + }, + + cookies: function(name, value) { + if (name) { + if (angular.isUndefined(value)) { + delete this.cookieHash[name]; + } else { + if (angular.isString(value) && //strings only + value.length <= 4096) { //strict cookie storage limits + this.cookieHash[name] = value; + } + } + } else { + if (!angular.equals(this.cookieHash, this.lastCookieHash)) { + this.lastCookieHash = angular.copy(this.cookieHash); + this.cookieHash = angular.copy(this.cookieHash); + } + return this.cookieHash; + } + }, + + notifyWhenNoOutstandingRequests: function(fn) { + fn(); + } +}; + + +/** + * @ngdoc object + * @name ngMock.$exceptionHandlerProvider + * + * @description + * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors + * passed into the `$exceptionHandler`. + */ + +/** + * @ngdoc object + * @name ngMock.$exceptionHandler + * + * @description + * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed + * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration + * information. + * + * + *
    + *   describe('$exceptionHandlerProvider', function() {
    + *
    + *     it('should capture log messages and exceptions', function() {
    + *
    + *       module(function($exceptionHandlerProvider) {
    + *         $exceptionHandlerProvider.mode('log');
    + *       });
    + *
    + *       inject(function($log, $exceptionHandler, $timeout) {
    + *         $timeout(function() { $log.log(1); });
    + *         $timeout(function() { $log.log(2); throw 'banana peel'; });
    + *         $timeout(function() { $log.log(3); });
    + *         expect($exceptionHandler.errors).toEqual([]);
    + *         expect($log.assertEmpty());
    + *         $timeout.flush();
    + *         expect($exceptionHandler.errors).toEqual(['banana peel']);
    + *         expect($log.log.logs).toEqual([[1], [2], [3]]);
    + *       });
    + *     });
    + *   });
    + * 
    + */ + +angular.mock.$ExceptionHandlerProvider = function() { + var handler; + + /** + * @ngdoc method + * @name ngMock.$exceptionHandlerProvider#mode + * @methodOf ngMock.$exceptionHandlerProvider + * + * @description + * Sets the logging mode. + * + * @param {string} mode Mode of operation, defaults to `rethrow`. + * + * - `rethrow`: If any errors are passed into the handler in tests, it typically + * means that there is a bug in the application or test, so this mock will + * make these tests fail. + * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` + * mode stores an array of errors in `$exceptionHandler.errors`, to allow later + * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and + * {@link ngMock.$log#reset reset()} + */ + this.mode = function(mode) { + switch(mode) { + case 'rethrow': + handler = function(e) { + throw e; + }; + break; + case 'log': + var errors = []; + + handler = function(e) { + if (arguments.length == 1) { + errors.push(e); + } else { + errors.push([].slice.call(arguments, 0)); + } + }; + + handler.errors = errors; + break; + default: + throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!"); + } + }; + + this.$get = function() { + return handler; + }; + + this.mode('rethrow'); +}; + + +/** + * @ngdoc service + * @name ngMock.$log + * + * @description + * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays + * (one array per logging level). These arrays are exposed as `logs` property of each of the + * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`. + * + */ +angular.mock.$LogProvider = function() { + var debug = true; + + function concat(array1, array2, index) { + return array1.concat(Array.prototype.slice.call(array2, index)); + } + + this.debugEnabled = function(flag) { + if (angular.isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } + }; + + this.$get = function () { + var $log = { + log: function() { $log.log.logs.push(concat([], arguments, 0)); }, + warn: function() { $log.warn.logs.push(concat([], arguments, 0)); }, + info: function() { $log.info.logs.push(concat([], arguments, 0)); }, + error: function() { $log.error.logs.push(concat([], arguments, 0)); }, + debug: function() { + if (debug) { + $log.debug.logs.push(concat([], arguments, 0)); + } + } + }; + + /** + * @ngdoc method + * @name ngMock.$log#reset + * @methodOf ngMock.$log + * + * @description + * Reset all of the logging arrays to empty. + */ + $log.reset = function () { + /** + * @ngdoc property + * @name ngMock.$log#log.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#log}. + * + * @example + *
    +       * $log.log('Some Log');
    +       * var first = $log.log.logs.unshift();
    +       * 
    + */ + $log.log.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#info.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#info}. + * + * @example + *
    +       * $log.info('Some Info');
    +       * var first = $log.info.logs.unshift();
    +       * 
    + */ + $log.info.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#warn.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#warn}. + * + * @example + *
    +       * $log.warn('Some Warning');
    +       * var first = $log.warn.logs.unshift();
    +       * 
    + */ + $log.warn.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#error.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#error}. + * + * @example + *
    +       * $log.log('Some Error');
    +       * var first = $log.error.logs.unshift();
    +       * 
    + */ + $log.error.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#debug.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#debug}. + * + * @example + *
    +       * $log.debug('Some Error');
    +       * var first = $log.debug.logs.unshift();
    +       * 
    + */ + $log.debug.logs = []; + }; + + /** + * @ngdoc method + * @name ngMock.$log#assertEmpty + * @methodOf ngMock.$log + * + * @description + * Assert that the all of the logging methods have no logged messages. If messages present, an + * exception is thrown. + */ + $log.assertEmpty = function() { + var errors = []; + angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) { + angular.forEach($log[logLevel].logs, function(log) { + angular.forEach(log, function (logItem) { + errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + + (logItem.stack || '')); + }); + }); + }); + if (errors.length) { + errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+ + "an expected log message was not checked and removed:"); + errors.push(''); + throw new Error(errors.join('\n---------\n')); + } + }; + + $log.reset(); + return $log; + }; +}; + + +/** + * @ngdoc service + * @name ngMock.$interval + * + * @description + * Mock implementation of the $interval service. + * + * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + * @param {function()} fn A function that should be called repeatedly. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block. + * @returns {promise} A promise which will be notified on each iteration. + */ +angular.mock.$IntervalProvider = function() { + this.$get = ['$rootScope', '$q', + function($rootScope, $q) { + var repeatFns = [], + nextRepeatId = 0, + now = 0; + + var $interval = function(fn, delay, count, invokeApply) { + var deferred = $q.defer(), + promise = deferred.promise, + iteration = 0, + skipApply = (angular.isDefined(invokeApply) && !invokeApply); + + count = (angular.isDefined(count)) ? count : 0, + promise.then(null, null, fn); + + promise.$$intervalId = nextRepeatId; + + function tick() { + deferred.notify(iteration++); + + if (count > 0 && iteration >= count) { + var fnIndex; + deferred.resolve(iteration); + + angular.forEach(repeatFns, function(fn, index) { + if (fn.id === promise.$$intervalId) fnIndex = index; + }); + + if (fnIndex !== undefined) { + repeatFns.splice(fnIndex, 1); + } + } + + if (!skipApply) $rootScope.$apply(); + } + + repeatFns.push({ + nextTime:(now + delay), + delay: delay, + fn: tick, + id: nextRepeatId, + deferred: deferred + }); + repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); + + nextRepeatId++; + return promise; + }; + + $interval.cancel = function(promise) { + var fnIndex; + + angular.forEach(repeatFns, function(fn, index) { + if (fn.id === promise.$$intervalId) fnIndex = index; + }); + + if (fnIndex !== undefined) { + repeatFns[fnIndex].deferred.reject('canceled'); + repeatFns.splice(fnIndex, 1); + return true; + } + + return false; + }; + + /** + * @ngdoc method + * @name ngMock.$interval#flush + * @methodOf ngMock.$interval + * @description + * + * Runs interval tasks scheduled to be run in the next `millis` milliseconds. + * + * @param {number=} millis maximum timeout amount to flush up until. + * + * @return {number} The amount of time moved forward. + */ + $interval.flush = function(millis) { + now += millis; + while (repeatFns.length && repeatFns[0].nextTime <= now) { + var task = repeatFns[0]; + task.fn(); + task.nextTime += task.delay; + repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); + } + return millis; + }; + + return $interval; + }]; +}; + + +/* jshint -W101 */ +/* The R_ISO8061_STR regex is never going to fit into the 100 char limit! + * This directive should go inside the anonymous function but a bug in JSHint means that it would + * not be enacted early enough to prevent the warning. + */ +var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/; + +function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8061_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0; + if (match[9]) { + tzHour = int(match[9] + match[10]); + tzMin = int(match[9] + match[11]); + } + date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); + date.setUTCHours(int(match[4]||0) - tzHour, + int(match[5]||0) - tzMin, + int(match[6]||0), + int(match[7]||0)); + return date; + } + return string; +} + +function int(str) { + return parseInt(str, 10); +} + +function padNumber(num, digits, trim) { + var neg = ''; + if (num < 0) { + neg = '-'; + num = -num; + } + num = '' + num; + while(num.length < digits) num = '0' + num; + if (trim) + num = num.substr(num.length - digits); + return neg + num; +} + + +/** + * @ngdoc object + * @name angular.mock.TzDate + * @description + * + * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`. + * + * Mock of the Date type which has its timezone specified via constructor arg. + * + * The main purpose is to create Date-like instances with timezone fixed to the specified timezone + * offset, so that we can test code that depends on local timezone settings without dependency on + * the time zone settings of the machine where the code is running. + * + * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored) + * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* + * + * @example + * !!!! WARNING !!!!! + * This is not a complete Date object so only methods that were implemented can be called safely. + * To make matters worse, TzDate instances inherit stuff from Date via a prototype. + * + * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is + * incomplete we might be missing some non-standard methods. This can result in errors like: + * "Date.prototype.foo called on incompatible Object". + * + *
    + * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
    + * newYearInBratislava.getTimezoneOffset() => -60;
    + * newYearInBratislava.getFullYear() => 2010;
    + * newYearInBratislava.getMonth() => 0;
    + * newYearInBratislava.getDate() => 1;
    + * newYearInBratislava.getHours() => 0;
    + * newYearInBratislava.getMinutes() => 0;
    + * newYearInBratislava.getSeconds() => 0;
    + * 
    + * + */ +angular.mock.TzDate = function (offset, timestamp) { + var self = new Date(0); + if (angular.isString(timestamp)) { + var tsStr = timestamp; + + self.origDate = jsonStringToDate(timestamp); + + timestamp = self.origDate.getTime(); + if (isNaN(timestamp)) + throw { + name: "Illegal Argument", + message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" + }; + } else { + self.origDate = new Date(timestamp); + } + + var localOffset = new Date(timestamp).getTimezoneOffset(); + self.offsetDiff = localOffset*60*1000 - offset*1000*60*60; + self.date = new Date(timestamp + self.offsetDiff); + + self.getTime = function() { + return self.date.getTime() - self.offsetDiff; + }; + + self.toLocaleDateString = function() { + return self.date.toLocaleDateString(); + }; + + self.getFullYear = function() { + return self.date.getFullYear(); + }; + + self.getMonth = function() { + return self.date.getMonth(); + }; + + self.getDate = function() { + return self.date.getDate(); + }; + + self.getHours = function() { + return self.date.getHours(); + }; + + self.getMinutes = function() { + return self.date.getMinutes(); + }; + + self.getSeconds = function() { + return self.date.getSeconds(); + }; + + self.getMilliseconds = function() { + return self.date.getMilliseconds(); + }; + + self.getTimezoneOffset = function() { + return offset * 60; + }; + + self.getUTCFullYear = function() { + return self.origDate.getUTCFullYear(); + }; + + self.getUTCMonth = function() { + return self.origDate.getUTCMonth(); + }; + + self.getUTCDate = function() { + return self.origDate.getUTCDate(); + }; + + self.getUTCHours = function() { + return self.origDate.getUTCHours(); + }; + + self.getUTCMinutes = function() { + return self.origDate.getUTCMinutes(); + }; + + self.getUTCSeconds = function() { + return self.origDate.getUTCSeconds(); + }; + + self.getUTCMilliseconds = function() { + return self.origDate.getUTCMilliseconds(); + }; + + self.getDay = function() { + return self.date.getDay(); + }; + + // provide this method only on browsers that already have it + if (self.toISOString) { + self.toISOString = function() { + return padNumber(self.origDate.getUTCFullYear(), 4) + '-' + + padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' + + padNumber(self.origDate.getUTCDate(), 2) + 'T' + + padNumber(self.origDate.getUTCHours(), 2) + ':' + + padNumber(self.origDate.getUTCMinutes(), 2) + ':' + + padNumber(self.origDate.getUTCSeconds(), 2) + '.' + + padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'; + }; + } + + //hide all methods not implemented in this mock that the Date prototype exposes + var unimplementedMethods = ['getUTCDay', + 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', + 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', + 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', + 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString', + 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf']; + + angular.forEach(unimplementedMethods, function(methodName) { + self[methodName] = function() { + throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock"); + }; + }); + + return self; +}; + +//make "tzDateInstance instanceof Date" return true +angular.mock.TzDate.prototype = Date.prototype; +/* jshint +W101 */ + +angular.mock.animate = angular.module('mock.animate', ['ng']) + + .config(['$provide', function($provide) { + + $provide.decorator('$animate', function($delegate) { + var animate = { + queue : [], + enabled : $delegate.enabled, + flushNext : function(name) { + var tick = animate.queue.shift(); + + if (!tick) throw new Error('No animation to be flushed'); + if(tick.method !== name) { + throw new Error('The next animation is not "' + name + + '", but is "' + tick.method + '"'); + } + tick.fn(); + return tick; + } + }; + + angular.forEach(['enter','leave','move','addClass','removeClass'], function(method) { + animate[method] = function() { + var params = arguments; + animate.queue.push({ + method : method, + params : params, + element : angular.isElement(params[0]) && params[0], + parent : angular.isElement(params[1]) && params[1], + after : angular.isElement(params[2]) && params[2], + fn : function() { + $delegate[method].apply($delegate, params); + } + }); + }; + }); + + return animate; + }); + + }]); + + +/** + * @ngdoc function + * @name angular.mock.dump + * @description + * + * *NOTE*: this is not an injectable instance, just a globally available function. + * + * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for + * debugging. + * + * This method is also available on window, where it can be used to display objects on debug + * console. + * + * @param {*} object - any object to turn into string. + * @return {string} a serialized string of the argument + */ +angular.mock.dump = function(object) { + return serialize(object); + + function serialize(object) { + var out; + + if (angular.isElement(object)) { + object = angular.element(object); + out = angular.element('
    '); + angular.forEach(object, function(element) { + out.append(angular.element(element).clone()); + }); + out = out.html(); + } else if (angular.isArray(object)) { + out = []; + angular.forEach(object, function(o) { + out.push(serialize(o)); + }); + out = '[ ' + out.join(', ') + ' ]'; + } else if (angular.isObject(object)) { + if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) { + out = serializeScope(object); + } else if (object instanceof Error) { + out = object.stack || ('' + object.name + ': ' + object.message); + } else { + // TODO(i): this prevents methods being logged, + // we should have a better way to serialize objects + out = angular.toJson(object, true); + } + } else { + out = String(object); + } + + return out; + } + + function serializeScope(scope, offset) { + offset = offset || ' '; + var log = [offset + 'Scope(' + scope.$id + '): {']; + for ( var key in scope ) { + if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) { + log.push(' ' + key + ': ' + angular.toJson(scope[key])); + } + } + var child = scope.$$childHead; + while(child) { + log.push(serializeScope(child, offset + ' ')); + child = child.$$nextSibling; + } + log.push('}'); + return log.join('\n' + offset); + } +}; + +/** + * @ngdoc object + * @name ngMock.$httpBackend + * @description + * Fake HTTP backend implementation suitable for unit testing applications that use the + * {@link ng.$http $http service}. + * + * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less + * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}. + * + * During unit testing, we want our unit tests to run quickly and have no external dependencies so + * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or + * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is + * to verify whether a certain request has been sent or not, or alternatively just let the + * application make requests, respond with pre-trained responses and assert that the end result is + * what we expect it to be. + * + * This mock implementation can be used to respond with static or dynamic responses via the + * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc). + * + * When an Angular application needs some data from a server, it calls the $http service, which + * sends the request to a real server using $httpBackend service. With dependency injection, it is + * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify + * the requests and respond with some testing data without sending a request to real server. + * + * There are two ways to specify what test data should be returned as http responses by the mock + * backend when the code under test makes http requests: + * + * - `$httpBackend.expect` - specifies a request expectation + * - `$httpBackend.when` - specifies a backend definition + * + * + * # Request Expectations vs Backend Definitions + * + * Request expectations provide a way to make assertions about requests made by the application and + * to define responses for those requests. The test will fail if the expected requests are not made + * or they are made in the wrong order. + * + * Backend definitions allow you to define a fake backend for your application which doesn't assert + * if a particular request was made or not, it just returns a trained response if a request is made. + * The test will pass whether or not the request gets made during testing. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Request expectationsBackend definitions
    Syntax.expect(...).respond(...).when(...).respond(...)
    Typical usagestrict unit testsloose (black-box) unit testing
    Fulfills multiple requestsNOYES
    Order of requests mattersYESNO
    Request requiredYESNO
    Response requiredoptional (see below)YES
    + * + * In cases where both backend definitions and request expectations are specified during unit + * testing, the request expectations are evaluated first. + * + * If a request expectation has no response specified, the algorithm will search your backend + * definitions for an appropriate response. + * + * If a request didn't match any expectation or if the expectation doesn't have the response + * defined, the backend definitions are evaluated in sequential order to see if any of them match + * the request. The response from the first matched definition is returned. + * + * + * # Flushing HTTP requests + * + * The $httpBackend used in production, always responds to requests with responses asynchronously. + * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are + * hard to write, follow and maintain. At the same time the testing mock, can't respond + * synchronously because that would change the execution of the code under test. For this reason the + * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending + * requests and thus preserving the async api of the backend, while allowing the test to execute + * synchronously. + * + * + * # Unit testing with mock $httpBackend + * The following code shows how to setup and use the mock backend in unit testing a controller. + * First we create the controller under test + * +
    +  // The controller code
    +  function MyController($scope, $http) {
    +    var authToken;
    +
    +    $http.get('/auth.py').success(function(data, status, headers) {
    +      authToken = headers('A-Token');
    +      $scope.user = data;
    +    });
    +
    +    $scope.saveMessage = function(message) {
    +      var headers = { 'Authorization': authToken };
    +      $scope.status = 'Saving...';
    +
    +      $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
    +        $scope.status = '';
    +      }).error(function() {
    +        $scope.status = 'ERROR!';
    +      });
    +    };
    +  }
    +  
    + * + * Now we setup the mock backend and create the test specs. + * +
    +    // testing controller
    +    describe('MyController', function() {
    +       var $httpBackend, $rootScope, createController;
    +
    +       beforeEach(inject(function($injector) {
    +         // Set up the mock http service responses
    +         $httpBackend = $injector.get('$httpBackend');
    +         // backend definition common for all tests
    +         $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
    +
    +         // Get hold of a scope (i.e. the root scope)
    +         $rootScope = $injector.get('$rootScope');
    +         // The $controller service is used to create instances of controllers
    +         var $controller = $injector.get('$controller');
    +
    +         createController = function() {
    +           return $controller('MyController', {'$scope' : $rootScope });
    +         };
    +       }));
    +
    +
    +       afterEach(function() {
    +         $httpBackend.verifyNoOutstandingExpectation();
    +         $httpBackend.verifyNoOutstandingRequest();
    +       });
    +
    +
    +       it('should fetch authentication token', function() {
    +         $httpBackend.expectGET('/auth.py');
    +         var controller = createController();
    +         $httpBackend.flush();
    +       });
    +
    +
    +       it('should send msg to server', function() {
    +         var controller = createController();
    +         $httpBackend.flush();
    +
    +         // now you don’t care about the authentication, but
    +         // the controller will still send the request and
    +         // $httpBackend will respond without you having to
    +         // specify the expectation and response for this request
    +
    +         $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
    +         $rootScope.saveMessage('message content');
    +         expect($rootScope.status).toBe('Saving...');
    +         $httpBackend.flush();
    +         expect($rootScope.status).toBe('');
    +       });
    +
    +
    +       it('should send auth header', function() {
    +         var controller = createController();
    +         $httpBackend.flush();
    +
    +         $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
    +           // check if the header was send, if it wasn't the expectation won't
    +           // match the request and the test will fail
    +           return headers['Authorization'] == 'xxx';
    +         }).respond(201, '');
    +
    +         $rootScope.saveMessage('whatever');
    +         $httpBackend.flush();
    +       });
    +    });
    +   
    + */ +angular.mock.$HttpBackendProvider = function() { + this.$get = ['$rootScope', createHttpBackendMock]; +}; + +/** + * General factory function for $httpBackend mock. + * Returns instance for unit testing (when no arguments specified): + * - passing through is disabled + * - auto flushing is disabled + * + * Returns instance for e2e testing (when `$delegate` and `$browser` specified): + * - passing through (delegating request to real backend) is enabled + * - auto flushing is enabled + * + * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified) + * @param {Object=} $browser Auto-flushing enabled if specified + * @return {Object} Instance of $httpBackend mock + */ +function createHttpBackendMock($rootScope, $delegate, $browser) { + var definitions = [], + expectations = [], + responses = [], + responsesPush = angular.bind(responses, responses.push); + + function createResponse(status, data, headers) { + if (angular.isFunction(status)) return status; + + return function() { + return angular.isNumber(status) + ? [status, data, headers] + : [200, status, data]; + }; + } + + // TODO(vojta): change params to: method, url, data, headers, callback + function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) { + var xhr = new MockXhr(), + expectation = expectations[0], + wasExpected = false; + + function prettyPrint(data) { + return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp) + ? data + : angular.toJson(data); + } + + function wrapResponse(wrapped) { + if (!$browser && timeout && timeout.then) timeout.then(handleTimeout); + + return handleResponse; + + function handleResponse() { + var response = wrapped.response(method, url, data, headers); + xhr.$$respHeaders = response[2]; + callback(response[0], response[1], xhr.getAllResponseHeaders()); + } + + function handleTimeout() { + for (var i = 0, ii = responses.length; i < ii; i++) { + if (responses[i] === handleResponse) { + responses.splice(i, 1); + callback(-1, undefined, ''); + break; + } + } + } + } + + if (expectation && expectation.match(method, url)) { + if (!expectation.matchData(data)) + throw new Error('Expected ' + expectation + ' with different data\n' + + 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data); + + if (!expectation.matchHeaders(headers)) + throw new Error('Expected ' + expectation + ' with different headers\n' + + 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + + prettyPrint(headers)); + + expectations.shift(); + + if (expectation.response) { + responses.push(wrapResponse(expectation)); + return; + } + wasExpected = true; + } + + var i = -1, definition; + while ((definition = definitions[++i])) { + if (definition.match(method, url, data, headers || {})) { + if (definition.response) { + // if $browser specified, we do auto flush all requests + ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); + } else if (definition.passThrough) { + $delegate(method, url, data, callback, headers, timeout, withCredentials); + } else throw new Error('No response defined !'); + return; + } + } + throw wasExpected ? + new Error('No response defined !') : + new Error('Unexpected request: ' + method + ' ' + url + '\n' + + (expectation ? 'Expected ' + expectation : 'No more request expected')); + } + + /** + * @ngdoc method + * @name ngMock.$httpBackend#when + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + */ + $httpBackend.when = function(method, url, data, headers) { + var definition = new MockHttpExpectation(method, url, data, headers), + chain = { + respond: function(status, data, headers) { + definition.response = createResponse(status, data, headers); + } + }; + + if ($browser) { + chain.passThrough = function() { + definition.passThrough = true; + }; + } + + definitions.push(definition); + return chain; + }; + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenGET + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for GET requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenHEAD + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for HEAD requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenDELETE + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for DELETE requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenPOST + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for POST requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenPUT + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for PUT requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenJSONP + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for JSONP requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + createShortMethods('when'); + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expect + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + */ + $httpBackend.expect = function(method, url, data, headers) { + var expectation = new MockHttpExpectation(method, url, data, headers); + expectations.push(expectation); + return { + respond: function(status, data, headers) { + expectation.response = createResponse(status, data, headers); + } + }; + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectGET + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for GET requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. See #expect for more info. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectHEAD + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for HEAD requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectDELETE + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for DELETE requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPOST + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for POST requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPUT + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for PUT requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPATCH + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for PATCH requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectJSONP + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for JSONP requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + createShortMethods('expect'); + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#flush + * @methodOf ngMock.$httpBackend + * @description + * Flushes all pending requests using the trained responses. + * + * @param {number=} count Number of responses to flush (in the order they arrived). If undefined, + * all pending requests will be flushed. If there are no pending requests when the flush method + * is called an exception is thrown (as this typically a sign of programming error). + */ + $httpBackend.flush = function(count) { + $rootScope.$digest(); + if (!responses.length) throw new Error('No pending request to flush !'); + + if (angular.isDefined(count)) { + while (count--) { + if (!responses.length) throw new Error('No more pending request to flush !'); + responses.shift()(); + } + } else { + while (responses.length) { + responses.shift()(); + } + } + $httpBackend.verifyNoOutstandingExpectation(); + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#verifyNoOutstandingExpectation + * @methodOf ngMock.$httpBackend + * @description + * Verifies that all of the requests defined via the `expect` api were made. If any of the + * requests were not made, verifyNoOutstandingExpectation throws an exception. + * + * Typically, you would call this method following each test case that asserts requests using an + * "afterEach" clause. + * + *
    +   *   afterEach($httpBackend.verifyNoOutstandingExpectation);
    +   * 
    + */ + $httpBackend.verifyNoOutstandingExpectation = function() { + $rootScope.$digest(); + if (expectations.length) { + throw new Error('Unsatisfied requests: ' + expectations.join(', ')); + } + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#verifyNoOutstandingRequest + * @methodOf ngMock.$httpBackend + * @description + * Verifies that there are no outstanding requests that need to be flushed. + * + * Typically, you would call this method following each test case that asserts requests using an + * "afterEach" clause. + * + *
    +   *   afterEach($httpBackend.verifyNoOutstandingRequest);
    +   * 
    + */ + $httpBackend.verifyNoOutstandingRequest = function() { + if (responses.length) { + throw new Error('Unflushed requests: ' + responses.length); + } + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#resetExpectations + * @methodOf ngMock.$httpBackend + * @description + * Resets all request expectations, but preserves all backend definitions. Typically, you would + * call resetExpectations during a multiple-phase test when you want to reuse the same instance of + * $httpBackend mock. + */ + $httpBackend.resetExpectations = function() { + expectations.length = 0; + responses.length = 0; + }; + + return $httpBackend; + + + function createShortMethods(prefix) { + angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) { + $httpBackend[prefix + method] = function(url, headers) { + return $httpBackend[prefix](method, url, undefined, headers); + }; + }); + + angular.forEach(['PUT', 'POST', 'PATCH'], function(method) { + $httpBackend[prefix + method] = function(url, data, headers) { + return $httpBackend[prefix](method, url, data, headers); + }; + }); + } +} + +function MockHttpExpectation(method, url, data, headers) { + + this.data = data; + this.headers = headers; + + this.match = function(m, u, d, h) { + if (method != m) return false; + if (!this.matchUrl(u)) return false; + if (angular.isDefined(d) && !this.matchData(d)) return false; + if (angular.isDefined(h) && !this.matchHeaders(h)) return false; + return true; + }; + + this.matchUrl = function(u) { + if (!url) return true; + if (angular.isFunction(url.test)) return url.test(u); + return url == u; + }; + + this.matchHeaders = function(h) { + if (angular.isUndefined(headers)) return true; + if (angular.isFunction(headers)) return headers(h); + return angular.equals(headers, h); + }; + + this.matchData = function(d) { + if (angular.isUndefined(data)) return true; + if (data && angular.isFunction(data.test)) return data.test(d); + if (data && angular.isFunction(data)) return data(d); + if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d)); + return data == d; + }; + + this.toString = function() { + return method + ' ' + url; + }; +} + +function MockXhr() { + + // hack for testing $http, $httpBackend + MockXhr.$$lastInstance = this; + + this.open = function(method, url, async) { + this.$$method = method; + this.$$url = url; + this.$$async = async; + this.$$reqHeaders = {}; + this.$$respHeaders = {}; + }; + + this.send = function(data) { + this.$$data = data; + }; + + this.setRequestHeader = function(key, value) { + this.$$reqHeaders[key] = value; + }; + + this.getResponseHeader = function(name) { + // the lookup must be case insensitive, + // that's why we try two quick lookups first and full scan last + var header = this.$$respHeaders[name]; + if (header) return header; + + name = angular.lowercase(name); + header = this.$$respHeaders[name]; + if (header) return header; + + header = undefined; + angular.forEach(this.$$respHeaders, function(headerVal, headerName) { + if (!header && angular.lowercase(headerName) == name) header = headerVal; + }); + return header; + }; + + this.getAllResponseHeaders = function() { + var lines = []; + + angular.forEach(this.$$respHeaders, function(value, key) { + lines.push(key + ': ' + value); + }); + return lines.join('\n'); + }; + + this.abort = angular.noop; +} + + +/** + * @ngdoc function + * @name ngMock.$timeout + * @description + * + * This service is just a simple decorator for {@link ng.$timeout $timeout} service + * that adds a "flush" and "verifyNoPendingTasks" methods. + */ + +angular.mock.$TimeoutDecorator = function($delegate, $browser) { + + /** + * @ngdoc method + * @name ngMock.$timeout#flush + * @methodOf ngMock.$timeout + * @description + * + * Flushes the queue of pending tasks. + * + * @param {number=} delay maximum timeout amount to flush up until + */ + $delegate.flush = function(delay) { + $browser.defer.flush(delay); + }; + + /** + * @ngdoc method + * @name ngMock.$timeout#verifyNoPendingTasks + * @methodOf ngMock.$timeout + * @description + * + * Verifies that there are no pending tasks that need to be flushed. + */ + $delegate.verifyNoPendingTasks = function() { + if ($browser.deferredFns.length) { + throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' + + formatPendingTasksAsString($browser.deferredFns)); + } + }; + + function formatPendingTasksAsString(tasks) { + var result = []; + angular.forEach(tasks, function(task) { + result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}'); + }); + + return result.join(', '); + } + + return $delegate; +}; + +/** + * + */ +angular.mock.$RootElementProvider = function() { + this.$get = function() { + return angular.element('
    '); + }; +}; + +/** + * @ngdoc overview + * @name ngMock + * @description + * + * # ngMock + * + * The `ngMock` module providers support to inject and mock Angular services into unit tests. + * In addition, ngMock also extends various core ng services such that they can be + * inspected and controlled in a synchronous manner within test code. + * + * {@installModule mocks} + * + *
    + * + */ +angular.module('ngMock', ['ng']).provider({ + $browser: angular.mock.$BrowserProvider, + $exceptionHandler: angular.mock.$ExceptionHandlerProvider, + $log: angular.mock.$LogProvider, + $interval: angular.mock.$IntervalProvider, + $httpBackend: angular.mock.$HttpBackendProvider, + $rootElement: angular.mock.$RootElementProvider +}).config(['$provide', function($provide) { + $provide.decorator('$timeout', angular.mock.$TimeoutDecorator); +}]); + +/** + * @ngdoc overview + * @name ngMockE2E + * @description + * + * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing. + * Currently there is only one mock present in this module - + * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock. + */ +angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { + $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); +}]); + +/** + * @ngdoc object + * @name ngMockE2E.$httpBackend + * @description + * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of + * applications that use the {@link ng.$http $http service}. + * + * *Note*: For fake http backend implementation suitable for unit testing please see + * {@link ngMock.$httpBackend unit-testing $httpBackend mock}. + * + * This implementation can be used to respond with static or dynamic responses via the `when` api + * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the + * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch + * templates from a webserver). + * + * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application + * is being developed with the real backend api replaced with a mock, it is often desirable for + * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch + * templates or static files from the webserver). To configure the backend with this behavior + * use the `passThrough` request handler of `when` instead of `respond`. + * + * Additionally, we don't want to manually have to flush mocked out requests like we do during unit + * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests + * automatically, closely simulating the behavior of the XMLHttpRequest object. + * + * To setup the application to run with this http backend, you have to create a module that depends + * on the `ngMockE2E` and your application modules and defines the fake backend: + * + *
    + *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
    + *   myAppDev.run(function($httpBackend) {
    + *     phones = [{name: 'phone1'}, {name: 'phone2'}];
    + *
    + *     // returns the current list of phones
    + *     $httpBackend.whenGET('/phones').respond(phones);
    + *
    + *     // adds a new phone to the phones array
    + *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
    + *       phones.push(angular.fromJson(data));
    + *     });
    + *     $httpBackend.whenGET(/^\/templates\//).passThrough();
    + *     //...
    + *   });
    + * 
    + * + * Afterwards, bootstrap your app with this new module. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#when + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough` + * handler, will be pass through to the real backend (an XHR request will be made to the + * server. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenGET + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for GET requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenHEAD + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for HEAD requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenDELETE + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for DELETE requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPOST + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for POST requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPUT + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for PUT requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPATCH + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for PATCH requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenJSONP + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for JSONP requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ +angular.mock.e2e = {}; +angular.mock.e2e.$httpBackendDecorator = + ['$rootScope', '$delegate', '$browser', createHttpBackendMock]; + + +angular.mock.clearDataCache = function() { + var key, + cache = angular.element.cache; + + for(key in cache) { + if (Object.prototype.hasOwnProperty.call(cache,key)) { + var handle = cache[key].handle; + + handle && angular.element(handle.elem).off(); + delete cache[key]; + } + } +}; + + + +if(window.jasmine || window.mocha) { + + var currentSpec = null, + isSpecRunning = function() { + return currentSpec && (window.mocha || currentSpec.queue.running); + }; + + + beforeEach(function() { + currentSpec = this; + }); + + afterEach(function() { + var injector = currentSpec.$injector; + + currentSpec.$injector = null; + currentSpec.$modules = null; + currentSpec = null; + + if (injector) { + injector.get('$rootElement').off(); + injector.get('$browser').pollFns.length = 0; + } + + angular.mock.clearDataCache(); + + // clean up jquery's fragment cache + angular.forEach(angular.element.fragments, function(val, key) { + delete angular.element.fragments[key]; + }); + + MockXhr.$$lastInstance = null; + + angular.forEach(angular.callbacks, function(val, key) { + delete angular.callbacks[key]; + }); + angular.callbacks.counter = 0; + }); + + /** + * @ngdoc function + * @name angular.mock.module + * @description + * + * *NOTE*: This function is also published on window for easy access.
    + * + * This function registers a module configuration code. It collects the configuration information + * which will be used when the injector is created by {@link angular.mock.inject inject}. + * + * See {@link angular.mock.inject inject} for usage example + * + * @param {...(string|Function|Object)} fns any number of modules which are represented as string + * aliases or as anonymous module initialization functions. The modules are used to + * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an + * object literal is passed they will be register as values in the module, the key being + * the module name and the value being what is returned. + */ + window.module = angular.mock.module = function() { + var moduleFns = Array.prototype.slice.call(arguments, 0); + return isSpecRunning() ? workFn() : workFn; + ///////////////////// + function workFn() { + if (currentSpec.$injector) { + throw new Error('Injector already created, can not register a module!'); + } else { + var modules = currentSpec.$modules || (currentSpec.$modules = []); + angular.forEach(moduleFns, function(module) { + if (angular.isObject(module) && !angular.isArray(module)) { + modules.push(function($provide) { + angular.forEach(module, function(value, key) { + $provide.value(key, value); + }); + }); + } else { + modules.push(module); + } + }); + } + } + }; + + /** + * @ngdoc function + * @name angular.mock.inject + * @description + * + * *NOTE*: This function is also published on window for easy access.
    + * + * The inject function wraps a function into an injectable function. The inject() creates new + * instance of {@link AUTO.$injector $injector} per test, which is then used for + * resolving references. + * + * + * ## Resolving References (Underscore Wrapping) + * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this + * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable + * that is declared in the scope of the `describe()` block. Since we would, most likely, want + * the variable to have the same name of the reference we have a problem, since the parameter + * to the `inject()` function would hide the outer variable. + * + * To help with this, the injected parameters can, optionally, be enclosed with underscores. + * These are ignored by the injector when the reference name is resolved. + * + * For example, the parameter `_myService_` would be resolved as the reference `myService`. + * Since it is available in the function body as _myService_, we can then assign it to a variable + * defined in an outer scope. + * + * ``` + * // Defined out reference variable outside + * var myService; + * + * // Wrap the parameter in underscores + * beforeEach( inject( function(_myService_){ + * myService = _myService_; + * })); + * + * // Use myService in a series of tests. + * it('makes use of myService', function() { + * myService.doStuff(); + * }); + * + * ``` + * + * See also {@link angular.mock.module angular.mock.module} + * + * ## Example + * Example of what a typical jasmine tests looks like with the inject method. + *
    +   *
    +   *   angular.module('myApplicationModule', [])
    +   *       .value('mode', 'app')
    +   *       .value('version', 'v1.0.1');
    +   *
    +   *
    +   *   describe('MyApp', function() {
    +   *
    +   *     // You need to load modules that you want to test,
    +   *     // it loads only the "ng" module by default.
    +   *     beforeEach(module('myApplicationModule'));
    +   *
    +   *
    +   *     // inject() is used to inject arguments of all given functions
    +   *     it('should provide a version', inject(function(mode, version) {
    +   *       expect(version).toEqual('v1.0.1');
    +   *       expect(mode).toEqual('app');
    +   *     }));
    +   *
    +   *
    +   *     // The inject and module method can also be used inside of the it or beforeEach
    +   *     it('should override a version and test the new version is injected', function() {
    +   *       // module() takes functions or strings (module aliases)
    +   *       module(function($provide) {
    +   *         $provide.value('version', 'overridden'); // override version here
    +   *       });
    +   *
    +   *       inject(function(version) {
    +   *         expect(version).toEqual('overridden');
    +   *       });
    +   *     });
    +   *   });
    +   *
    +   * 
    + * + * @param {...Function} fns any number of functions which will be injected using the injector. + */ + window.inject = angular.mock.inject = function() { + var blockFns = Array.prototype.slice.call(arguments, 0); + var errorForStack = new Error('Declaration Location'); + return isSpecRunning() ? workFn() : workFn; + ///////////////////// + function workFn() { + var modules = currentSpec.$modules || []; + + modules.unshift('ngMock'); + modules.unshift('ng'); + var injector = currentSpec.$injector; + if (!injector) { + injector = currentSpec.$injector = angular.injector(modules); + } + for(var i = 0, ii = blockFns.length; i < ii; i++) { + try { + /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */ + injector.invoke(blockFns[i] || angular.noop, this); + /* jshint +W040 */ + } catch (e) { + if(e.stack && errorForStack) e.stack += '\n' + errorForStack.stack; + throw e; + } finally { + errorForStack = null; + } + } + } + }; +} + + +})(window, window.angular); diff --git a/test/lib/angular/angular-scenario.js b/test/lib/angular/angular-scenario.js new file mode 100644 index 00000000..a7e34984 --- /dev/null +++ b/test/lib/angular/angular-scenario.js @@ -0,0 +1,32287 @@ +/*! + * jQuery JavaScript Library v1.10.2 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03T13:48Z + */ +(function( window, undefined ) {'use strict'; + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +// + +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "
    "; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
    a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
    "; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /
    ", "
    " ], + tr: [ 2, "", "
    " ], + col: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
    ", "
    " ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted
    , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
    " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("

    +YFG4Kq z=aNA0cV-@sit*tgmy*5oWwTR%DU@I2z|Xg;5QPoq_7ab4UU{PwC$(_1A%1gHPaOsk zZDl{JnEqh~`un=6)<`wUt$I>RjG;IuF#yq2lda=5O$Es5fSCT6_4fsXk`mCa-2*C* zdV%TVk$Q}e7n33DKkZ#KZQ6)bV64(2Y<(F8w!yq7FL!o~7wm{y=hFnF%=|;$Dpn|= z?m`IUkX|nNxKGhhPdoVaSf?n&uEKwinD36+kpaN;g#;W*&U1=_sqLH8OuZm;f5CIj zwiL6xZ!^haj)Yu849Hke$*o_YFtuP53$E16d_Ld%YFmV*UMGZX7Ku*i;X*^ZR}q%l zjAOEf*WpY4uD+Z>f|oZ~BZX`>1H2$OSFy9xxPyq_( z95>d-`(PX~ha0yd7z~T`63DkZRjX{d>mDze(VWw&)Y{2Gk_Qm#BH9ZJ?FiY30ZKUy zL;XL>WZpGRxR_rtI12F*8J4f{c{X}D#-`Eu#vJAo)EgH^a zA_2PWE@ntQK>1k(r4J1t|2J(u6Wj|N2Mn2p-_-0dw8V`OxZ9W;oTa}=$DhWLr!ZzS z`cza7p!P4opf>x&!q>6-bAeF#-JU=CpTTsMx|JA}%*harU^Rpjry04$1wz}Xvk=aP zZQW_LFj=nvyl5??UD_ti2ZRz=GBh!G1tA+qhgY=lGP|+S2pxaWI#JmK;rw(28 zrnu$cM1oj<-2mSi&g$265Hz*`jQ?pqRE!^+K+JRwD#-dm1;3Lt5(D%lP<-Rs+q-2u z3y*E#?1e)`(Z7W67MyrC_&c97ei=Hm?#!Ax+3OT?iBDAPvk7-hA~~SI(0Z3s=#Dzz z%(l)3F(rKb3cfB`xI72_o5|Xeb}nO043g(=If@Y`a@{A++wo)P)em*6nZeaSc=8F6 z(wcP@2fO2SSHUUK23;-63Pdi-W?8wN;M3RPpLTOn|DIy~MS9+NNlu9$ax7b;mOA)6 zeu0}U3sSFR0-n49F|l9g%a)|H`APigv%<4A!d@$ZXasuYczqfUUOQ$R8(Q6sVj!b- zZ>-lIi-piRGdnTu@O9jBU7oXg1+}KCrMbONl|=Q$iIkK39{4L*OTf^X?06`s# zpz&whU*O+QhWzd#@DLhm-7Hz%db8p-8pa6wmI(%g{k*t;g;?rsm)ajdbA=^+cQ6_+ zJP+C68BXWfknZ!_qF1b*DG>t2sDXx3k2jNCk*6%NU^hf-7D^3~HSzT;%NbRDE{gn` z8-hZFI{7&aT>?_2J~FCs`3aaOmx&=3iBqBn9#%2`ed5teb*Dr;A9nfsD9G>s4B(&V zeED02)%eEjHI{l4mlQ}?8yhp)ck^(_j%AC;6JiR`#cJ5? zu$Xa<`p;Bg+r?BCzHg<4p6gSCR3TH~z|ZM3WtAj5j9yCTeFVO+ zC^31OZSABtp*R#Xv^ivpOa9Ia)Pj)ve7j~TgOT2ww?q7~ZM{T(HY2T${4I1QdF0B? zgm>-2IvvnaYzb1`lgvz=!Gj(Ltyl_hlMk;MdTnQ3XL<$OE)I}y#w}mzr3J;x)s~=! zl+x&u2hq9N@f<4Kdu7CoVYHLr38DudCZ=U|i%oGvzVoXj*n}H?u>AM6|GavIdfokV zTgm}8r>QPs$_Iu41H8rjKa0`_#tPSdg%iTKzTFU(Z>Vg#(AI@=YlyJr?IdYHABXmo z94Hz5n?ZbsltHPv_sf)H$0jrF%qPdgcOnG|7jK%5N+iDBr4OC(($4KwGE0ct2I&DcR??2Y{;Y?V$g>BReC}411w4FqwyLSKEwmDst`rM_qN-!S|P z#$RclLsYI_XZ$Oz0e=DB@OxkQ;x1Tw0y&Dtxd+4r=te+*iqaham7{UB#gWTh=ZL@= z(hjbzkZe0yhLwF^HZ2=KFi~VmWTwQMZl=9>y{RRC3xfB@&>X=?c~`>|R=O|fQO4PK z`|Zv7UJ*2Ll(p1N5hIiI$J2VRPyXoL7D+TgamD>yzv{Bs5?)NZDXc&4Xg4!)VCKW zD?K5ZkvJA-q@Q4mh+9Irg!1>6%>dh#y9g(iQ3vHtLN7q{hMb<29xVXE!ySv-qG!BCf?(PnQySvNa?(XjHFu1$J;BfiQKKsnxH|~v& zSkXVbYgJ{vnfYWUXX)|LBLdkFW44Et|5!F>vSe++lR8UqHU{m!ZF^_ zmI~n4gDP7!->@u2skJ)hkIC+N5BRWo73X(TGx`iBOZtYpxiHzw9rUIhd?E5O+-q4tRXNEW>o`$F{QW-a|DYz(j3*ir&6R(Dgpy0-xsDUy z66kw8wBPmt)DiH6RT-%BNGLV9c$YQ)aV{b-!2+wnjy?+T4CNMqoZ7FTqjgU%6{Itv z_)LuTbIq1=L|rJLm6`etezN*WbQNTXf7DaIxAi3KO7NCKvdTP3MrtSWiy|E3z4CN%h6}oN5)5kL#+2`olxrOI+U- z7vuLs(X)myZ>E)wPDRzUjZJ#$`ih_89^GJ#RByFGQ^ruw0^|N~74FK3zK#iNQ`1F( z8PHl=>=V~f3aR=(*755q{5mx@sOY8k=Cwoa6^2<$33IpwE=U;r?<`snN{aSPvkBIU z5ZPqQ_Zs}s-;?u1D%-4&obt=g-hrZ!NXudd#*8WA;Nx=KHFMp??M9UZ10}L79@qrN zA9b3&@wAmesr)*ykn#10AK#5}vRniRm-HaNTG0M+FB8lfGK;pxMUz=88(8I@4k{jo z5>5XNUcbNHmy0y9rviv+HQu`r*q(GEk?)899-pd~lm@iiL%a;TdAsF67K6r`4NN^%-fenR2< z<1W!?6yx3VyV4X3c%oX#{v0AoJxFOzI)nR!cNej}R_u;CgezPh_8#jA@AvrOzIH|k zP>TKjE;ZLu2O^RyjFDL2zI#$+3-Zc{T{v@M_o|>J0ikj-w!8yCNRo6U4a;(`vcm*OW+tIKelOnJ zlddb1r`Re#7uCGhPU{$;`We%jhG*<5(opag%- zot-d6!9T>I+KF`e1#d~f#Dpm^k8g|>CQyo>pHLIjQMiH+5N#=0=2>Q!^uwA0(3JeOmoJ*WArthwu%c><9 zIyv`nnSP8J?^tW>Ad~gYve71O@+eaBP8StsJC?UoR}=Do?&3Q$WJt(!jC~)MgoJ|_ z!hq=gcm;iF*0^bsk)JMI5|vmX^UvnEKRz^FEQ-$kzU;s>3W3xgFKrbYE8I^!RTTHH>i#@%NNtIjwR=gz&&7Q zTiy`A<}bAeU++hP`{i|(64!z7^mq6sK$uy&)!IEee8slm5DdO-Z*qUfJM;gBIXH~G z@r@9!1A(efxU;WdGv+JOkcz_Wu@V6HeKY;lR*q8SunUr3w0H{gjkeF}>38RCiLJJ? z)9bAiLdOoyek%Q7;n6W@zg7*6KH?x?sY+M8-G~YMj6V$QWh*?jn81t+YHtPJb z`}6xQd6xFx@gWHhjXQ}Gw#{a?U%z*A3w z72P1?XRIu{vO)_-95161~EG)4U#}hrES@05Sm` z%)UKSW*O}oI*vh0V$3UFv#i;r25JJW=SOdh-iThBsGA1FtLoj5ZSUu7;wKW~y=B^q zImq=J(z73>1dk{I5#vlP8pDiQ{~c*5U(a6b)~6Hx5b9bJl`&+DASg4B@&;{)Nfp$= z_qzC35Aa+{2l57D8FBBH>F;O;pY*ha#W{iuzTSG!Jsn*MniKvQLu{LslUc|g!!OQ;RZX|X@ z0&j1I`FWbTRStB3zW&`c(!RsiA@kbL7YpY`lK)C$5L&dM={;T=-0-3M6tnlUqG0Ty zE6OV_vIB~_Jf3Mcrv}%_*PAXyRzmajc~*CqPMC@sIm&L#w2as4v7#|>cx$O}!QQNt z?xV+{B@()V+CF2E%ofH-y~#H=J1*`z#u{ zXPB`U!8uXtO(K8lO_X|G_KO@}fQT56_^@%u*v*TsSx+@wif%E+8aQ7%&sR#O;?D{; z%p^U{EWZ_}3InyXtrS?suvz|{Ib1{F9rYB1N5}yOgmJc6I2HwTJ6w4YZn)W#SyjC6 zo~;ch;@FSfMmf+Y0K1qQn9rE$5C;v^|nkQaoSM2kD;VTe)cx zPuT-hW)!|}El4BtkGP`HM|rHL=caUN%a7vb{&0?@Q~r2Wf}aY=(xt}G{JPfpul1uNrju);PVD33 zMgk6<9VPKpSXa`4xSdoEAxol@OjiYoHS5gLc$oFPd`}>WJuO(t^IL;mB&cP76&u84W7D5X-Q8`7Q6~o-dYtW1 z1gtmgTUvEP5wuPg=*PPX4@zgKC{C z&tO(mysf!q;a3Xy6!}rSoIF2%C3mC66?d(cFOy%DkLxc@y3Z5E))JgEm726fRgG5R z??O^I8RG9$<1YWx3WamjPn31mjjzS)0o*zo{?T#D!2M$7$BM{P=^Nuzh%a4+9`7+12)WLufFEy zv%;S;Kx*lz&UV8w@+->sqn3VK-vML2*DW;^vLBZoh7o8fGiL+B4ladyLyc~MQShs! zc~fS(f*VrUI;rtCYm<5s&X7EI#8!-cxl-IvneNSKJ$2?w_V@;VG4}aoRgnwG>-Cqf z_MXVci{WwS=?m!Q0Jo#&daP4-H92;wSjEn+QMjna@__^kw)AVItX#<=B&ZQL^ z9f`)@pf_*C%4SD91psB6*O7Kw2Pd~h2Bos|TTbEhCs|Hxt!y+Bh{@sA&a9@X`3l*( zkxUiZ^Gre0-{k?Mu*qyr4WA0jy(XcyhMjCQClj!P5dw+N+0GjjAq5~dR)yiqm3l8c zW;jr>8O{tx=3FA&+OKCky3ni9H%F|h{>_8!{3g=7N@CSYof(h!HR0CGm?!jp!#f%^ z$RWpbc$DPW&eBOxm!IqKfiWcuGi`@6B$L!{$;Rv5Z zI||I*zJZk`$4jIOV`LtIkUEn`A~HaX%7KTk_DWh-i@3~QZLMC&6irl7!CtBijolA@ ztCs-^G`Rp;$}O@Z_et!EzTG5tl%{s6Z8`yI+9&&Rm(^zOzgEd@PUh}~Im1}nGiaHz zY($AB3I40^I*P|x)ng-;jA^*5;wZdmNlK_ph#K(7~3ULI3tVgm({L}pTumxx|H{o-bJ_4M;gZofcM5rt!JZK9(pjgAwL7K0y zDr2iW@iCF}MboQaZ$=b+UkUUN`jQ((@GL8cK4y!tG)k1lbPzW(ac#Lcv-BF`cN!@0 zZ#q#z4488`VHu`d%fLtM^<^Zl6I}y0dkR*4t{x~f^5K+;v@+6V5wvyFPHLUwAUg+I zTqlSGNIp~>fSn~;jufHkG@+Wih)f%%CV*==Bln=q^z=+(9|v!3?2PLztSHpKG86xV z_;umaVjzBnp>1xyhm$?f&0lG~M&u|oc+9nwSytScuRblpUk%-+-2f7DUvwkDI3}%l zC)VY%#?Rs93;NDZx}sVcB78+(n$!kQ7+?{9q8`q)^R}Ex$v8rDYUmaS6-$><5}+R{ zTxR%U<^sXGqQsVEc;O+LN;W$^4uv<0rMRd^NOUlZNwe$3bfp#^Guav!)Bk2j56%n} z-nz~Ju#tpmj z$la4CZJJNVSxVQBs-80%BK`GO_@5Eg*N9kfgCl_w-Vj>lp_#~I1#B9zOOeIjn(wM+ z;Hih3hIIl(=O{}C;&-zH81n@4#Z@b^(LFx8rnVs_7(58fD;@GRo}-H%?CWN*zZGy9 zzz@XQaVCnkZ7*+M>KaK1@)36#CPJeXun8iy~LM3n4m+^E|17<&4`Yb3B7e zi>l6Zkw~Z5!NV$lHK)1gq|#tujGFQ}8FE|U4h>Hb_2ms!hEk@GZdGc`J7qTt=BF_X z#zs)XIRV!0>!)LK4VIWB*bVP*FV+?Gi~?J;MC3K(IL2sN<)e!szVUMe0w-6bBSr3ns8Flg|~RXFYO(7{2g<9@MULz(s6k$ z@ug$?C>*2yBjFrDR8NOGS<|ol`B+=n+|$LaS$}Jq&>zX)>G|sz{;Xw|R@U$)ElVO< ze(tn4#sC4+_NU7w{oz9#pY}3~adi0xQnI5{z}Zik7T%K1(w7_{i)v4TpYGLwg8Fd> zMg5h>pXc!tUXc&t^)|uMDY!jaG_k^;KeOz^Z7W77N`LdRu_ADUm9hMNN;`$Z2}&wZ}3-+#mhae#&EDL#5xvMPECr$20qNh*AXzy;h=)e zY2=?Xe}<__1^=Rqj9pq zR_?*189$3rlV>`gK@3G!*+7_3s629y!Qn@AX;;ii!;v+LS)32`vC~L09-JNO8Iuw- zYr4cbB$CH~PzF>1rL?6)is^5#-_6bGk;o>YpRSbc+5=dq_+un$d9fibfPap_M!FZF zNg~U0JmsJE&~xl5*%p{{jQu#c@U1fvEmL3|GR2rh`75W3Nm=Fg$9PvOFyf^qiMSxZ z_9D7J+35Mzqwh55kGb#-Eiwjr3qdQ_^N#U%hE>hrPhxh|YCujR8)Z{4RZzAf0vznZ z$ruyoj`o00#DXq_S`?yXU+E06$tmkE;kiW$TW+}uBl~8g#|WUyk|ljGQah| zyV$~C+M_m3#qkvdM4>gTIJq!2E&WDzVpy*9(zOfAsD8Zeh5yOux-N(_*&9+lw?72^ zJFX2Uj1C(4x-dxC)J?{V=iCOzm`nD-(R+{Mn~R&^ZPgHAg)5#O2M)ZKM`}RI3)XZa z#nBi+AnG^}J0VWtHhCMPWJ%K5K0($tmJX ztvJtf>#!SxI`-vf0(3yZi&(0(*Tv7p^YpEcf@{j9th~z76`j_6Y()l0D$2oc8`?FI zBf`U6Fh(X)cm(E$8_FC75T4U&yh;>HZbTus(V3K)mo}WOSmDMvhH>51th$DH3#po> z2NuYl@$bvW#&x)my{0hPXL`^@h-lc~U~~^8J~- zP9NUqZEIQxUat>0f%CMH?P*TvS;M2_*dP>$?VD(OT4WVe!vsLDGHji3ZNPYr`VsSh zYgwIZoE+nmeDQ&jQ&?Et%?Z+fV-;TtTFYq2tGC+j;5Qw)jos-@$TOXD^(iTG6tU1u zt=bih!0K7HbfMVb4=QI$FuS*&J1VJs!|;#3h9cmx!!=U2}PN@}>ATd`ryE#B~A4&mo54K*?AFVbN zJURjJY9@oTj?@F;^k9$IV1~dB9E}mS{EL$~gw=0sRM1En5aaj0^9;_YJU0ti2Q$bM zWG5B?qD5WC2a3f`#;+*gG`~!0gaw&V_f{e# zJ{P`B>j}r~kF1g$Aym#Zu?1t-5RM>=%F{|H7MK1Rnz7$a@74Br9kdNq**wS+m8w1UK#ihz!?c`It{?l=sk(&FlzHfd7?(HcI ziOdTtP7)=zhp=n8mFgsaA6~iv(ID5Jw^rz=enuis(LGJ?l8bO(Pl2$|14&qb1oOUJ z40}17&045YK1miPcmc(>yb24K8AsXvuL7_$ncb$YYcDcP@--_Bs3U*8d3R zg^j=kkh#wE>LMQsT){fj4S05xVb>47KKYmVWe4L_%pe+5C$;qB3x$?@hbq2N}YR58Eh-$}u!!OU3lpNQz^Dp%{kk``o2 z0thKoiSseT@GOt;MsWMi0(v4y{SqD3n@pNQI@``^C4>^r#Yx;?5uAn{Nur|mO}(#|Ygl4J2G8f-NAq|x|1ETXqN$OZ;=M@q@mMe_n!myw5b|5SGj zI5K;1!G?V{GvoYfE?a!4uhxKaXzlR%7&tYVI;{1A`fF&vJn?amnJI<5r`pNc7_qm> z*S=A|v}gdJdR|>9s`%H7(L0>zQU%_P50Gh1uHtF}G}q(Dy9m&io_U34Gv+KTUyr3dl$>jC}u;sN#(ha`E)MJ9o z=7762>J@hXiFqGBP$Zsd9|4i;Yvn=^I=K+NlE*ea)E-m`*zg->0N#|I`fCS3mMupa zcD3z{#^9;RVMA@%4U*bq^mYrS&V8sxI#z5!&k=dPq~M$ZMxVX`SlH4q(g{CS`;x*~6y>b`trhKuwbEx}(-kYOJ6XQpB*y#zSyxsk zfg_kB4TSe6)qSbl`LUh8pCMSb60XxN5GsgxU7bgegKaV6SFfaRd4@_W_M_Rt)Ce%% zP#MMHVuD06VQ~w>$snmBLDtXfozV#rZXRhCfB)g`h*xij+$V9Gf>3PUTYfwvP5S-? z5jZzM(&K5{Bak(tDE+yNX8T$GAYMN4IEdP|ne{*y$HE;P<7e}E@4rCaAHV5NN#@xG`kjr6z@Sg6S43hW6*|@yvJ3&U%xzX*QP?MlQD; ze-2Z0E0+I9xVCpB5_`R5wHVR$JWaJ)4Qi2pO!|vDP(vq*Pi(uEmU0lGJ&-@i4=;)4 z*~!&AVr7Oqq!j*@A!C^rl-{uj6j09PZz`O#HPGnYki%E=OK!<+&9OedX3-d8b#vo- z1VKvhI#76)mXps=$J-$i1d+FMkDCiwJ>D=?B$2pH>c*C+RK5C-Q|gT9vLUvDn^0?6 z;>FHQmVVRkkVNwcQDF^EI>^>M{|j$t+hI^~WDXtvNt->U1{8tG1g`hJXR4e5o@ ze1is$QCgKIq(U5I*;k+MWwVxj*_*~cj8%@)v&?cq`8`utl&oS{Flw8AsZ>6!s&=fv zTEe_E>ddIunJqwyl-7$-rj1{(bV{QKQ_`deOJBNBE4nGG`j<9)lQcTi7R#Mrz3I=t zP>+d9PJwX!g_o2Yp@OIKEakGqEApqXPP}Y*6P@NX=;4ox%H~#N5+NFh3eI~Q6^&0z z#3CE71gfL|k@g+@19tX0Xc%S1*0<>raGJ4OPi5{x$E0jmL6!;NX{UXxpvG(e(@d2; zTGe>{un@4I;~#~_rf@^{?fN_gOrwAh{-f-%(JcmGIuSaZgZ3*>!U(Pp>Y{iv1TmdN zwEpYS`iek396=QKop}k3|Ch-Gq0Dq7n8)4J=NA4Ewh89%3A4wPo2hnZ))Q`HVa`p3IIjfcrq2A~h}r?FIqU+}k6RPmNdYNa_t)#&*56LqW=- zg$<|Lt%O7pUxun4un(w*Uden5RM(ko*?Cq9RebApFFUn!paR8M)=aPpLe(@p`F&7I zX#}s1i~&t~QIsv~6Mn0f6Cze7-fnNTu{aH%h*yb_Q358w>?~OQ73J9Oa-h>L?To?C z_xr)aKFR#2`2^5HQcxqP#_0zgZ8;X}F92fIUmY_od^j#}_G;K>Xl}4%VwOz@uPNsPJ_l-4n|dYSwQKpYabvoju0KWXkoy*0G!QDST>E zvvNodgi)f;X{%El(wwV_$?d--rwIL+`^J<}O^_H}EyNG=yQ`XYHfApV1#_R}(oko* zoS)OE>0gTT4a>*`04vV8oNoCx>*c;xJh|~4hO-!9y8zuXY{%G05VXMDAXWFevm?;t z{;Mv^0cn?zB8zRMp*9LGYwYZY@)@veS4G`FrCH+!sb?+P5d_wS9(_)Z=Gi5f2l?FG)? zsd!8s+ih_0|FzFy75dg~EfFmZKTO6a_4M|=CO6y4n891DgNZ<-3^xQM^W#Tfp#&Be z9bVPLmXzF6icYe&ri-tk?V5XrYG$-})tWhHf5n2%v-b$obM0VRXcpRqXX73dd+e-$o*vD_1k_YnBQ^@-stV;^M|TNLh>* z)yjlszGOpQ$WI1PPQxaXQYjaECp3~KF?6cOS<^&Ob1?N@g=TuVkD&o(9p-3ue!~w# z&(J~VxPjb|b~O24)KCnH^L zQ$rXXkYCt-J)F9;x#iQs5AOc?*dr<6b@a>UIC3}5NR8}UYlW!p?XifgLHDC0b&QL= z-mcTsD+gw_#4Pq}n^O1N$n8jX+*EbkK+A`5-WoWi<6|WpQZ^Yf{{E#-NQ(GrMIP%VlDyTk3%@>gT z4<6<{NioW`yK~&yo#KbSBN6HrBP`NAMow)&R8wr5r z5{W!qdUST9-1liqj3E1M1fIF}!$#D^7gipInq@j*nIASMvSWI3G=L_=**G;Iyv`m? zz)hjQN0;n|hn6Xql>Ku@QgqGw)<9DWF$DXk_YaDi=4LSm=|6=don>&P;t0I)ozeLo zMWSooCk^F!c9%q6&6^lZntY4`c{@ta!$QoAmWP=03O@A8i@r&{G2i2RJx@9G|B5n; zk&Z1oAnU)>_3wi!YHG{q8l7y(43A!40p&LnC*K{;zWN}Mk?Na|Yrl-5NooC^?++u_ zVcv>3AyRB2-bkzrM@TFWw{`8&<4Rih$J_^Zsq;bdI9kvdKBd zr7K0^&kZYItHxxblH`o_{?96W)olb!g3SCcF8&WqJW0s)WSXN*v&=q~AkCB1a(VAF zBF8|UCzgb%f(9;yB_Pe{oeWJ={*vnHlO|nM(P*p<>3v^+i1YrnwAY@q&t+AvE0p?R zXV%DI-aLt#oU*jsu2OukM^=!AmIXr{O9r;|O9Gh`Fn8lg8B}2+)BNM$Q{iT>q>;8=^j^eWRON^h zjaMf$k2*^R|30$tX*rAk^*YiUSASE`?$kx`WzXlS#|zF;(=-6kKFL~7<-L@iN*o{X zx^mIzh6QbrwCFhyEq!3On$0nkMyiuOaQ3c$x^nLmkGa-?RA)s{P%TRa9(n9~zUruO z4%hvVVi#)NaC|q?g=1$d%yds|%bIn#&7-k|&VpJCfIwz@ttLff7Dwr)o<;}5Nq1MM z$&U|J%pq8t)?7<+p8PeWS1u4{FpLy=FBo+LK%Nol)SP0Yfz z7FkyJ4_+xug%31~(UY0FOgibY7Sqo}G!FP{(@+kbgxOT)_#!NP3V-FiwyD64I-}T| zHM;{7>U{M#S~K;^NO9MorY@5R-Yr5-YGt}F=FY(CsY}+AP+S}*3-4?9ywp&H$uBuG zz#0WTD@oQo_Bp}oRvnv-E)AVX#y6CDa=yp!p41B|g~Iwj289>Hx9J}S_g|$77q%8z zCaj7S0&xDuw==)>dDwE;%SBQeCRE4r@`--6@qZN9gGoqwwF=KUvMgfy^K!Pmq@yo( zT5Nbp)Yhd9$!ChQ(H85xyT#)uAQFlKLwhcH-3Ryuck!t z1Be}=M1sThnvHIaBPnQUsgn^wVMYF3vG=(*Vg+nw$;xK(V2EEA4{6DYFxl`wRU2Q5 zkKIz< zjrx;vsdAv&uImlybV8dpc`RBp``lZ_yHSY*hj_Hhe8p5XUe^FNhTH@rwvk{_*cq-Q zF%tzMtK?b$<$BXsEkNgd2!=}MBn%v8Fv9%4`$ui6*m1;V z<#fMSX$0POkY~UZg`Lxf7gVq8M5hCV$9tsheGnK1vWpy2s(UZnw{GmZ3s1CU!9j0n0-GOo@M`4qO=apdIKO&JEL#%Dez4?cACAT#yuFCQa z?H$o*6w+~)^zV`TBr+1<1d7TY?OU=WyzuZf#l1?`Iif(V2N9_Tli_zl6iFTGs4L-X zcH!rQ7Ln5=C3~ly!sD!e7-p)?^ z)_L}|w)8`Nci@mA+wIQmb>`l&pSsU>RN6Zu+TmG6#tvQ`Z54s7QO>Ps9njMaruO>Efb;( zbq)^%p=#2{q^PTxuD^=U^AE@H-=QeH^ud5DQW4crUcwkk^U8g}DGW0((IULSeYY=A zt^FgVqbZ{W{`A)5jm%4nraTVG z!#Pr^C;*p8?SHj8v6(R+4(M#DM&MfnVOgyLl2GSDtQU%$_$qr#P=Ztkn*th6Ghnjy z`LEP^bvA%}Bu!9=F;66-V2*!R!{JD1dU4c>sE_UtWE}NJ|0_lQ=jiOpV}+>f@MBq< z>|VPo!H+UZbTWP`gY=raK5jIJ?^}y!@G-n~c{aSL9?fj9e4eS2PDHfpS(>)z$yhH1~n5 zZ^gRoks=`tRclld?*tP^&vT<}_937w%OdjOo3cJ_9*~_;_OU!w>{mPkS{yk7z z&}jjNHME?D&Y)~3Y%6}l7pUE@59?xnm=M6?c-8xzUj}*@CR$^oNxZdLtP|O$e>Zf7 zOax+_tZ$s@(HV9NE(`NhVwh(D^j)*aJH6-T>1&%=UQcWwxPZ2Z4lA_?>AHdo-U7Y2 z;ZZzqg)O}OX+ke~5HE9+ND|R!s>VxiB}r6%_8YhT6(!u>WPq*^Rmet;~9=7FayZ(I$U1?dFg{dS!7O9+r%FiYaCV z@TZ7vHQb0;5p>R3Zv0-BGJkN8uJ`9t!ey3~qWSTVY+MB|S&)YTEd*5-nrXN#B^7u95@l^@`lwPAMv$9Ag8M05C$TSSs8F;OXcSeO)V`Hg0I1QGW^}s z(Njszp@1a@1tZAaHsq~Mi5mHdrSjB{IcYAd+(zYx&U{-HBc(Xubfb(Ro_Sr}#Qob> zdvsy?GAS3XGIz-M^EO3VI8szM0vGjQKRd78@5=L$LSIF=`PID$Z)nxuGtf?$tl$|@ z0{+z_;Gbs~Ez9fY>*q)Jd)40EfP4??nG}A$<|0W{o20?*jBC2iz^UzFBe2u=D@m3} zlXJ5THo_la;B@m;OIr3a;teT7^@r-e#`tr)Lv9l?M+q9t0( zTgl5GJV6q*Ta(_E@DbX!5oMV0*9gIi*Rw*?YzRr(BX4XHI z=!_5UW1ZH=ooz(M-rM&*R8aAnnqPE_;0!{bn-p7RwzIfmDUW1AF7FjtfMMZ10$MBD z2DL)-LG($o0p6q)X6zwb+#=R_PcDIJk&G9^olRDH0vZv0GutNVmgUAxL1pr6S$^F{ zj!%1{@unANyv~OA=#&%&4$D#tjyf8{d;&~;spJ_)xksX8Hex055(VG2;RY}7Rr}XY zeDGFl-V!cutXZ^FPq|<}nuGGOSROAWXL{lOl9Y3LxswiL3U0K^@ul!H#)u>NqE!{% zMfxG^H^1UyihC_a{n{IFRLhi}$&3Qf=3z7VzZUP4#R$R0s{nwW*P<1)t_k`UX{@IX zJSOdIDKb5b=~g3{A;Zv_p8T+&R2r8u>b39DYEfAvLV+nDJjmRhMN87+@+6AI_VULv zO^#bO)n(w!U%VS>Qo^qQf)!to(OI&@dcj7WS9iQHgyPR@rwLjYL;=l$>g?BKJl$m} ze6XCt_d>bOwsapvo4#yj*9xGgtS;9U$fTgz)TX|lBQ1=6WtGB{oQ=j;3p z%=70roT~6v5R!p{%cXTLZAm<2H%^C`<2`#;b@A+U$28@gf8^Z;9#tc>3I@79h23J< zzvZs&h-@dhJ*qn+st!n32d17#YoQ>DK^XNcIIsHrR{%RDiUz2|npvCV>u$rPuR>cV zfZ#xQ7tHt?lvGrEhsfE<6Sc+Jw-GO=K)akyFoa{$Ev>vskW#02st=G$7#W5HR(rf3 z%p-2X{FYiy`C%6{!ScgZQg~l!?)S>?d6u06okhiR=#0x7Kb2cR$S^cA^i%tofs1BA z^utBr>U^ox9+X6ugVL;*Mr!^gE2tdUGRy_*k!2i|{VC6Qt>5)+`@%KhreCJqWNe`) zG8y2BE?RHx0<2%K3B0h%_t}?-PN*}pAG$ctzpo)d6KrW)c0ZNOv^6*pA@VmKn0p7% z#^y6JBQ<{9V1%6oe~H|Gq@z=a?~eGO8BM9NE!_Gf>sJ?z%QbUjLE%2zanvrrE4eA9V^!~^{8b~Tk zih2r(Z2rrL%*L`1X6oF#9dG4!P?j1ivQG(arQ$A*{JC)-Zq+0c+QyzQDv~8LC9m6# ze?nFbj{!BPp;%r9L?BzYzzA@{ZX_mTaH_tP*GSENfJ6rB^VZDBO@WekktQdk2;u6& z5=lDB%R&KvlKv>Rv#0sJO)jRPTZ4dA=I0vws5zmTXp z*&N$!{Qb2DZ4U_q3gI255GT<^(rdxbOA%06q$STX`u2jn7eU0IuCU8G!-WtQR75Y^{PbT z-U;aQ$B`hhaP3+KY#VDNChU*|M?*}*;^eOX@W5KMPqrSXN~I|;VkM#{wHQzxAXRaE z*)2Y6tQ;h^zg^r(n`HpDVh|p+EdOiolwQ#&okYj# zI@am=wW1KUK~j}z19acZ3pY`Z$gcNIwiT@A});y5?VJ?2f0S5q6BL|wNcU()0 z18Z@WZtqk$>H6a(t~@MA86pjE$3L=_LF|01dD{@l#nA8&exjpGb<6R?o-!yDmRkYvs8 z9hQk$!GTtKg0Sr0FC}=J_Gy^?cPq7K#6gQ!r!Kk0v{n7LR1p6iT>t9EhaStVfIt0_ z_caETwnIR1@R7s8%hiV-6%I1fh)(xKGrA}_cB!+Zpa~}eoOGDS-nbtaPAZ7{`S+1? zEE}>m%LTIt43&d9616QXJcwZYD!`*vQe9-tvp7eKen3{>7PTJ_%j@(mlGYbh=6`u# z+X|Any6Cp&PC!ztPjDY(2eF5o@&E)7Y&S{NnVbl~MpdGk#FiM(7rS3BFj|81ch6m3 zYT*SWjd`FyQT5O~bc!XP@{)crD8Xr|4riEfwetw?+0^snqAj~+~}Eu-`hZtb|A zMf)AD8bnd2+<^%nu?^Az-&rCf?X|o)ZnJ(XdQe|&YUCu={vM@v@$`n+5zVmiUqQ)y z1L6L6QSDbC^B?v>WM`M;?E@g>WR-RX^@)|I7~V~IsMXyXH-kFvRdGaA`rR$(jIB~Q z>gytKQGqvWNl3!&GZEk*8Dzaw@O$x7fB0e5>+u=BrO5N-)#fU*riw4!*_3!a`C-{G z*KMF8TF|)J^*Kt-=q_X2iSyDU5Mv91Rf^Ygk6BUSo;CUnE*WX36ND9=*wTe#QE0Tq zAqrV5a1Ac{0*?0p7-Eub70pElXw5K4qspp2dNXLxH?S}_g!WNMDIexYXc?FUI;Z+r zMDpWGmEj1i6ey!Rxpec~rHj+-t?e>rGMP8Jq8Eu*TNs@SFHmbEF{3DpAWi&NfBWrW zOexCV*c_`l=SBp3)9&utrpT1{-wXRIyXKp=qTcz`@wvqETb=UQvb0o8-Evo%+@^7~ zc1SdR6gJSjEA|J@8^&4UGvC6_uT*F^2}eUG>$nsN1G;l2YNS8StV+qP|^V%xsi`aLzE&{GyL66$GG z#2}Rg2GF9&nlC+r5a&#^0+$R5v3@XSW~E*R#LZD?t4P(|wztMinfI>!E6Ruud%6+u zcW3k-nQ$8O33>feJI@oF@&@?-2p9?~(L9|L5NRt>KsuuvFF=icRS{c&Ox>Y+G~wegNdkWW?kp|WPdQ2d zaf4kkoA_kvwnDS>Dn?vUMVKi7D9I=gdTeRR{c3WBW@K%J5P&lxxdg;mh)LmGKX!ll zhX;>(z0_Q6T4)boDe|VaYhvRd(R&T&F{mO-*I@f3QQj_TraM^gQTrVFM87Dl%3%e%0aH4iJj3m^N)Sw?R36zFRN-C^_V`L=wle2p>WqEB z&&p2Bip#Hu{jz@z@s}%+ggU{5BsI{XPA0aqmb4^s=1c2zi|3)#KtS6b)m{fmY;ZiJ zQPWY-5NMWFK*?9crGSXM;sn0LBLk}yT-TWg?}?8*7HyMJ`s7aajuvc}7J+dUcR3=; zqNz(3aJBv7+FW2Ca=p_}T>DX+apst)Z+{g^ijDG(2Xu;vW>yHXc>P^~(=V&4DTuBP zr8fdAczQaZ$S>L2Q=XApY?|`MWit%?54C=JQ~=nSzTCbNC{o)#z_7r~V={&*opz^4 zKjrT=IK*)11_RKQN^UZrUS;NH1HP2@St6sNnF||3jZA{jX ztmc5h7&x&!yLr4&v;!i3Dl#R=MCde`9f^!jXe!9qDnGoX=Co8&PiF}_B zP&M%9O<>v?I3GrMYz|dF6vdnC5r$F!vlLZDyPR{OUg;s@3FO8wyRpj=QBAWK^(vCb z@pPq>w$A>8OJ0R2mPC&vPCsNS7tWKD!6JfDcjs$NoEwj5@vS_xvL1|5sJ!W!^s_v} zT_43zhA`q#J>CJhK@7JAbl%f6Ay-6|VrB6sxP5dK!J60;=vD2cz5T6>!LN%Y)b34t{y*tD0s6_g?{Xx#J{0eM&v+a{d*E;R=gwM)$Z%$ z7~7^7sa*HUS%$}mgI-7&^GH` zAepCI*OheR@ox`^?nRZs>ew9{#3e}U@~(AMY9bd|J;PSC^zTxLa56Pu9S^6$tE5GW z9FP&18|tHM9X56BaF4ezm(~SVE?s(|O5f64W)JiHsKPMdSwNeqwwLtaAgjX6j1@CE zp{Ns_I!v{oey20?nzgvcBrXh*A|_D6D}&MJ+m_MQdJw8F6fc+0E1=Po-_l6wCNWkR zmFU9(1ntd>Yr(|71K$>dlHNO)IuP_kbxZWx;+D0SBUYM5LboBR9sKJ`1P^>K;*-z< z$4yE+lzuBKiFo)#FTQn7q~;9n|Jv4N%xpyg+4274mXJT=)?M2lH^|vfv~}qjjW{L| zT6%?GUU8kQ16qaBIuX6N7AkW(#C-MjF_(}G(%k(_GOwSG1cxH7JPIa{oUE1bLG~Aoj~{KswuCDQvpBDMk&F3OUFkJ1rN3aEV>UeT!*60N|VY+##K~gCs$e0kU!H; z8QCV4vIEHsY?Ez;^1Q{7gk9BByG^fu(QRfT=6on)8f#Q3Fh+$4Hr2SE=e;=4&ah!# z{wGfF@vy;4?d(av!YiTc_n*bYT2lAidnZ)}*n_1># zoJl8E9GmMAS-EeqfvEN-DVCD|R^xDxG%Q`<3>T^G;`!VV*A41oR=IT*Ai!uA5-@UWBmAKJ`C5)sZ zFC{-Z`Ia8XE*+Fmc4ig1PJ}J3yX-`<0cIhqPa%pzR zq5I&t4pk9N&rtul7tmEQgw7duN_M3z@ji>48$N_p_`eqaB!u-{eUvtlT2&I1*2Z84}dro3b zoqnICyR$7KkZkTw9LrvyXfl)958*%It3@#Zji={??IVS{ZW-r@9t)R!Ka4_F8qe40 z|EBG$gj!?XW|m7o{;KbgYK@*ID&9}(^19IyCSZy6eL+NVW{ie%rS=h0%50)_D1Yv+ zbOGPD)Bu~zL7ezXu^hrtCbgP0ja&08hrmv-LIMPNB`H|)JLS@@U&W_MUsA6YIj5ud zx^K+#Wcy}`s{Gl4`EL~@FVWw2jnuJ2)Y)b-ItW7bmjntiEueZ8yK1u1OXjZopfJYard630Sjm*43+RXxhs zesynpgbcpiBzOe-HG}Qhzgx6LJBdOqVNi`7x zQIKvb!g%PNR8)pUblsoe{IB}z|M)*2NNT_kKleLuq4mVaM|GXR#jASZe2|WK91eoJ z&;HJ%f&dve+;2^VI?25IMqgkvDMuibSq&t)jLUgKt{mcM{7W)K>f#Q>k_HkUHY#Wh zE#sJTnzL9yoUgY)&QSxK5XBgP0qPJD?$>4ve#$S=G1caFKXx@XiVt`Yngj zN5W>!gx+G`9vOT*`+p5l_>*;WyMzSAJo!8ssp)4aMJtU|SqizNx-LUqSM?ui(I+9T z?$gXkkQ}$rOHMgI)nOB2H^Rhp>PvMj$cT%79qTd?H_t&&5R;||*t zkWeVXD{OJ!)rk!lLePuY3SRmuxU;Y7H=PE9$|HX2x(tf_u+&56gcWZ8&S)9g&Tk!iWCep91c_q!9}lA#!Slnv9c#ePN`&2z1wx4 z6q{^Ka1#e4LN!W~7s&Y0F%!55#0S+HAVj80wY@2|SB&~-YDoWg(8SKjca#K&K5gn| zW(zqgXCvEjm#FLULS&pjM>>3&*WyZevcP)o1iC75I9cO9jUQ{SJNG?EO!;ytgX2iHN*hEqShYR99kVG?=*=K(19@MbkP5{JQj}-r zYiHI6D4|~D?_Y{H_tA&jjDHWX-l~M>#tuqvkkj|2l6rbO@Ggva{q9h#qKktpj~MW! z`QY?+zW=jmp}AY*4F(r;{6LoW1(AjOQX2eSXv${?LdZfY-*9LqG=^(Qinn8$MrelD z<>ge{2iuvVElnb8R6PJiHAv4#$G@Vbi!UA_ziE2$bdg+}mU~u>dqkW(0s&0&ik)3L z5P1M)8oXS|NsFyxv@&LBNV{NzU}Qn74;S$dW3QmuxwC`!0?Yww6$TCD5|8Q;PtueO zhhYoLRp>A%sR5Rj@_r=W+?{ZeD;u`+^YVclQVdhVI%-65XW42x1eYgc%py-iF=St5 z8Y_(Ajmt93KF^%!I8e31!s>_&A(R{BK&#hWtbPK4E9PhL-`WNx_SxZBKUx>M|!y_a)EGMLJqAgot9F!)&MTcaE7s zdvO;mQ;5uuv}Jt7g<*e$_hushdFBEkLe3qaxPI2M$i73KQ?YK>QX1Lr?%LV|3>U}G zUy4MHs`Vjb0MRW!K;OISN6nI&;fQ7cF*!q{2cHe*UhB^h%%3QNC-|?FJ$Kc@pZL?} zqh7(jtf9ZF?^1A^a&l7+6wur;2_w@%eJDDK(AhEh$DplC=>_c*^}(UV}&b1Q%?Dl|9(7Wp+gV{oHsz~Xp;*}K0u?5N}c zczncc=#f1jrS?&(;_iK0oFb7??}rt)*lOYpkuf6qRvNw;Offz*8*M=~@DHy*iDG+L z6Ut2%W`3*}XO#i&zxbXnjg{>AajwgckZWNx9c=J>k0*w9VXDBne3^ZsHheq;CXAz_ zcvlT)D6!}k%p-=CCnp9FBdV?8en*GIAxg9{mab)U@R0fHekPdX=DoQ?@$SlT_28MR zczw4OmNt9j158l!x;x+TQ&kBwT%KBAjQ^mlYpD18!P$j@CeO`5*m4wKh7njiXVwuK zT;t`u6`j;!vvePRd{-F-ZO0_dAuFQ82mA+Q4aUAXzaXRJkV6|0oA>GyXM-lfIriNR&m zqzZIDd(ldRw(U`S(ov0Q*7fC%q;0)95?tfW5(0;R;GfBM&NSo?>pi}pJ;6Eui9TH1 zwQ8~*KH*YW5ZA_qShv-KGf*@&UvM?KgKP{W`x_KLL}ECW<;iC35_=)6k;)>qTo9~W zxXp>&KBP#HnYA#%Y>qqXe_R&=U2E>O!=O95r1^;GAn@&+gOx)vc?r=X7U4S#y25O_ zbxa5qpL`^oZ&`ak%|ThoIcPl{5QsN-Seti6;E!)ZrO$*XPhu6nW7V;YX@9#v zN~)$QZB`V#F4(9@Oe)zUv|@(68P}*(?r*ji>(n4tTA3HSu=N#^Qf6~14QWm3C4f*>+6DFe9F@!k zi*g(x`&6iH{ocMm-1znR@(^nd=EOc!4%=;Rm7ga^1jEqKv`#DIpN&qgdke~0u{N<@ zCs2N%@4k4X_NH77SGTZ{YtUX`di8O;A_)fsO95m-`v8h+hWx2Sqrf67&inlV^w z@4q~GSt5Loa6j6oJll?r8~RiyUIGLJ-)|Ka?!fvir()V8mn;f4(?_96L5bJODjwoE^PScCif+rhwLhF&G>!eFM*u&e$dJ~5F9|p7B$^A{ih$k&H|8j7EeE!wa4NN z!4+(*R~zh>X&G>Pc(p$}k*DBqxn4YvYsaE3N=2nLi8%-|d6dKpwFy__zUoMv`(`?@ z&SGI5m$2fyltADiGBNevc#I*sA_F*`HMfG+nSm<2syh|A80)*3XTxQb(0$5GR9)bZ z!3q*aIa;JO)oBfYY32w}ftbIQfsXGu#&T&MN{Pb?Xhx-Qszs8|FDF(nEK!esGl0zr zGn<4Z)iezFmIFTiP!HKna9H&$MeP(pi`X|xIKNM5Eb97grCAiFL{aqwH@x->HCmy4 zFYC>P^(qn}3>G-*MR{%tL08GS9g6Q)y@8Cv4sib0rs?e|=t~%-MsJOhx;EXvG@`)y z@zIElTEsNQ`K~o0g8TP*N0W*E zXYIP4`j7t#3I5|xM^@TE`g7##V_gUu(9DYMWZk*VY(?L*GQsYG>^u9`IDCNXa@!Ty zgkhTt#P7gxTLdfEveG=c;viAQ_m2Zy;ByKnPn9J!cdtg&uC|0Z^D%n?RG8{CG&iqB zzK9iU-IKOn!vI{}&S_JWb>4#YR(n@J-m*=~|2fd+r8-b~f8uk7H2yx4TmnJiY{$?E)m7eFb&8 zA6j36QI2X9wiSUuUk;CssBp0Kb5povU5}hOmQ1+(S6!0~7!$1x8Q`nGMAvrOOl_1L zne`kgTkz4F41SE?FG~=#*#$1BTRbv~oFWa{Y=;%i!fQWEnNJ3JF5bL{#-|&| z9^`4^@kN+`Z=hRVn0`L2r*oAC97oo+@AV+~{5snY7O0_t99neL`AmKzY{%{u0rPBtalIE5pb>CDx0^no(-xvZ7jyaIqBEqh7)g|V8{`Tq}%%)hGA9Jm*&mg^S)k;qs(wzu8M_r z^qWj?ciaho^Xjep1HSAmjY?GaDYd4B@eA|vAT@Nw3!Z&a{?-3oD31f2b*L$b__4!= zQJ8j67qYWuik~yd^|Wf z4Dy6wmdns8`Li<{owYJ^P0MefLi2l6G2~fNMjLU~{)?!sjz#$$Y3-c;dEZx~h!4C_ zoa1;(eT<#0x;FTGOR3dGwftUO49Tt4qgx^JwQ>jjeA~hy5wx-e{c;N`e~@1o$PiI2 z?6r`Zmu{t(jLP$=a_c|PTO7uz1!6T`Deg}k#DJF?e6>oUs*B90n^AG|dQhhv>kI;^ z#oJUI*BP4`ulHrB#OZT#%KmpZEXpDnrBKv9u8PZ8%HQGuVn=(!wetEC?%Vde1u&B6 z2uvVQui%_QJICs&PQ~evd4-Dm!V`Dc5{sc@ytjywBWzb97v)NExRg9Fz?R{)x;T{l`{X*MBXYN)Pk5MhF0C+2Z3?$+_;N`YU+VFg@TkrcYZUM{C>)(A8K)raw2Rpzn;PY zQwg8wTipt~vSLbNZ}=ZhOa`)IUN(|!irKV%vYnUTgeAT7K8Zy(w6 zqp4aZ2cy>L%!#APd!?clf0+Kmhp{7Z(n#c1nTBoQHD+xnEtZJ}xcta~D@=ZnJBlZF z7H>k$XQ0{`p7?aYX!x5ET8tZ23VztE+hqdGL}$<1ZEniR`?}MGL`-cG%zb!yJ5}fM zDn+dcYmSFlbv6bK1TmUWp*4RP12lp;j^4&Vi1K#kDddr}puFvM1V?k7rtY`^`KrrMJbtp78fUC0u50|Nz{B!-ZIG-! zT1=HhDHJpllz`YJw_-CQh|Hs_e>DhosibbL%on5d@VoVTL&M*j=z05BurVL@6nfPI zHm$I9!v7ss+%OeszV?!b(|*VwrU0fvK?&`wt8|MEe|iYHPc{q4gk=aq(1A{D|DBpc zVXri17%vfuf3^#)-xR$;2+S_C($r9Z;N?10_PcOH?;70ta~{7 z>K=HZN5j>j_LDv`6KV1>k{HJTnuH+M8^E<%)vGCjNw})iJYs)XirM@m>%vW0G38W@ zIgC5PB?lZoEa(fZZLS?knYM^~Mz@#cs<^9SW1=!`k~YaoD{~hMYF`v~%mhg}CP6JM zPD1x{Of+F7tub6c?8Fcp)Trv0-xJwje(}p|k;nK3hfQctfAuBCFx8R?-O{*wvW+#v z25;jHk@|RGTl-txWRlsJh_n8Vu8@DR9hmJJ#rvin!GLU__eFK*cjE=GX@IG4 zi}|40xnk(H^8@`~C&LgqaCo2oz3Uy$Cp;tOyLwZzyZ@lDaPAl?OkkYDCXrS^_og5q zL*();E-SvI6Di`rVU){6R>Nx`_8@Uaa+fuM4^GUSk9N}!5{NK43?x?z$-Abbp-^X{ z&Aljq4hEw1ofB@`5B+!((Lmz=qcd?Ak4(5>>tqs4LtmQvP4L4A+nQtf8$BTmo_obd zdqPDOYRfZW!-C~uSlnGn=ZHyTt%_TOf4na54F7nJIzckQ3I-P>bKBgR)lzNkSxtF?jCAQO?(#upL6uzS;|={@ZhG39sZxN#`sYSlzq4@f=>$#ZzOg##QHqte ziOLJ{x=g$HFr-7j2ytFi#TF7vq9rw$EK!J3Urc&wZQ?+CW6M-hN%c*R)(UO46P< z#XdqFiYh5ZJ+G+5I~|8TZ{1)~#r(&61SH&F2mi{VT}(ic6Tu5W8}V_+z$Ex;A0m4c z0mAX0JQLl72eqhBr=UJEX2M0JH=ipWC>QmK70`-xNV0df0_t+p}F_gq2|-MG>k9WmwWcS6vJjptW5w$_6}Ht zY&zHXZ+lcJsOu$61z)tYB1Crr3z^1Qjxx=<=FJ)+@GsU`w1;PZW}z;ABuU5=dKEk; z@^NvO=dITc#8t~2=FoO1WfUX$Yg(gG+`7ttC}#s~2aLEB%8w-HEozIvp=FLLuH^9k z?%{(FJmp;J%?7hD9?HMdN-b3}8InS+eZaU>*HUb?c8f?ytR#3}(9wND#{XF!%+1AU zkP8j6B6m4ZPZ+>2nD36#@ZAFF5Nx?IT?<>D7WaUpW26R7)!ERj>(xGz;+@hAS9KyE<`UbN}JY@pqHU zUZ$p;VBmfVc3mK$UmPU&t@Lk>dKS;oYditokLz;8KnlV8eH@fNHaFCvMsh?$#r^gS zR$oh*1o@n*s}`6b{`_kVuFO|8Rn8WS`ZTLwbBmHMmXCle~uYg1tu3){-Yv z%AQkUs0!4skWF)eR5dd{`g6H@HwdNCrex^A5X;9k<49FHF~(3Y$}l^C_T9o5wvgWjB?L`Q@nswS3uTbP?`s(b$- zdk_Btm`xVJ$zfUlO2%?h{2jz_aST;LUQMQ)@o7PrW3+Tifoo>MBcoEm@TDShp-8Me z1-XrN@VhTy=GCShS$b=c8O^!Y6NTh70J{SwX{qRuk(AnkDl?uXj3_0d<;C5`Ow>uY z@>huQ$&45}C-Eqk407LS+ zzLr*KMfM|VbDUKF8*+G~Z6DImaeLIeo!lsGMY_;-@z15sN_6>)UP0ibt)`Z=%U`X* zy?_9B*Zr}ZVRx!i^;n|J%|dvid@QNiWrWT!U4499ldb%zT2%bV_ik_ORX!i}<;i~* zT>}_(o(P_%qXZ-s5K+eZaa`*cvMewBpnFvdd$wGvj2{*+t|PD6C51hKv{1jKu^tYB zkV5p_nsVInUoP*HauX;gSHE-&@Y=+nZXVZ_`aZUpj>8JgPA+ZN)K80L=lCU-c;xIQ z7%+se=!s-R)3W?^G_YwrS0O$wP8mV3bm^1L2z$X!m1+e<%evOiV5k>r8-CJRC=z)( zYywTB*aW=O@h0P!Vm5NQdQA|_zz@z9NAB7b>d!3}UZpN{6o&d^w=k%q${`u{fl)xE z)J#g7>#pjQ7Rtn?&ntB`Jz>V%n`Zpp=LIlw{bSQ#UVI71U$*>HOmxdVHGo>|V1F8J zDh~96+(FI?L1>dI^aQuV;TA5P)eAk4l7+%=T}7KYkS^?Pk+7o z^h!>LRcTU?{ytgmQZYGu2NKi!d2C$Dj#4o?Nx2xwPSUpUabD>>z%xZ+w93?3X_}dZ zf6yHl`)K+j>BrA9voyIn)Lqht@yj*6j(f%p%G|F=^Wo6c$p8} zL!HdKktU;7l!Zr`WIW36LAgpwjT)LR-gm5G`w6bPG6T;)22Ah4%HW>hiY3Kbvd4Ky zVY8EE`9NdhVzI{E-QS4LaxR1o_z}>hTgDgw;G7;bzPB13mVuw%4<2=>8)+fw3RPNT)ZwEJYgPKC~7X%GKr@q$o5{rV= zqrEP>x5V7xPRfVa_$&E(C=|7v`{XFi*H-8Ds%I{8mzGK!8nQb}Vren(087|0C_GBY z{bS8_f(JG~jBn#ZqJ-KHg9m=_poy7u$|^O%AVZ0gh?q5fn_Oqew)7LRn?HUzkMR6F zoyx5?|D<}l8B0LYrunp0KXbmT4a7Pv?M)O*d9xnaeCw5CLM)T&_AT(0C%-^X%4y<{QaU5OQ*5qg?=sA7EphqPEc2neuC?o9%E(iCY0PZ~e))({a z25hQvSdr5%HsrVwJdw!$9*y{WaQjlq+PWL@SFh)8ke-`bVKo}N_KIQQZEjpRyN64_ z15?57d`os3sfBnLwct&TIm?;(jNdEgQYLw<((F4EGgcTwO#Yz>#Z`k>q+t1ns7PzYwKNr)P?6V526<5(43fG z?QDDYKR=3VuifA!MXhPT5hN^Gmb5FR#%opClfGFka9YQ^!rFG}Fqz_HjScFHluc z^G5Ey+YY^Ktknc(ofr2z43eOlGLsYUWg!>o{9jEfn+%Agr{!xK@;V0eFjr0xE}94{ zrCygsfnaXNfy?cLm=D?0~lz#zrKFhKn4lz~F}gX7D#faRtKRUpmba{c`tH zOAap%w~yF!@ih}k{lcH4&kaC7oO`7m(TTg=<~_r~9Y(he!fM|8^^ihB(Ije5J!45P z^YdCu4^1TFS065)OB*#94UOyH*8nltQ%Sau?pjzm6$0M+nDpOFV8eBZ&Kih{wQIX$ z1wiyc>^#A|0Zknkh-s4{${ET@)cD4q<3Rt4@>$@idZ)tTQhu^he%=yxx5uV^!_XKX z!E&!F@7gV%_lHN^2L;AuepBw<3xquTnD(%$zswvtso{+b7VzT>po3qgSer0;tU&T$ z5Az$5pJ2KiM5P8n;=)uY+m*}29vx~nYcNF@vRH$~f%J%Pji{wot2O7OmGQx;SbT?8kfA)m zJ{TJOJUW1s|4Bzj*&v0RtDyT$EU)o*?S5R=SgXur(c!>Dz>IP_csZ)W^`1E>BaxbK z9u^$GQR%IB80vVn5m1egQpD82cxi0gu{(|5MICUIQ}~mAHHQh%@IMIw!1&2*=d)yV;kgqU0p({XXs^b|q}kdu{{aC9Uksx4fMUmnW1ut1IlnI(i$fKn#o z)nq@ze>YzDg0cV81SfNx?`A?`B(gxjE&B5P=89q-gjyA6JFlgdzeW0E&z4UELQ#7K zD3=t(0#5H04i3(MB%$4uf>aJSq=(PS#4y;3Ui!9^M)FY>s#(c5<<`RrLTp+-0$=bzet}*OH^UFd;&;bRwT!DFXv9OS(wVGvkB^bK{6N z3CyEcmrnw_6ch2mQj8PXl~(n>WW%KjEY2wQUhsbUUym1}7>=-Bf9*j1yK1-fd~6Wm z-JxHhRtH9@X{y`+-xYZ3KTOz>BZi$3NVb_Jj6ArUwH`f>+J>{OnfDD)N)MapNJGGA z6E3eN$&kw2AF&nva9L#QcbIyqTC1l_y80i2PlMIy)PWLl{w(q6h(WmUXQ$?R#M0@S z&xm#wQ9X3x93*w9T1n-($OPeXkPb}~RO`M+t80y~smtuFow^o%>-&j*(VBJ=j#8qK z<;F~Rf){F}s2RyPrA3=(O;kbDdJ8-+1jlwka@hc^7}G$_^^Ys6r+%8(={n-g@aSLT zz_J0yNU(k)v+@>I-uirMeR*07%pSL$qB|mn6GCdnha9+BHUEksU+;k{pnA_GoifCa={z7#?D)%9pYY2PZW$!*y{I{MWt!z?Okx3SzCwmn zt>WX~R6P5S{4pFZS_7Jk5ThcJH2-<$1TDn&9#?Sh?{$%3h%?+mBEmOwit= z%lQ+SMEohGadXd2+st=V=P{;c$nl`_Jr~R4XnJcefMhDWuPgX*K;6|AcL=Q-y^D!7 z5|vM4IeX%xmmxrj%W216?GF;3RsUZ9@^Lw#+?H0+gDJ8cr1-}+=Em(K{i3Rs1Q@W% z@^u&T@*mMu;qyHkcbKE^gK^_M3Iv;fU1%z3+}86ZySJ#!pOi@o4+Zx9y)!&@A)sna zcGJ8=GD5kFTqRzK>C)(KWl;F0WPWm0g^y1_%G`3`Sc%7x@{Di_E4zp|(4Xbh$emlm zZE@Gf5u3@d2Y`pa{Ok2SE<6MALsebSuX+eCHtm^X8ISvRT5{lNVmqLhAl@+RD4<-O zAls;nH37cla3U2S`kjXA_`N%lCtseb+=xfi_vJS{P*YXi+*6GE%tVV6sFG?t z_RkGbq;hG3_A{fz=RV_ji0+(!3&mN!WH9gYSIO?%|g36l({^L${ z-0o!A*9`D76KQ-)otG6^k$;d6+yOZ`mVLEf!lbg~4y>oHyI-le zS?-AD+2GjyX@^TIAOU~DlkkNvCea-D^em$Jr&;neQL46_pW@T2||Zmy{sD`mxcK;?Y?fN!aUcshflu z%%rn#oT|!#u5YfuyNNsxCCht2aEZ+glcz_dT!yT~;GtYu`1LwONo*a-C4_ut2?r=7 zBp&MDhXkMUa6|?4;5ZOXvRnYkluW;cIrY}|8lkM5^;2qkk>Gg1;MyH`;~^5j^!VhO zAC=94FshCmaY67*u7jC8ODX~=A$Fr=)kKHRlIU&_dH z?-51xy5;aR8YJ5(mIxY+-&Cb^CL-Y1EdAbq#B}bZdZu8UaSu8M_ouXYHEHF2jNj^y zR4pd((IcjNdt}i_((^+$V)t%J64RVFn=vH9@5j|GhR4^w?c=$q$EaJHVY@H7M!6;1 z_c=x%6<_0s_-LGMXH^INE03(jzEQe}RzxKur6-}bygYzhhG&qpYJ?N(r^-ybMaLcb zGf{-O08I;m;?6mB5<3yv?mfOrD@MHBB`Ym{gGrP^cA{Q)qd5y!(lU8-Yd;G@bI2;- zpUcAuosyNPQW&3ru%>8VY1sDn(WPHJht2NE^jr!vVsa|7S}PSlUBzkMycW5U()Z+R z9pGIQU%RmD^EW}|IbzX6(4eWt<1{`SqhatXda6SZ^D8+2{!=N z>M94P@|3Pkynw&XMdv9g_Y?TIQ3xg4ub4fBjXP-AWU_2FB-r5owNk?*{B=l-}mOW5^rWDZkMqRC6Ox)f8=V<4lgh9%0x6cPohQr0gwG6xCNZfF_;>1bAfur?Q|daCdsdo^T*{o_Zgs@ zf*S2U2m60tXrENTrZ%W1TWFY%OxAdXKJx|du+EI`;x=pRLb2xT+|tjx=Z~bmFS^IbO=ERFHDPdK+}I? z!56QiBK1*&$=P=G`mCz#Y>KprvZZiBIz$D|^T8BXBmB=HC48Q+f}UiaZ}LwF+^svu zB!MSNUcyQ=B3+8HmX|6b=NMJ};QQ!Wq+n2Lus`wC#JQ*!T9R+BWJTLhJ^fZ;K^RkPq6js%zqgB(94J1pbBAn}>iRoLww>1*cE# zY!HTZdN`uUyrF%s>&dE9$@$g_yL%9MOO8H!RyPI~MZ2fs%wF+T|16i{Q+F|4Cq;5u z0j=g|jviGARg1NOHaZNfU}3<%YPA{e?zaj27Ee2WO&9L=v;7$%p!RgXrv2%nzjEG1&{$ zzdH|LFBR<@@O91NG`~$W@V<8j7<+jXUd%en?j*|$(dkXd3za@psM|h6X-3jG;i}!85-u#wd{J$Zo$4 zPSVm%O|{7^hI{B$*HYw2r5!2*y!gy5`3Dfk-Y;#?6UEDRilIb7bJnp&grfGCVXywL z&JAd+TN3OP_+1@@%vQ<{TZ>ZgkYT5B_ICV&iV^_JJw?ShP1H#c>^!27RAO(q0{vJ- zep@*Qq(du7>%c;<&S$!(^?7?PPAyOkPaFzCOVpuv7pWc+^@Z}@$)c5(q{%>W(#|U%|FQjqVwqsStgq9cJh#w4B z2g21%tWAJ@qmVCp_%46RfAXG1^2okW;#L(!ksK_Y$69CM<(lC zpe&aHR&>qgOOm06H;;O9hp=lks9dT{^X9r&QqQ~2+ycWq0(Csm%vhsA&QNy3rwVrV zJWslN|H?EfAaqun}k&DoHBNsTAq(xcHqD^-KSjphx_7>%q*Ydq znDtI=JBvTG1!*;GBM5*XJBt8=;eC!N0-*8Dw_LRj*EAj$tRhrt(t&bQ^&Yi0U``Sn5~zg480Z zR`jwQcN~_@?4GHY)8!QI{lLRo^PTYtMh%f zG%#;Rl+mjjw(zkdC(bOND*@FMw5~U@@8F9aN8b5&Ta|(^{PCw8PQb_p%kTIsG8y7MN&J{LG^`dH?3-?Ts-k)OL#+u z!yg;X(H*XK5sSN$GxLx;!y!m`@0~_pZ9<8})^ojl$VdCMdC*~TQg(9vasShQ{GYSL zr=QxQbwL!X-oe}}g*Td$uAS8S7RiPrjuD22|E7*-b@yJW2~W$YhJKR-D;aM4zcilUbPTkA&r3 zyL5E5#Tqa=^8xszm$8vcMNTa{t^<5&fQl=czCUVt)}u1M_-GZr7-CfVf~Zc4_Y%dD zk4AdPMR+xBRDf}C25jqLjv;ej`Y;Wn)$&eOw|=VTro$>hybIv$!7k`)KWS3qrhz~O z=3_j7C_Lzp@vp6r4gB|pFwc~Egv=9#$q9UlH)~6WX~&jGQSJUSvyo=8f%>Z3=@7%{ zQNMlKj?fY>`T4!VX6wNsvR>m6Uqp}tDEv1FOy%0q+NB{FRjcUx)(vvmeygS8Q|szf z8U^28ee!Bi!{UQ9uJ7w)Uu7XlZk)FhCwHXPDJ31r4UKO#q1Y3Z%g2lsl+WR+I!Wb1 zqML&#E){o_D*b%;LALXk+She+g$J{D?$V#*E{N=I30DtG@#|1Af1?@wLDy=R4}j+%Dr6N zbT=A6Me`iN!$nwVbmj++MgvmpCrEp(?TaDE7LWy%mK$7D87d@LoxeclTImfae9r)-Wq%7;@YexoW2)%Df|yn3J$IO;*(a-jw6ER4qbFf+4H z-{RzI?}-$9X~Ql=eJ_s5H}PNx9|KA(1wQQv1G3WYsQGN#8e)(mE_3a^@q(+(Quljx ze;5GFJRQ6a!{)!^E|LqFrb5?MdL+_DYs@p`Y?^Nk2K*$T-M-J3KrnwTfX^D^Sf}7X zag1M~%TT4M5iy@#5l9@@{@ze^Wf?0*U&DK8v_#SId)fc#YXshH3HE~R7-udhs>qQX zW+E=eCUh)$h@8u$PtOa;4n`E+Q#&DiG))=7%*-WaZ#>)iY;c@cs?M~2`mUb_^T~S- zKk%<@Qj&x%ci#^lx+VGHGn#r)2MKB-`$@SnU6&4l0&q1OjML*q*J5Jyo@bZKwi=qY zWi}dwuY&y?(nlpO3B=_t#2LUUnp@jst+jK#XN6d3`+^|M{*p=s-fyCw znph{?DG;#K{TMr1fEGANdA`2x^&fxq)L%%G8FC}#I&K*x~bY%~kWqS!w*MbFM zvZ2>8TbYza*=)Mln)o~;#k(S1212gy`gH6pkMe%Z$TrDz5ihB=j>6Bc8L{;%?((fH ze}M4%UM$ikJK`Vkwm8`Ie~wUd><8or2ZN4S3^siz7LERQ@e4g$qNa0mH1DKPihK(HfMqwBZC4!rg93dt7q+Hk-Gqmkln%YF-L@xFAVneG zX9jPAn5pWhGQ|Y4(j!>{(~aRMq&{oIYC|lX7+-BSAkPXt{lb139AFm%1`YkV0TSFJ zb6hnYF3|UdB7qmfOY7a`d#AVVXeo9=aB1ib{Wl|k4efXusT7RZHz#kpWtup$Fl-QR z#o~XMvIZ!xT#%xfp4_V26^yYVM_JZYD1*#BmL|V|I=`B5Ob3>@XcQck`(CbRdlvfB z&0h%pwbdnXuWi`8>9L}z7xZd$J}e4K%vRW<-THzy5VFfSO}CxX7Jq#uv)?n6BEQAv zsY9x7&M?@Rq%bgtFFXL~>c}w{;kteWLZ*h-F$KY*ZSN{e9A`Dl$L}{to>~qpYf+y& z@EnR*yZI3&T^fE5x=C|6Et}FVGaC&bQ1vF1JWV&q)<^auT=*^E z`iU4Xr5fD`00|}a3&WZ~KoW`_dEK^kvfweN$yn_)otm^D-gD7G;~|u*2H#*V*P;9l zx#<=F%lql-*+0?ypX(=TZRddrznsWl8prrcU^%uQe5sp2?BL9YUd7Pj=uSQk(EnEr z=^y!f&Gw?xrGi@8$IWbTedeG*T8sMf!%?pZaXKk(B3FO@H#t zGM;4orQN7~;TQ$O&M`w-o!K<}R}u@Le$cvhSqox!y`@G3PIPhOH{BWXj~2w$%0?|t z^f7E$mtWB@zq!v`3^Z_{0wU_u!pM#3zT`mgfo!G||3v)e`QuldDpy4EcM&{<#DT{y z&LjmTHi_=bgV&!uGe9xI&ictPV>}obG5$X9r1>_tf>rH(l+JjAt?$d959^;Q?7O~c zt{ny*zq|V$(ksCrn}ZM02~#aL1b?#fyn9O~R8wL@k#H{-h`!vQHF4x#Ed9G}%x2a) ztNeYEsQMRkej)wS9G#|$!?q5*Ib#<3Iy@jORu$+#Uc|NRN+ujpIsCB~wrKkPNJwZo zJ6*B)0g9d0>vF~+w+4DoY3L$p6t%3m&hhRf)PhYm7J$fijgSDeSn$OWZvi)UIgICg zP0Sh&D{T)|j}>ki*UA>O3MAS%l?4lgMXjlhrl=ilY>usA5;Hc%%Y2ML_fzc}YGCE9>0AEtpt~;>Q@gu752_zxB9;_d_`f0#!iWe8BQ}vFxYr09p zr_JY*wB<7)g4}o(*5&h5z-sJSWyFg@AFTXq2Xb5pTdiN7oGj9i}2% z_qztusvqg02YH7*b1X{NZF?QWRCyd}Nhvr@xJqlsrtbo^CLSF{^T z>8PZLhze)yj8Soi^juB7oxbr?=-%g86Lp-FQ$7Toojd)t1_!bm8EV2%0ogK$EEM!-1Qj-I{EtcZ;7> zJN{!q`n-09E>eC?o1kzRH7d>8gl}1Uspbtsj>#gdb{UV(JFad&JX}qddhGNHEGiCP z^B3{BLm_SDGgtZJt8Z>c>Co;&p&gcYGKZ!WB%a2L4hxk`G)Q6l;cT7LIm@fjKZ|dK zIipPUICi9U5nL9wfcyowWXdTz^#WQEDy*D{1hGUgXId>nw`43wqiyhy<c zZ@YumCRn2fA-Zc#zas9KLUR$@gBFzLuQWk94(B{; zA6xsV`G*mkMj6C9H=do+vAdNsjuL4fR7>NxTK)5-+0a;tQy471qw1a=V_Jh@Aene3q9mp5T&@*N^SL zCVlT$DWG6XUv^frlr$P40xIbos&6o}F>MPV6VrIos3;8ysD^kGK>9L6;|P_zE!iHhQ=xN)^CIq z0M@O|anTNT&@iActRI$hMSD9Nv>e2<&O^K;cy*Za1+ha%#!EAiObNmrD zVq>{@2Qap!RD}UVyToxC3@pZ(l@zK5>M{GI>(?iQOrvNZqQ*qjlqSGt38`y_UB*~3mYL=|qfk2qBFe+L@^LA9qn1o(m^k!q z5ur|g?U^k;^B~b9cR8myQaOB@vfI@$D!(FoYy=o~K#tp{q&~5hvr1xZuWttve!zVM z37B611<~TiquUE=Y&Et?AD%?@y{3D(;tSCtxho!)SEolwOXz8$hFh&b9f$b_SwGx_ zj_?+<6Y`ffwI0ag^&uTLnyvgG?&2T+p-}NCVDQX&fexO((o^X#dw!B9|L!b5JC;E` z!^mVJ(=3}3*&eb_HTrDI%To|Rw9HB8o^uhrwJHtEgwL|%ZdOo3M0a_~0WzEf0)osO z@4%&aEaa--FJV9YmDP5XC(Jd>a%F3F;1egSW_9Cdz$#&4Io}!L(#BqAh<$eMXt^ZK z)ki;E!md@T4=>N*P6SaVvl$S?I=CFwr?7a>jZsBS;QeadZgwb;8qgNGYp3+Sp^9p{ zTG^@tXz|4Ft{voCRG8&96 z^i)xo-xmK7_-X1B`a$;-M;zVGDf4&zZb$8~9Uow>nLptLL7tX}ZiN=mB4v+M_8?m` z58o@S1TI5}Mi)h^=RHOJyi~~eqEm94!NE{jSO~C4zl?h)R1dWV~L-7 zNh#O($gv4BbnJj^w{krm7xtCjdRUSu5h4Ua`O0dcE&~*B)S}y4n5^KQV z>g#b#`$s6czxtkH_T0hNjox1+xI^Nbfa7bbXYqR7i`72MfNvH=CS<>wSE>WbN2WR9 z(`z2M1QKam4M7V%&JYojnqZBIN>To_ycrFnUnENs&U>XKTGut<&H5=xKlF_)^UfNq z>`{1FZ~CK)PZ?}tQ?G#wdW?broP@RSrJS2?@*?-Al#9;c13f+F%eWH9>V87x7_ouz-K$ePVvK3M=8a2=XLqECUHvr=q zd1rJTgW{&kUlmWZlSMKGgC1hFQ7w?OTIZz;}zh^_P3H6WmAX{AK7mMM8y()A3mh@4|?`MtEW=jOMu?_MAZ+Til8lOL&7ux z{vfCU@7FgTE^=Qn={K8eI76Vj)cOCtJbG41&u$^Lnx)nflym$w2)~UE39eEC;tArg(@?w zXO*;k0ZNHEkbc3p+tNa+ zB=_+W^u%UN_*+f=j?5|FE|TTEzGk-DXFSJah8@JCDw=Db;NZfMTPh483m*t#`VS^8 zy=~z|0it1jjpYmii00;k*a#XG$oG8_0_+>3)nhf`B219TnAuB{`Vm<|q<$@WlGin| znaj)OQTX!=@Od>W9#1Q=-7KGBs_{@bHZ2&d>F-)I{xejM^`mZya2%{|ghTkKILvZ9TC zRf@CD_o`|wY-dM_nJb8^5|C0ts&g@)M7IyVDU$hBz<2KR{jxE^j~nz}ani$a66DBi z(P-Kv{elvXx%JXNX+Mr+ABDW1P|?ebow%iG8{@Z0`65mUi2%5&Rp&T=9nFU*R(P=0 ztkWQju@J3;-MWClTYpOF^V|Ei`fkL@%k#Ejn>G}YWoQhD-)Jfci9J$`_T0lxK~cA6 z;Q-#BIQcvtekf?=Ip?wwf(7C+WMmDoScIg^uk!x4lkw@o_Rw=nA&(6819J#!JH*l+ zxX$Itl}Z58&P^KFx9Fkz}&-P3L>OnTmMO)3Tmw z^f45`>hPD#po~UjoL^n2Q#aY{pKxLn-DrZm)+OY)9PJj$1^p35;r-%-PqA=nCNzNw zd+s&Ncn5C>n+hwctH53+UKZULQvY?)eF^ApHt)5ryKY75eNFW-06QyIiS4L#2}Y!+ zddJeamhfnZDz?(S01P`aF)%Rnq}67}awu>A*E9G;Mdl)gOo9{)f@~FhtqW@{YQN&X zfn0Amu%{0lKee?##o16G5 z>+hH|6RdW$sEn#YK1CnAHXK*v)<$N<*YUc_PY|QYT;*z;Ab0K|<4yZ#HiSoEn7acP z9E2AyCKzSqPEY*Oy8ouSU^T1EI#QtpSdlx+LSM?W(ZH!i#;xv8`*ODW7OwN$X>v#U z)zzGFjGr9i$2PP0Wxb~Z6HVqUrR}CpQmuS>nv5$f_@TE59pO_41@4djUA>?E*{9F_ zv$AGG0m+wMbeicKtXg~@O;b~wmti_MwvKbP)(k28Es{_gwsiK`DI&GS4x9%p=Gzi{ z79U}9nBlO2;*UE@CVR@U?ESJpt;fxmCJsT06Wt&qYC?+j;Iw^_bQH;HkdWrJGVKXN z=uh3Rp-15w>(hT=EYcM_@?E&Rx7U`7xYZ#?2i9J&+4pn4eFX`J>IZ!lz(#F0!l$1l z#P96PDCCJisarv`)L3Fr@zO6gp-(tXvK_T4pxaJ9ckddk|E3oSy7b?BdYvM3DT3pW zLp3KT%ub`wA$$3D>Gi8?&gOi$=WWr>!-XFNlQ!@2TaOuqf8ZT>9$dT%D|eeyUc^zE zFGinXX{sOXqw!9b2Np=Qnz}N8Dt5zsU#H18C9rqqGRzp?gjO21dD#n!u^IYH_zodL zKtvmlZRn$gk{W!S&igXviP>`(LltFRW0zrIqEdX_vCB%2AT*~J8Itjj_$#P}?Ze~N zXtA=zA?}7>o_Xbw?=`YHGyv)-m-~Yl36qiE*KCA zVh^IRqk%NFKO7vfL5mdsr%CjmTlS}AZ9iEF3~n&pOX&T^lD{u@Q(tt^ASLu=n%p+A zwVn5H1oDH8N(DpQY*qzHXJq`lu6ne7rs0=!9v$+jBQ})Qdq=4`tod~CvfIe!ra26^kB{#!oWrB0ow{YP&j~cY!ygalhZ(MAXd*v-G{iT9 zMo4s`tNVJZoi&)VU;=WRluW9cv=IG13*@q$rU#Bf%gm=bz{JI0z^+1mvs%Jjf#fx(mWnp1he#D1CzV(4d)08dQpq7 zvHKjS0bX6J<{6sbw19}pEb%M{1=Qf?rl}nh3_)!6^WzGfmmZ*>#Le#p*^+6;n@aJq z{~%h?;<#ycCb4(wh1OYb9iW*`5f!n}v@5GL$QqdX25eHUAy@38$iPjXW99zHJ`44S zOiDQGy&+2_v9I3|(Ta!-hj{tQgQ650ti2^zXLRn)Hc2ub8^I!R zW3KbB=hS8|HYsP~5&)u4^faIeQXd7P1UCmDS=~u2315F2&KAg0nL6*?n%*Vk|9Rxm zlm6+ZG-tzqR|~k>MN^r%O3*<-;(0f#dgd)O*4M8=7HS3l+XDCq8Nr9FI*`$KjT_I?=nNc5TcUjRrzqu1!ZF9giuY z=dA(Jo^@f>>)g#|uFckX_sR^t5YizDUxz@dy%fXT+NKk`N)7)aKXOu?b~FTI6qo5z zPsftfUI(Y;Vqxa0l>Rw&Q!M?&4416}WwOga6Njer{2qHkh*MS#NK4i95YtS69&EB> ztI&0B5St#msMbUW6k6q{*bi29V$llVq&!bcsxa{SW|RDo0En?3Uv0u_?VDuZH7;kF zOTK^YTbYn!7v|%&pZWKe30Q@2K3{b!ONRsesgjSHcKH{4j;xMbIf|JAynGBUE%Bt< zUz)j%#w3YfWTG1#Yd|7k259zdh<``=M=+ID1)k{Y06>H*1Oq5u82UWk~xY*)0YeJ93#>`?1K z3umLsOuwt6pJ`akl1W&n=-8Dnq*Q&u@Rhbsb4iR3!pTATH) z_&gp@kS$iG;o1~83+XOSFiLQ|8cVT=DWKq|>z^I~j!W&7K*&->SqQ`~cUbW4@_M7U%5G_y8y9;eK=G{utnJYt?V%~Whu~n!Um)KD2 zSBWjDAmkopi-WncwU-JA{mICCiCg#Y#(X@6Dh&0k(CuPSfy_FZy*c8Zt;_-SX#9`S z&b==%0ih~rIcD8g5&F)CE8%8YelEI)f0<)NcAto;@R4Dal;8q6tfWa%=XVYVjbE0UaIdbx~L&x-Og|7cfo z9^b^Hb!hIZ+Cyq}aXBPZKWdg{#iJX{qX~-_zJm}8y1HbA7>Z8JloQW1rg4BUust4+ z6Fkofh-cJa#5p$%O*-_ZspKrChjo$yC2{FF zu8k>>u>ab_u^z&s(mqKo_PFTRX)2O~4x(@)%Oik%Orl&`Nkxij58^4!{plNTN~pJ2 zrGgXwN3z>CnLGJe>Tm{IW+DCx&B-tx=c3}2uBq}@z}O5rbv9Nv*Ii>n!uz|40EEFM z7iUzO<5jk*j!h6};r!v8uQvaXHyiJd>s5gZpV$p~$~M39y#* z!zumsIGRc8+b1<4<#tqUs8ah+cvnv-^^*g|_g>1~ntwdN9J3ZE_4+4KzjnJFXsNWG zX=%EGgdTxW&6d+Fp5#4Zw77eIoxRt6_3=Qu{b{bmQFv31J$zg*3S3{~bhWKl_N}hS ztW)iR__?5U+s4ZC(rjmc7^L$6ra~f{EVwr7=iH>jY3*A`a>qbkN`?iey3FoIa4=Yp zS#ZdKuF#sWly6WDg@zWLl~@)yNo7Jeo>ou(#zJ>Yt}r*-#^qR;+Gxg+?TEoyqL!`W z2rzf<>_$h;Jbyp@Mb0T0RD1~b`(H8kDKINb3Gs+x^SY{V=pVQs;y;NjL`>N+p-)s< z_e1am)JV8A{Kw>|h+N@ptcqxpCrHp|)f`rruR2tX5>k$65>^mwAA_*zGU}OC>AfDgTP4hh>wR3jT64#SzjGK0J~;E1hphrb&g{^A?{;(0(q|AM#+tShYvwD zN_vcn>je8iYH2!FsIopszQwDfei$K37~kb;yg*hU7z}^H5QJ7G=Ru{&u!(N0`RtqO z;G?eHYdXMuWX(Mf(XmQr01G?Ya{=W0KEK!4&o1@usERi`UYoz3jn$|4h8IP!^8L0p zBm{L(nC#F*ete%bB2g_oDzi;5ALFAK2oAgi@aL5`qJ|eUL%;J_SMI>S7hvo&$nQ3H z$3?a?Q^>7qnF>{B(s1R>usNZD_@jznw7))3el*stxu`Vzd0MviP~LsQSM2R)b!9Rr zr`N3G%BM$&DVaOW=@i|-91%a2CYJK#H&o>1^sv4_*gm9La_1!)@f2T&Bqj!J;Hf~y zSts5E4i$?pJ0}wVpBK)D2MF@muqq?mcbiP5*xA(1Z6Gu}t*b5ftbJK(PV>a1J!?Y} zuiOu$AJ_}x_!U8ZaFaVQUF1mpDl&I^xP$-a3_R$D$tZLp21N7U8>jydkR?R_GkRJz zWFC!Vi+8su3u|!^MCP*7Aq-$|;a7bhAsS;eM@hVI`45k^P<1tp2}-rkzg;p613aD4 z_d&so*ltgmxY+X2H-=u&Jr!ztmIr@nV@2>=-NP0~6Ci6ozof(k zmEpiXOQR*IF6mnB@NL9qJj6(&=M%{ysnd1RwC5)w06XhKbDLn%7d!| z(AVxPv~aB?fXFPZS|{${+!UZY%@YdPa25Hyn3^ntPp5OZH_kPwGtuNSCi^QB`X0lym0Ot|sigGk)5(;YK!6H&wyiZ! zQd#9uJlM?8et#;Ag2&{5g`sk@Tin@^+cG@%<672f0GrlJ6Lru!nP%gdq5o;=3W8R4 z%NU56!>X@?PQzqi+_ct42Ba#^%FDYL^mIf2LCC4iXlDabMYO!TOp<+8mz90h;JG3 z{1(E20G-~7 zHPcRnl=&EnQT}P@s#F#hKGrI5RF9!(>72MY+ zF*Wc8LJ^lzVQxE%n=y=i{OA1qei)o^%pRB;cf9+dLKqN_|3hI}gZc(+FkX;HU-t~; zsI8`FXlK%>eE4scWBe6r@hKxeIxAB#l!Dc=fa{S;RFtPKi!WQvMjuPAj8g>}TW1SR zsKoBW(IlF{@})T3w&W=|4OITXu%}o)OX|za<}>@EF{^57*mwhe_}|;rf&4AfJ=|I+ zFT@evfqOJ`$)sy_zILlP&F0uiqmqi|eoD$m9aKk=TmeTK86Hyju6AYcc+jO&Fl(YT z6kd76%}tAQn90U3UeiihA2)XS2vlQRo9*Sp#${((t(?R>(if%#0zu zs{94!Ee$TyJ*1Dn)aOx11JOi!re>3IF+y;v;f4QgbbOj_jiA(?ekr>=Hd9#H6DoZx z_%0;TZ6ZGPWU3?*{g9K=&z=G6GFZ9=z7&VG>p-s~2a)BNjMt;FQ<^|%pXZ#1VIt7O z7ZQ$E(qH#_Kg|G=Umf8NlF2+K!U4Ip5nX|+!kFIlB41!G^zNMa%}>v^O~Nw!`+$S~zWzKOE8hx%@J4wcO4O+^Tf5s;A>W z=E8o4cqgoW(wtVfztI+?>U!^7M!YjyC@u>B^O8k!etJ3-cV_FVgEL>=$@=r7>X^ZX zOM2(j6$+SFk|@$I%x8{5H2C(cXA_YKzZ*0G4(xd|CLt$`Kr;ysJsMc9+N;*4dQXEf z+y;4k>lN_%KB`_H0*wb{-eWP;#(Aw$_JfzxDQie!Kw?Kh<^_lFgcZCi=gY5mrz8b3eF(_tSSs^;BW&Ogbb86va z>6NjnSw`qhP|+BVLp!dG8UYmNy&zD5z{f}Ch@bk*+*g3sQO9cGw%I$qj>M0P8{{$ z{BZDB7(+q7AlEZLdv{N?TE=5YFQrj~yYTB;dilN#Zi(XaM(jSkVKT7XT0*T=MH8GZ z?#ub>Q#SJah6Z2%BSAln>5Lrd>zOhtw3`AZgyW;-&E`S&_ItBe_=~(NnEbNeTs6em z5V6<|)G=*PQnU%&Fs^Q@ahwD(Y4hU3XGHMOx_B1&sXf=TjM)R+ZE}25jGhfeP4^Xo zvsJv34#WY;N8f~kvs=x)?V^#ZFKD{9N4XD~?fs?HZBVdOLX_aE}>$+a+fq zsze!&`RH7%@I~;vU?p4o?Ohuf^}39CT`-@@_lwLLAj>Zx7qIjS@G;C6O#NtiSWw$~gUxKc$tlxzsj1tW^kF~lXFsemryGlk%kTVNLwtY&h<9+` zg6%99jR}8c&mVaocd9tRwc(*Cl(zr?&q1^^@(J0(TD;b-)~b(L)qv+8^h#EKsVW#- zW)k!wpJ7Ajrfc|1G9` z2%8G-9M)he+>vZI#7w;Xm%56rGffz(Jp&xLq=YLKM#*isp;H!|$2&OB#~xf)K1vCL z%6B+xq`KT0NbV61?w)FXQ1eRJWiT}u_Q+TYAi;kb#!euYy|U2l?3tTEU{Nj&Y)B|! z3jAe@aBD_j=5e-$IbHTLVb0^Yq`Bx074L3pr zGP7^TN{M4VNXi8Zc8JCxTt?{O3u4JwDx&f&^6xBR&~zCHA-M__CUbz|NwwMAnaa5^ zS@Q%Z0K#w0@0VXZANKpcH=nt9xZw_ahPDj`BUY5iTbTf}sBz!pVk!nUy;%R!Nm%+j z3aWI0h=%Zg>YI$mNrl1vk=4=6QK+9g$96UAXWIxT?sEKDW%Ghtt61JE62St&$wG(K zlIoyFT++L1wM*-g=zBk^>o<(ZB3*6khAwLAR8gV>42>#=#S@W^+O_Szgn66GRcFvE zJJxj|d8Dv0nsh2wCa9wMD4sSu`gm?MPkduFYa*0B#|c;9pq-VjKh^H>)pVpqGDd?i zG*ZSC<@KZR@3dR_qt(o?xA>JJy?UyQD^!_GWIO{-5Ir zh8f2$aRP>L@zdG66l2ICL*YUjq1jBb&QtKVbL>2hq10?PnuxmfJQV)ggiv;DRenQE~qp_3bd>0Sn!$MpHWJst(W~7}!n=%Rwr)b-% znF1~(yKWp=kMPbe0zSUOUO0#mjs=`;icZu*qO7L^5HzJU6WxBu^K*JTpXH@ZHny}zx?k8 zGcAw)owUSiSka1!r+T_T+s74ufy=BD9u~>CVA*U_y@P7;FM3q|1ekB zAqg}YCFCgzb#s^u318S|SMelKZyLU=7RX~)P+!a;_Mn`>$@)(8iTLPbQy{!`>Js@V z7>f_5JDt`~qMqFmLGg?F8343>sr?dDHe0|_wQwPWc+Ct~AB}s7r3M?e-}2%^%#T}S z{;D;RG1Yiv=_;r7AS=YC5^T`i`7+O0BSBjBc*Se7-#zLa|G4b&>zTOG-0s7?cyn_a z;_*75NV;W<+lV#5KB9UEc25}nqEMmj&p(YV+vgo|N2!!vLitkjo^m(yT=i6l|0_ei z!A}?^1S#CDK2_fB5*2ylJ5646uIUK&aw$%Q)aN7vBQg&aYgsFV?{Z5<0!cujwL(T4 zY{2>+WX?K{VQNZTOi^-V@XCx@!$=OhUp=u(4&`*nX@HLESUg?6V5XM7nr2driMGxT zU)>G|Qd5q48Ewf7Fb|r~y*a||r_Ms$1`oi~njjB=;;7zV_gp{7Gayv4;iTWwV{c_4 z?>2RD{nw5tgqYDS1X67y;L5Ulv1k?^mj5%{)JK9-xt6T#DU>nu+M>>JpwTXuoB-ERPLqOi(PQGp33L~swhcW-JbjJOh9dq)o(AFF- zzIDy_i6)lbJntphW7su}gROQ@mF~`*?LXp0{)Cz_k=84@zszDB-o3Sq{krWuW@P*~ zuj!M->h51u(yW6n(%F2SPbP%^FU0cm#1qqTTf^3cuH%=e3S@~*{YnDT*Snf&v#$GS zuNL}6Ty;#>%ww_0zesZPlZ7IEMS+o>qtJa?dD!DQ;`m=pFNL!{kfV*D}(6N(cwp||ds4wtjf&3@k#e@uBBx5O=3uG=VSa+<=h zPQJe|0>{(W>^6QIj*VdpT}_x}#`efB?bHF0h zJ*S&~v%N_GXj5#2{fDNq-|Q?#_FFw*0^a)2q;zx9{}um70d2ua3UPNyP4_#HF!EdR9WJ1?+KksFYL{2l3ai7{p`15#nW>uzkVI=X$#30h#3-j+{7AOS-rgrSa7*E>g~ zghu{UH7)74iJA29qiBBma}AfLf8~;Ew3NW1_q07rs!JdjIs=~2gRi@5xH3Pw&w7rJ zQ+vb#frnYDZg0fPB#qXcrpq)p5#=3Km;sz#gqoxsCM4;Nz69)m;as;c@L%rYG`JCY zvu#GL_fvkXovG_pZ*%G1{Eg33UA{W-+zS&8y@Qid;$gGEX4iqgr0-`kNj>CGBhrFU zg}BV3K3aYKiyxF+*k| zX*Whl@kHZ*3tBrDt%9k?r}&Ppqw4V8)oAa+&Ppa&YW|6eK*iHE^yVU80P(G-n>OKR z0i1<){?H>|0-MlxLguWHJ2!&2t2}sD(ADyBD4oNUrm7A`R#8t)rK4Q5rt&ZFs@GwN z;VK0$V|v0?#tSt6lV!jWV`2duCT*0m8Riy0)I4S>i<`-qc@RB}&1a42cV@djfrk(OIiIoIcy@LaB-k{(Q&zeo#}~8n(Y@v*|x1t#S3axZHI{!oKtAWWM1BJl^??i z1@u3Dbo@yjs4c6RO1yP!OLvilEW)bcz0J* zw!^-4aJcSDLkF7ZmL~{~&*&N7>Hr~+RE*eCiIwlM6|fTJqqI&klG#AO==s+IuC){l zTcs|wJlod4f1awN`G$FrM3=_Q(@eA%*YF1ZM4MIWzYCoyUTbBFfvFaUZqOs2 z3D&_rVEFH!Gt2N80}0RXWm77cB5L_^NRyh8sWL*V;Snb(6zR4fh1%EH2o?pM6D6jn zs}&iScRv@NTz4LK4oRqYiY0S>0S1 z+t$Sh0luI(;X&qzX^)}&89la*`m0g(dFMp^I%;|x%<%3_k3F)nu2;kpl0r6zP!pki zw_U@1OtZJh)L$`8DKnn)w7G*BML+R{z;!*Zr-#&R}o9mj*N*t`w!=|P6frfOavU%s(w$4 zdAhd$9nQ@m&(5&ZQk428I?IH8NbLLb4R=*3v*$+Dc*2AU_MJu*w}1iu6h~c^do~#f zUG__BEdq2uv8UqDl6Rboj{jqe054cfOxT-XsGh+XfKk=y#oWZSmw~d5JgtoO(_s|H z@l2J?&kRI83lo1@K+)KF@o4glaT<^R%HLwevugLs9~XS6`@grBCVDWehX~7PpgvU4 zV)W||2@RqIUdU7T!}`8(AX}@kt*t zVLME%MP&8eVBo3{k$vUT$VZ{(*+)$!QBRKnlXp5eSpRqW3xNR+Mb~Kqh@e2z)eW_Y-PgfPqhH;*j0^wSRsJE-S}IR+C~SCBsZXX&I@Qjpl$2B% z%D+u^mu6pfl$D*%#dP*oaqgM4fO*@JCDGrUpNDj}IoPS^vNo~m_j%yp(5tQI9zw9X>M8fI~O+-Eq+=sqRo z)7`f+pP9SM7@tyO+lI0Vn~b_r5f0om&sy~xUFafQ0Nd)6`8V6sl(N1^rmH8F*l`)1s<3G ze53DyfnVO+zb+Y9l+0MWbv;V$*zvKSv3JmT{1MAEmRX>=-EzE119&>wA$)x?TEmW$ zvf9hDzrr-x{efr@2mg%mdQQo-!|gjz67JE2J$wywRw5rZ9iso74`)b$Rx&sAOc;Kw zv|E^sV|(?E#hGt{poZ(-j}1n=**qlmg5OPWPn-p72KuO|eO*)OYC5CMRbE5xB?#3d zhxo0MsdmTM{v1Lq22urYCBASxS7?{~uc+J4Sm!*k)9#h}Xw90<5^1f)f`GoIy3ziu z^UtKc-9f+l$r{-zjs+TBLbq&yYa#W3Dbwu03y_I_{g)eM8AC-hoDt>9?>YyVzxW{# zyzr0Ze2ySEJ_$`_DKt1X7KUGS`T|3P|BtM9@UN@ww!dSeNnz#0sco_j<)CF$^h`3-wMw_p7 zb>|{~^>DIQKKotQ++!6trVh8~;3p65reLtvnPnzA^`Jk!6(&B&VliLh^Wgvzu_oRQ z6YoSixva`>)}a&r)I4`frlJMK0?sp<*ILRbe6f;iekEX+E~3P82s6cyl-^`;=aPx( zJ$O!E5!ar#U?2DDy-~0`%LH;8`3yUM*SHk7OznNE^Oxr5vkfIbI46X0hGDcew!XE) z=Ax+VRyh{C4NA?qu43buhs&(BYPMFLdH+O*(tE26l*3bv%&6flS8^T(7f`9(GL)`v z7Pwx1tXG25pe5DZ?FdxETp8oqP#yp14&uE)*@WcB^Pp1YSpVEk?C2|dWHJJs*VyB` zGnjm>t@ZnELGdAg2}0iW=dXm_phFS==)! zxgG>&5@L3c^Q`7pm8XF+$|7R$kgV&vK8UGTQt)fhxmX;jBsnd6zo9&=5!qNBD=;U@ z*9YkEx|tV=mIHU$7&_bE-{zZ(;3}?4sMQrRqzvms`(~Z0)Ede4?9={OYPA1Es#E|h z@F$J0p;YOrwVTZTqEIyexZr2?SoDQkWEOO@JH0E0mSo+(=y`y~*R&9}aNl0hOujT| z5)g!YN&>e8geg{w$sV{{+FpL_9t>eh!!(KME~}q*QN8!OM4C6x-lY=~Tk z*Et=wtLY>FKwAJtCM^E@6> zf5%s!Mj9!VvnHeN5ABPYuMK^ft}xP$zF*I-(CDK5X?AOx4br?mSW3cNw8m;e@M45d zJ;M4{Q?;Q?A#t>7L|^09$Ou6Z7}!H_Q}J?|oHa4-5PoSvB zI7PW#*Q~vnx`Fr9q1R)1k;(L^ov!qNHzAS+G z?-teXdbEIzhTpir@}@y=j85wZ(ww`7v+9^%l(zp~>U|)YeEd}>b&3q}xRu0s1@L8+eF>(-*hE<|T-Oe0R&Zp&S2809{9Mh@Xv@pLGC&E|AZRQ~~-5Sqy)C)nht++``r& z{d&6SDdm6Y`msf$Hd*~=ME67}WP%d|L=dE$E9-#c_-z~hlC_t1Ktp%W*J zd6ZMSz0UJmh4H9epnhD_b*j&!mmC2sqUxzL%5g?JilUg7>ayw!1*aDx;N%kzX&9}36) z^rWX+)Pq`D__UR%{ewjM!Qx4T6~Lk2?7n*O+FWYGpI=|RET;R1IFE84)U%Wn?P)0l zx8UeKXzLe@?$`{L^9qgEG>+rH@91;XR+Iw&BimjT5iq~Bu=Z&i+&uG1_6%oy7-)4P z%h!7%eQ5*IzTW=omHHiKzCT~u?mP4k*HcueGH8NPqg_!4@exRA;G7(RMm9%%fMf0T zaG1Ep_`vPTOMT(Hq7?@_ikk1|2CeD6mi)f?&Q`!Zx2OAK&B3}7FDRm;m!^NBk_FY zw>_^~)6#wVr#1ilCx-kv`PuugbUb{oKXP*Fe?aHggHcytvwf*|cPZ&ZznwI0>A1Kq@MVy5h@$}L_PAQ|}1h-N~ z%sOUiDX6a}=bD#_(E_Q0t5!`YdOG@&2sN9}Vxy{&E95rzCWS%6~ihS4RPO{~8 z_x2}}1>gyPB0WYln${s}?rN$W!~o_vM2TOc*{=z-QenmEXl-3$Mv1Bsw}~zOXY&I2 znfC44p_7(gO^0c@A`Vx{E&tU{`H(T~WSR(LMGmi+kjvyt=~i*PCvNPwnXa(VLi)V+ z4uwkepmw13%bOXYZd7*$Sx@)PYQ?Jj;b+d5j`Pv$x zC!`<9A=%-r$5_RX8Z`SdN>>nR+N8GPZkMX7_+mQ0;>n+v7r(y=s?}{@ru`ljw7$PFHNVDu?t+BO%-wirB}0 zG7TXh&yI}XfB^Z_C7|Az9bRUCyrb~5l*F8u=32Hpm(at!q#VjHueXdMO7U%2u*JhS z;va+uqbd9i{hbX#h#dTDT2x-j9vF-wR)%`MV(SVU*f;zPnx64Wv}bMB$P4aO^|Gw! ziS$k!*GF!9osu|c@X!qC@Cv#zZekw|20nP|Q_Z>Ct@TE??vDHW>h9O*;*FwTN{o4i z6pwrZVg@;*c{;Ewog0muWE2^BL_;Fk|0#)|$`uv9OZVShXgkPcZ_=RnB?O~|j2?8z zT+}hT@FR)_m&5MU_(&1_*o1cwFcTCm`51oG1JV69=rlCpg3P}od{ka(qxM3!NBPT2 zEpZ&6TQ%ut2xU7Ugbi5}$TikK8_0v(u~0no-`cCq1KeMsbZm`S{g!gIeX^&S3S0AO z7M~7ewp(+AtS3grrc1njA9b~{i$3AB(E#PP_W?oU&(gi)Ofp>Y#0G=iN*5z<6r}=w z67GSN{pTP@)u1AK&o)WmiOC~)v4k;SAUpOqiY#y|mAjwWXJxRIgyZmG@xy^)8K9{2Io}Ql*HE^P8!eUsQ11u?B zoz9v1u@Sf;n)vC)ln~Bx1nU&=eqFVQBhIc{&l|y@f<6|huKyxC+j)D?(9sJ3$pgt9~4?6E2 zb#*w&U(Fj4mqvUl>XJ{{$+&OkG?B&{kVHMW5gf+sKSq#B{Uaey)x_`;`^(h*oZo*T zY*^IlI^%b-rPaf~vii}U#JSxgYMoNToZGT`Ibj-zfseF%2A3aHVOHHtz#v5=@wH4= z4Paobvl?PX9b+%ikrChY3$xuf!q>53h-XEI3@9QGJZolFZjt(__`6VJcNUl8c%U{W zwRd2ALyRRSjRY;fZn1< zk|LC>AGRxGeCiGjlnqItc^E!B!1EKsfs?A;LTkXp23>8_bnonfhmmmB?pip5ti@#* zmCcCK^d1?BuS|Goa#-PN4N3Y?o-GSeFcC<2-1%zvfvzzZOj~;291?L@6Fz(&`T5^6!g9=F=80gg&7 z!f_IyXbRFxfgj}JITgB*Fl|)VfUXEB1Re2ybJ4)4@IIOYqJJ&QbQ`!^q{jOR16%dO zAZFHz4cY1dXq){?ZRCPEBXhc156DEcTTR1bLKj$MJoaG%(^}XDrp&ob#%fq^kWPUg z@Ppa3yF}iw9^)yqT{Gbd7pb!N9W^N)7;&>JCLtF-Y7b5SerE5Y#?GLJG5yHQ{+Vav zVixwr<7D(#a8eW++yThIKg+hY^_93u%|@_kG7!v>2UwfxBq)6C%utTh%ND_j#2w|I zY|UzXz|m&qCtPEN$<<%)ItfV9Xcb&RxGJa{_{kvtN|8l_unIK*7xC%ttLG`Q^1PQ+ zz_@<)@IuGJcjtb^IbiVg^J4we4%_wZ^dROSJ`^|7A8fjzIV#V&L0mH4gX{`j18|+7 zN{M}ampQ%r&7vQ&oXR$>qy56!EzAeXdlND7UQe?ef&~r=CK@%Icf0wI*Sn+=a^39s zrk;h#hR+p%EqKF88UtatZp47MZ;4(Z3p|n6d}~MnVM>m`f2OE?u3hPk$W(~Gn(s% zp{4myFFqCh7+=Z}x?OVgv%RFC){6Au&YLx)Q)WR(J3TQz2Zx)Q(|~pdgDpS(=$E0! z0@ew^^4u8u7{c2#DA zA{hC5b&gS>C3mK(py*D9Z(UH4dE>~<(t_AqZ1n4FYX*2X6c9!w1~9n{c3uCqctA?) zBwyTmVbFXSuabx=P^zE)Nn_feoPEq;-i4bQvZS2XDQP9+(D@qX%0i?XNG`C3XoiCqx9vl6!6$mif7T z;=U!!K({nDzV|nyY_dm=s(r!Y@Asw&3@a+~UURJHvQzNxV#Z9x-`?tePQ>Rojg}t?dF}96#%!xhY2?^u-Hs2$2wXUb6`|4PM*N zezep^nUAOFHaX29PH`cImMXO~R$|PxW>nE*y}~t@Vl|I03n%yKa)>!ipq@xa}t9{|K*J ze?nsJ$cG9%I-}ag2wZY7s`^cu^;jF{(a0N8;@yNdLql?aB}A+_EVov!prJ=f8$?gc zhsCuCPq!*75ZIWsMg2+tGxu$05(Vtr06Hn(Rius~QJ;aCCSrd!I=8@bA#RV*D4O_H zBdt%xvFEf~X{La1$r>JbRfGD~W#ZoY1N9%qW!}9v1^Im85A39| zzXv{tF57SWH7x1L+6@9DmIxNO*{+UMVXi(DPYJvM=fswFU%=e|+V%bOmY>SDVY1vY zi$#=F$u!@!D;t=;@B?^oN6#5lU~fl<*9oxlBOx7=HAp%;8=h+yvH$|yYJaSWLXdo~2CC~7hXcI<{XTk4dkU3VSMjYG{gX)$J@cZXB^q&{ zQV26G(jik_!O>H_MYke8re0<34q-{TaoOegsz2XC@LNg;?oB5fL%jVcjnE0+RmI?6 zzf|=S#L0h9;Rso|nr^g|pNE${d$*fmwz~6RMM8lN+?ZyLt81kXY>id~s{Pv@J%xO~ zi9z@w1^G#(DCVkv=>B%TS)b8LO7e-?_5Ds$ekidWc$~~CjRDm%vfV4KW^`VRqd1V= zwdi<|d~%cbtvG$3m3}}K$pqofhnd#YMw_f9^$T)qNHy+ErQ4NFjdw!=+GV6zz;% zdx-IgDCND}o=M%$V7pBB+|Ds@FCI`J7z$#C04I)nT59$%vXIqK{xlUVHlwAXwk|nx z+ok+fvy#pH*+c92wNiWOpS^XD7NB+7kDzIYTONLhP@09EeC%8sKZlPMIYlud3-Kcf zS=Mg#hO@3STtuD%o~Y84W_g@1*Rq8EmC8Vgzs=uXrm<_8#|2UBMJVl&iy- zXckU3&N2wNez(#+0e{Gvbmh&Cr>vOsC@2T_nlCK&-`^LCCIwKpT`5>7Z<*@0g>XhH zc6ltJr3za_R50yn^Om`PRRSe*$s{u=(3z?4RDEc?P_Kd=`>mp|9;v{rvjR|(Xls$pB|>t;z8wufk(szZqZ{w2la3LM$!(yxqDSc z2v1J*Rt0OHSA{Lf+mA&#o{0aUOj4}*aAZu)yLR(PX3zY5D|_90Wa2%G%v*F~g;pwf z09#>(G>J%u?)H{Ypk*TnGT87#sNY098yl}2iq=d4xn{*QBz7;v7Diu5c@mNX7^h7VrB zuuLCm+IbKENcS#`9l-j6t8yM?Cq9W7FmtB)0M6Fg#Z&wcKBYv@X>+Qq0SbjjZDuf6 zRn%BN-7>kTbfe)5TbJE$H%KKVn%DN3jvekNdh&mu$Cb(!^S<00EA~RI7Pf;2S~b(X zXX1Gj1dlu%_Bjvqy9g_^jhFeAsXCUbG7IPB_@P6i%`p58L zzh_JQ{Cqpsv)CfBwtl+-cz8L#&aF(E-Q6bXs!Ux(iuMbANs5*#i5-HlInb%*Sa5#oT-DN23 z+d2$`-!tjpO}mI4j_65oD~jQjHw8d~j!)S zBV7pKeLc%0p8+{NmzFm(s0GjexfC`PJwJ^o3EG}-zvr<1^1=30*%6s3X%VWsq4U$p z)U=7?1(brRR4D{%sw$UBhDg}~PFofwWxsef6aA>mILl7)RaVdlP zRwF3R6D@;)2s;y&*;=awAb&4{>9PfReQ$+nWO&4zZtQLJ!`8PN@|UdAQas$oeZ_Ne zdgmdpeO(?AwM3l9TU;I@OLGCdddNJg&5KX~-n2sZz8~r#-T> zxGvqVb}LnfO9C*Oa1r`t+J}9WJS!$$3_Qe~D}}7Jrr~!BBtI@s7YEtdGG-p5uNdx{ zrUXE|Ww5`iVFl%a>A0BCJO5R(IxgXm)k4+jHMX-zCzE9rNGG^m1Rn@N(f@muy#NaTg_fZutha-q>8z(_YV&xy%0{HX7_W^JX3qLQL#&%@Lb^kqe z#96VxmC&<_l_OddsFh0TKF(ZW$eX@k+GrDLY=lVMLHXtOzIPsuOs}bbidNB~G!x~a z?p^vc!m3liHX{o+&t!euvqaN!s`keBTQ_3~-Hrs~g)@jzd^~hy3+;>Or@&+_{qC+W zPcgXIWvZQGS7{?nO|^AyJ&$tyzt8u1iNZG~n5PXx<885hlIJiXCnY<7*g`~m^h`ZWmPr{F*g%A4SxG2PC7f4QA1 zOZjEAf|8cAldR!W3#$JebzvT*JKK0gHc#kSs>LhN4}RKw9bq64kLQ z>c4>yej=s~A5fu9mVtb#YmwZym-wE0I|ygPLwJ|9oezjv7gXdJfYV!^$U{OSx~f(8 z(x-0YkM?}?LE`pWhqs|Ern=#0gtSp+3yFWu1Tqi2r%9RE&NTQtN&eDR)Pfn-7fa>C z}IrAJdvbd6jjincSXb=X7&GG|rcC zdF25d_H**<^8eP$PlN*d@-`qhf*4@r*fP*c`dW4ycWw&Z7k)dXBx4U4uE=<2+}Rth z4$s_g#!>=fH}cZLo~lyF2Z%63#-S+3qjbnX%8fgmS70V0Qbx0S`7n-8Yi(P$G(`0G zj=@ukX;4Shy4FDVebjGE`W8YT#%}oMrPa-mw?czFDk3&A@8~wjlP|Tyq)NdabWy9! zkIN>clxW~ucFaXzD%b@dT5R0Gg%OT!lOAu*;XTTQ;Q^b?m!?!RO4F%K-Df|}j>7EU zEe`~-c?d4<<<}uf#{L03U{$-ihD54&@TzItbI80Z<0Ks6T5;y4**M2o!}8i=E7|>w z%rnPxD_oxb8dzl`rd{Y&i)h4LqF zVE)H+*3gTmTcKo*dnI;gFp!jfTRa4eKT`ag2d!_0qb>J^4VbI8`V_X6eo|%tSR2$#oUl-i%!Z}K<<}o9 z>(==a4XzV)o8Y}dPGtz+rR!^rrnM{d|2l4pzB!mph$ajWdH()9A*o~-w({v=t2I-L zYX;;d>r=y3aC}Au2yuN;wPy^SjGAs4^&e=sryVDZL9;DJZ76kyshFu>kGu(Qr%PkM zbOupU2r)@Al+=O1qs!l$CTTdZTP9LjTJq9-EX9_z6JJl5ZmfmHi#ki=YLo(TRA(lZ zK(%vWq-3IVg)0S#M@`xPU`{I-_%j&Vo-)JN{>-NAkK}jB9lFAskf7r{bpPROrmTh(z-ikF++8;b*T=a;pR z6s5|f=|CJ>IBJ4iXvWHI4*OfV5&oJAWy7akG!d>|9x|ra7P_2;2WW*JxvpSH;CT^y zJ=u|8hA>1$Crgx{6SD=`ih=9XRZmK)JFIex`xJLvzG2uU*~N4?@|w~=~f=fYSIcR3nKFrfeX zCH_{!UKApu#{d^VFDFZ{C zz>$YjRAk~+{)-+U!kZCo$>1zi_0rnIPInH4$5zX|t7b$Hp$Q6w=fw4XWTbVqe#om{ za-)${b?;N<*ds5|G2N_`_Y}X%#z$}||GQFeH1X%T4z(R50$B{N0K+}EQ3ewn;XG%S z&reUmkWvb{79;t&G|8SGmvtYh^jWRKR2_MErC^T78+g0&1_3Rc%#`;fY^CE=%t8K{ zM-MK+p<952;iRN0vXO*3ABSZe;#kXWOk?_IssG}J+oE`$aOLC0oYA%O|!;vD;1 zd~R8X%Sc)uutu1()T?MhwV$J}nhxFd)wn7W#hZ@6^A`My8c4KgXx(OYX#1H>ioYnq z>m#xo*lt&&1XmiVbfjFGU+)E`r})~peLto{V;ROn)6w-tFmlpj12FH4AaY%#MKhF- zc%}&J%Eqla33&B6WmNwX;;zJjUg1v?7P?kV3af(nSj&AbtWX`9e`o9`2+n7vwj}Mv z;-C}Q)6cipiR5{*hj63~TvdL4|5&%bie0~aU8x0g{?IVp_{#s6aj0DIm`AW5C0n87 zhavO*06|=#xrDH{(l|FUnHTHwM^=Tb1BqUXwb#7k_3RbWhLk6pMyH0m5Pr$xL?D%9 zHyFhG%C1t9|J4BoU6_rBCvbs$;vP;hXq`KF(azDn`Bjc4Dy759flMPW2N=AoVGr1O zg7m}UJF5cZw!@E-GlnF}wt9VM^&6$CSJ$_$9Vm0UPR3N~cQ_jwsTMnpEkbMM}^ z86a4-HF5$;`H(PgH$+o3a{GlfV1r1iE;WPof!bguyT2_tkM+pzKb)Bo-;JfU`5PZI z=Ax&t*yOefWAZ<$tIv?x4>YDu=p2I)<@XW`qs6QD3u`F?^hu=%c6}zcT3gHTSM7L$ z8)zZrVB=Q4C{dvDyqO=W*5ID)^eQOTW?CLC3V0rz;siI^`G>V%}RF@*jyLksOQB27)DW1>AL1xf+{*lf@VAd`C z(eRiAC>kRy1jF-LLkp5yJ+1hHAm_f=ML@fV{+TsgiyGB?lZdO2QMfhHUkqTk4Fn<*8KuOYhYcn@;6t&10Fhi*#PQ{Pb~ZZt5BFTOW`xbn{|rq8~LN z@3D3mQ)uN*CsqHHbq$dOe(l zf^(VV6(rd}r{l%kC@~|v2pz#^8=v=MP@wg{fOR;X3V9L9sX_%h(Cu}i2zkK1z#Fz0?o12=o z1LAY4FYlk(uM#ZmR%sK-KXg(X#qzeqND+|<4uimqywLGE}j)jZPch_sK-%3kmoJ)vXJ7Mz-a^*CRbEI$~#hShZ zc_+uL2G0fZAwJ(0vN0!lu9+)fazt*_m%M4^tLHzP^R1b>jgM^iPDO)D?Tjy&^7W(gnOsQpYyE1N~(q|P$R`Tnqq7JFlx z-G(vT&zcE&U4iQM6d>B?{-Ec+zK zAj*Z$XEJ^_q_n(6ym!5)D^U_(M3*N%)Z9HLA3S(XcdV*eK(}6uM^C!GFjoB0GCj(6 zg3A7?H_F1-xlV#t)e*x&@EubEi{Q+9u!x6c;8!~yA!5Gk=;s(SvxMItrHs|c%$y&~ z`76pLL5hi=0eobkxSD3_{`L312`0bpF4-;=c{Ru*?z|t&+&dzCODz-A5whepHI#1; z$q%POA3yn6Sp^V`sw^-kZSl)jr;&U%>=}qBfhr%GWG6H>R^-E@;f&EV5*-0`uqJ=W zle6K{Vgk@rb`p|l$@a*D`(DVIx#jWc=lzq`DyN(4>%Wg}I%$Q%9@qo%eC{{MObuMu z+N_q2?8!Pd_!qw(FZylKzb8j53(Rw(C4lp~7qjq0#DIOgV?k@b6`Io<|D-wkP=j6> zX(d2&8Ri5noTR=7KVpocsC&B=uF)k^zcZC?s+T>EMuQeJ#GB__e=L->yMgMKan{%Gv3ky0;~hLptFu1kruF^kj4*d#QPZ#aeuz{^lHLoeY(N7 ztIFN$}uRN-P@;ijnUboMC;Ft7gT zceTrpI!y8F^4n`WJarCU{l$;+>GpPvZ%MM6By^yx8zl13maqX9E{`DRKxDRHZhEiP zJr$j-f<0O~x2cmFA@B$W4jh!8<=gS|!!>*R_b#!AH|e z^2hi9_ri9yc2;(lB%{4#QS)a?zD<yzO&7CqWu)BQzg9X|#*F)%u8vl_sg$p$LBpO!SB&&_FbxmXSCs0y#n&{1Ne`HA4b@bYEd4<(C~ zc5o7m;#HGu2E}*5g5R@QD)?70FuUo(im8YW9hkmyc)^gH;mod1sgz=jObP3`f>Hf5 zPSddke_0zsP3FA*VljKxX`QCXWB-3x4prQe4;5UVjGl6ZJ*f8*Zo-P1)n#AQ(+yZ* zoK0Nw#H8)#jocW8*jwk%^a#ZHL=|qNm0vxHdTz1DAq{^y+hjwgO>zo)HF02UQk02; z9cpHAzRKM|)GOcA`iGFAUfRXhanO~WsT{F8==d+RZF1Ag-DgOR^0C#X!yhE_DUL$H zKZQTiNA|S{%SQ98vRQp$zwOoa*dk`|l}n9%T!)Wnu~`{~Cag2>uDbtoqpj(*NP2#P z-elUN(TcsBj7HiGm=v)N?#=8`)flI-(xn{u)s+i*n`)v8SWV2lp{2($g61QHWx}BE z;9Q5zeu2(dz!wk2?H#n1iAhzTQhLFRAi6ZXR|9VzP zkw@VwjD&G9hBa6-U@8lFBtZWr4_Unpt7Ng#(L}FtZnvMy(Do5j!e3D8OU52a6b%7f zxkf-8_mD82uLrdI&2`goURYWaX`Up)g>|xAGi_@<)jXq8)794HESs9KVwCp<|EgP4 z+qB<2DERBl{BF$Wu!Y2sMGxfc0L219q-xcIrHv*7y-76$8_*b4O&L>v@+}+7sq2Ri zG4&FR#keqUXK@4^fp%C&4aD&jb<5_N*KbAJUs_=TymQY2lW|N}c?fQtw8UZ5BMlZ#`5$|r1_bz)bp~b}&<7`y1 zBN>?@Dn4_-%LktTxZry>-`@k5C^Fd4=91?w7;flr+WU2H{wVvqavWicsOzeV%!wC9 zrhgf3ouI|2@(-vJorj^p^5KE!G|2k~7dbvk*c_vAX(oc))($UR_g972iyQ;lXl70; z^e2gY8?<#@x&!az4tOxPCpzsh)c^it<>gKN6!Goosd3_V*QU;>0ROeJM9X`t0RJS? zvh>%@1-!#1Z#mkKmYgO+qP}$0{oyDA6mqMyAQ&+j;eSwD4@y-_!E z;Q*jA1dar2Dp5r4E6IzL@f4D^$no&){bBl4BhA;!3-taMq2KDAgIA>N4fQ?`sKHmw zp5)&$SZw7dfP@`2b3ESXN|H}$!+-rxvZ2!^c z#-a(825$7WM#s*s(=6);x~GITU1o z!JupncX-iu{Adw~O2KOu#y1;hYpb_0Z2nz7WaE~bS}aBVrD46Xpbe$idcGGz81>#v zU>#@6^HA&RL_8OAquJ zU>kB79ZrtJrht+jhWY%4D8re!bm_s)m!lejKE#eO@l1xEb!V z7?KpAh#S-E{@h!Y!@`!o7dkgIprmDYW2iG_5Z;833+6}qbI_4?`62J}3W_&h zslk9|5>gX2B&T)8u_Fq<^cIlAWD&}Nd|@bS7b!1J7>Np|E$u$mlahHlSti-p>;u1) zmoA)4?tedK7&q87D=!%vXNI*DR6gJIpvs2$mA22oG@_T1@%a8ib>Wd=ECoDPA5JnU zT6u2O4B9l9H*BD*=8O=FS#@`higmen8F{U~K)Va&?^qU2_Iw#04NiSE&j)93AYaM3 zUeDt-P3}2K8Lp;^l1|QB*eE?i;O<5|o#Qt=(+au}G$ooOshzXr$B-!Q-pBnN{}&&x zM0C@d{dHO28Zk~}nBML_qdE(Ho#x&<|EuhN%C}U&D#)LthCCBYOrNb8(tZL@q8>%T z(qd(zJ3v%RNJ_asuZ*fQ3&x-JJ#+wcs+0uZK)~ThcnMtRTZ6PIA&Vse;cWN>^quYd z7aZA-c_xp$Vr)pf?)~=FD;7$`EL^ur$=-R5Ymk-u=h65XG{$O-iWUANVWr8RT0n)X zZ}x0iL5zK7$G&&%gG$$*F=V1(Z@P{3i{`5G8@x1fm4RQ{xeWMm%z;kol{@Lm1-W?A9U*OD%O8=@df<2_zOtn&^gb zAE90P>eaI0G-wgl8*weZsH`7%d&$3&u-~J1Q;!Q!@);L)b2zXy$hponoc$y!)&}l+ zd!$#_9Wz4(^ehoZF)bfabU3v}Nqm<5BKk|hDifpY@<4d3;T-z6V9H7UfoJBGGe~>3 zwR>m{GItoCkvab|h5RhySnvnd2*e_GvT)ef{94{0#=d(=Oa>PWH z#=vu(zDg*Kro9bqBL!Rqd@CkzwTa8{Uu<4dkMDi6K zkMEvgNp+`Da-S4zx^J6~4h`2HGxKoi}Bi1qJ~s!GSq*_-lqQZ2B#-FY}cvXAdwS0T<=t|Kxg z{`#p$dKldQSa{ajpM!q+gqT1ym48fsk#N?sVwpZWr!~*|<3mebb3&T&wQJQ~S~$J| zivo;lPmLme-pSn=gweV1kr7wXNU*Du-bg^wO2Duv#g>7HDZe6`OKP_8@cE7^O%x>0 zX`Wi>Q5+_S*I`BXCobs^1ktC7inl2dXQwr=AAFhTze-UKQW=^nMl)FB%XzFlPu?WJ zL3r0~ry8v_nmGJGC+m>oEh~n-9RI;@XfF3IwqU*O#kca2a_Hyh|5Dd{cCJOxu`%7o zTLOZDVHiC0@Ve>yO0nGu+x<&Nud$~->117cTf|KJTRjWbNMGcw@c|L>SU0F*-H7nP z+FZHKOKV{grcPpUOC%N-nhD3luFU5-bBqrv?!pfdh_9|}4Q(oz z!JJ56`J0+=6;d-Ge)c6r_^D8mZ0@|p{8F-^T+chC%2l)!p%+#9h^sroeKJQyZ-h)QpQKjxnpnG&8uR~o)%*?CEvk-uG zRwW{$l)L$*E#G$6MKxVE$mF}?^|FBFsb9V1-Zg&%I-gq#KBFgf4Y3x=tFl}}OOot3 za7YGD?SND;Qee93-KOro4*O`w1vN5s6*9QGI&)voh#Nx}*4(LNt<@@Oh7_4jaWlJ{ zYC0w(y^PTp1=|blP2HMZc9FY{74A<^yBc`rg8X*9H3JH9uVeCSY5!Ff9S@aq}BZ|YsRkw;_gi7+Agiv z1lhsBW$N1nh4W`JIQqC&B~cS~m@VMFdLQsJ!0)JUXf|oOrsv5B;ywF!5I{$&Psy+W z6B!J#03ask_+)C}QU-OU6n?Nye{gpQFrSkap7gH$R*-OcShn~5G`VSi-gdM)XV#aM zULvW%8wBOJpp5a6=PEknGe{77XEQVic@=h|4{i{ABsj6^y$ay$022xEA$@IHR1Im$ zgq08Tel_dXKqx|r1_3&+W@za0-B(Fj)}J6m1ywPP+OqP`pCVz2%Na+uzgmnPnoc$@ zd(MHGt6=N}tTd+qNuRpnU`kM*=a6t4n7mERTTzQ$9nR66AtRDHmS8DP(M!gBPD+8Q zPyv1YjYa_1l=fL9K9dZT7YP7fbWP2!Y3zGMpvQoCDN->@aG#xK5zi)8Zc|&=I8Xg4 zQZSq)f-~t8?{9g_AR~sh$=EQK^95UZW7{W?dGjp9;LFG5z0YWe$GgIFp7*aiZV~(V z`a+sttaJ)M^#ERCN$Ulp;sP1=sHR2?@%|Lkx%6jR(d!2$Nb#iPmh*~W6rg|5$8Hh+ zU&mQMh=kkP!~)Z9qoTtn4|Pznh8p6@J9(FiFqp^?&!iS)hPMpB67_n zr{@Y7#-Yv{qoxJ9{1jq1RLD3lg_SIJ{PS}j*1=yL)QZ^g9E|O8{l={=gTzQ(A$fiH z`W$)vF?9l%I$3piB}in4zqlzIO{Zl>cAl6VcHRPIck^4LZH=K%qWW&<%GVzyS5htl zd1C3*5{y|WbsU^Z`vH>IVpH9zueE4o3_iU$H8ay)Y4%*1e~PvKSR}vs7uG+hF5mY7rI2SN|;#eqeFTc(` zCR@V}=U>4Ycx`;S(RO?LJEi48q+hc$Q$>EkaWu6@9T?4xNG45LF*P;Dag8M%*JOxm zNB~Bx%D&$p1RqC_t|E?PTmFa4O}!cP0>R}E|2L<8#I`+BKJTOfxoyOrOGf#XTu-;r zltu)M)@Yr*dp5TtJxa}-C+mYRu~;pSO$E=m-&Yg^VldWM#`XbG0=#oezL?UMv=W|a z!VC*$N$x%+AfLYIEAe>n9!CB?O!fxL?(La97j$h_>0lH=@zjU05#~ETzQUh`BJ08Q^n0tmcPW63R?KepMCTH#_{|fopQSj1__! z5YFk$0?hun;}c-8Bq|CQw6e#`KHoO#KivMrhrFv7gh-C3Q)DXH(z4MK|Du;2^pYf! zjaY2KU0FPDYH7XcmG)ZV@lUeJ+D|mgQ2-}num&FfJy(SuM;W?#O$*CUTT3!zGrpv$ zft-8@NS+RgeW%+vk3Z!&$2Y83EDlB8s9zHZt^;Ys&L(FB=*Y8KcW?p`^J~I7lF_|= z{XmrucIV60G;;m>LfBmJ)-09D$gCNq_ilbd%pOBftnZ3gYLK2tBbQd9ND@+cdOrtS z0WJPNs?Nc&uCCkqaT?od8{25?G`4Nqwoj7AP8!?EiLHi>ZQJIT=ic{zPu~CFoW0hb zYt6aGZ;X9;1{3l52pS06A4u5XMCgToVf&iifwa75fQ}xyiKm(&(bNjbVt5v?Ed{?H z`cW@o3QU?`P^{iAx{?YQ$CP57d&` z`eTNvJLojLKJVW1>*gfx>X{1gDVGK)-AURDp%pqJ>ggK;81|S2nv&bRU-PWG2x?ey z$-G2sA6TX~Sx>i0$;wBtpw9N^<1o-P>jt=}p*uY~Kd)&nS|>vy%^eJQKiCFHCx$U@ z_(+yxg#$Tv>(T1QNV^qW9(vzQP!!}%g~#%I-Hf&8(y9C*KCexf@C+c_D@C{AK&HW{ z%AoVynh`9U3ihW;)2VsWdf4l;T@U|~R9c5=^TlC{sTVSk96r2+4q*#aEwTN!uge-S z<^7^>(9HlHP^I` z@YbeZPZ3p?t!@Na&_sJ@sO9)ng&TErRYz!1&uTCUviL^fAHKX`r151NQT2k*vWK*; zi8vH55L!6w+-nSw{D~1PD^9oODL#|Z7W7yaSh4)M@1nA{&Tf=;(mG7_%*|K*E7Wbw zS8f4ZHe&FxeZ|=k0?wM6OSIIb^o!S?Lgq{`{aXYi4g?&S&vO_+*BrHy;dq|*xqKhN z1%Pf|&1!i=*8fHbTlV*hSj*(ZPvXSn+%Qf~NQH&2bS4iB(&-dpAV=@7NGeC7Gy#n8 zvgT%%8$Q_4*hRQ-?W zQOEc$iS)v8>2N|tCl>2!&-Vl8<#sEFyYhOscNbe9|JlRG&NJ@-qqpMQMfldslQ z27`5YYDb~xlr^fOeMHG{FsW=Dj*W;E93^0Tw8WdSdy8m67mtl2)(znGlT_&6i}?d# zpM;BeS1CzepKA58CX`Q*}+505)rg5S;P}REB{NYR^9y{$@dn!~M zoyy^7Xpso5Y4lc@LzGr{HYXUy-yf?VV!HH8l~y?LjuR;=Zo%mh{ue27?_&eE{ZXfd zc4C@YFh!=Yg?r|yqXc!3&Cq+7uURTQbVCvY71Uq%iigmXlO*g_em88k5x47>cLhqLK}OL3g#lsJAWQc z;Tn3e|I&ulZ>kP zwk*;xm*MRKwMELEqIN)c#^{Ut=`0ESlD8q`mYZ z*_lNi=Bq~iqcSS>iTQ<=Aooe_cGMUc1L6=88quEI`r z1pBO1r+#}6GH~*1m)l!;9gd}>J+?Qaaoa)B@yjQK9B*=n&j_*~!ccFTB5taEmpQ=d zs@BhU7mmoM0()+dsw<@`83wBKuqDq~NO6L9Jr8%mOPRI$Ppbg@FwifaIlwtH{r#_( z4*FQDCdDfh0NuNJ#VXcwKwqx9lk2$k%{jd{sM>;Rz=Pz7xhOQm*}|);dl_u${|4ykX51HqkazYWYf34{KI()%U0EjK* z*Pi7{#=yw_5i(inFK5%*P+W(PEEvI)7MNQlH>i<_8)Q8-AK5Q72$wHwsI^1>^>0!x&fkZK*6 zV^MW`l0i}kCUwRsJu0#Pji$~J`U5XA_7?`JX2w|+#`=pD_f<3CJSuL^xBHWh_q_AF zVtQ#Bl!~-9(R!dQw{~aNqlvV-=2N(jgH0;Pi$$h9xk{^0`n_PflKwf>b8G>Pez*D33McjkD;M;`opGMqmf`$ zOEXE%UVC+hH*tY_rZi}&wL7C6#KYB29>v$`<5eN5aH@5sx}*>vH_fj)=porm^{C8| z7OABBLe4Ad9&{|PXbS$7?j4jndiLEgfDqD3 zVTG06OUb8weA$i9L-4NbEj%p!`1YWMO$07`!e;^2C9KYBeq~+%dUQB2pG(wI-~~76 zq=HRh@%Zi+Lq>?J?#ro?ATM2W4^7{F-xIz5KLC5N_r+DsTJ zgL#Mbrq=s1!(CagTY#;nSiU2l7Sgl{RFqmF1yPDrd^_)!H}=+}H!&o9F-5U@=8p$= z`Q2Juu&-j(0QP7_o&h<@JPs>729IBk5SFJvr7|(Ma>Cm zcF>)yCt_FSr22*ly#=$ggxGH%Xs_BuOty{tmZ%i0j_|=O)OF6mbs(g>2GRp)i;N~o zQAP><$ZDnR%H0|yoV;Rx5&b|Z4OMyT4p6$NR8tZadO9$^-I}(iVlXS1M)%7>Wt7YN zym8=lV)BgU<^S6xlF)?R#9% zskuK@ru-NOL;$VdrCc@-3}mr}et7HH4*2=aURRwPwTLi0aAR?#WliIZQ_?_$PYUQ3 zTW~p|Ss7B&9vmw6##4rW0Z9Jl^C2LFJ8vhK+;zB>1o0J z5AajLs`J0V4;X0ZGRYz2l|q59+uesGe89vJcir5&sx=DHAa%g4H`%(90k(gw<$ezP zKh(fK9|iY9@nl`1Rr)2;ysp#0TFyiTp9Z|dwojWpcxi>7sObUSP9LTTdfXd{2K*ob zw(cK-a}}a42sQv#(f!flAM&4-zvzeR&;t*$T_y6nh1&=Em9ymeSdk@EjV+z)Wha6e%|>ftYmd4o zUY)q+_GJ%_emhQB@leS_N;7ILx@fLp*{sH8*w6#e1A+0f=-k`VpXwof#~utncz_yA z!*8@WvdM;#^zcDbYYo#FaQ~A<&!a^aeJv%6CDMJ57XfA`O{GHE{a`Q63AeM?J#*Sx9kHX+%J2sbzPK*SeaAyz1qTAjSXj)1`!meOQ8VL%5 zDW)2XfV%i+2JTogJgzM{qCncS7kx{}_ysF~skv^flw$;64o%2;6(8EOfuaKPO5y%o zTItE7Lc?6H@jj?PfT6`6Q{oXU9&LwejHY&@@%qp1K$b_Jx{fS2B~GMUx)!WpuOlv3 z%Yn(ZSFzsZ!A&&ryH8^WQ=vWPIc3(d_qma!ttWKrMhvkU^7Ce%{ZNnHyA6_v8h-}% zCQZ|sq?-kw&CP6I6-uioV?~P4Nfzrb>*r^=)#FSi#36d}ZPt=2(PpHe;19DpX+TEN z8NEV6N9Q3xf!9%1^E7H&A@OT;gYEm%AC$l3Ok-1db$&>9rooCTSsKvoEuGSc{>SX~ zV+Lt+76{tngh%VGTnBZ-a0gR09 zvyU?|u_e(s2T+kHAJpb1Q1g9(qT=5RP1a@Frf{@+&@^^@#T32t;cn?#gb#U0huu66 z8jjrhP`(KzQNAxBfwi{5*QjD>ew1Z5tcL|hiAx(@KE^HQ@7|uM&xHk^;t-(6urUBr z|G!ox%r-u@?&hfN9k=%I;0ibibkpt;Cl@;C+`A}2P27eOQOn_jDphlLBz}~S9!pHH zg51%tFo8Kwzh3*Ph|p3`I3?-Jwfpguq+Lhu{t~jBzYNosUmm?!{+XWL{3GZhZ@*2& zTtY*=A%cSZBAl3gpYhc+gJ31)ol$#KyG}P~vu@_>zZdXYNM7akz1;?5TkT{x*yDMh zZ@D&pU{fw9Zve}1VE$wLk|YeGRwhnUy`UdotxPkeJX{&sR>~N{er~8SpgavywR5y> z!X|R-Yuj8K*qKBWMsOM4M7lS7w#*r-5?+Xs_2p+xWyNh@uc$*f)l5ky!FzW)D4M4H zw^Nq1o%ifq*HCgic}#=xGPW@0NsYO}&DY*OzO;o%Y$-Jnd`R{T zy9=^vcIp@SIrFyAeM2`mBG7dCwX?^5sxv-3kS4)+alLGnB4)VRS*S}jHvcK7=4{hTx8y1mb#F+PGdtecQR`+?Ty$%s&F;~LCCF+)jPgD z^4mhO0n)YNnEXFrj>9Yz=ey74a+>vd3_r?QlpT2o>SYC6qywn)@)iMnP8fm5_j9zO z)%SLZ8nhkb-BS~WJ)lzIs~l*=n2>{lBdwit$%e`$r93vB>$cba?&*f1gufA3)5%?r z6;n?fmOc8S)1$sHn7ZYC=hifj#!oK#HF1(|DzIl|7ev?#Tq$TNRgm0sR@Mh`b6hZD z>C%43EJz}3!cu4)15$0qXOJH9AK{`D0D|SF zjEfHyJ;v-G#)3il7DQwTm%_qs1e$oY?qurAY`h{Ms-JShrfGNpe|~C_io`8QmcKG) zHrmAvuG8UXcX->>2H zymLcxp;VShUwyvOHDaRHb;5+%Pz?WWn=i2^~{$Uom=GZckpvg1lmU>S18SM}+B?2;y$=#Q7 zG^K^MHv?%e*_w4M zBFt(YayOwJahB0^7r|n5ZfUS!mO8y21W_qV{_i*x{L+-9^js^?yF4wNz281dXNW(N zXmlb4twg&v6ek8dLVXyy6pc2X>r6v5&Pcq|gqK*yn(t=tePhz2W#iN%>25pM*&tJRib3%=4t@a-Nw3dl~ylg>m z34eC#5ws4!&-!|tt~}%mONmX{yRH(QAZJqS<=QOQmg<&i=p$;LXLYFRP%k7JyU%=B z#>THGX|tqWJ z_5%ANQF)GSvu(DT;}kZ?{xk`;eK|u=IKse^vqbx3>t;UXQb+E0j>jNGW%(?pTt1M8 z%7q!j{vsJPTpdF%Ah!G^wUMFC=?%8cfYJVOqOC z8~{@N#|@Um<$Mw%+rG$RyltLQ)_+fM3myRFytD<-B>nh`zkFLrv`AUtPS ztyL%9euPO}hf)DUSVMccL~B|aItH6cxd&9~sbn^ZyScn-@{l7&H5@}Jd~PS}OJ8PP zunM$C(nz(3yfk5cF90Plzg12U;T=B*)WELiFll?J1SA6cg-n`TeF7gO}!uok6s z07$u+rI=%BFHr5RvK``lGmFM%T78guZcBA&=Tz8~ERFhEpufQVLB71@6I#7A2TSHI z6Rt1chR|_JX;1BInV~0X1y_6cDEWgu zXK@UAxS_-BT+Fc{EiHs8Ovhs?tv3MPl2nrpnKf5=a_L6P9~n-_+cY>U{9Tt$QV`@TVoej5a2s2CVm zxG(Xf_jk(0kKmPbqUVVor6jXBZt+$_+mp(mt}*SKIY4*H-Gb62q61gdc@4KN{Pl%v z#wF_7BTbkbF=si;pnLj(q?qo2tcqiu)s0NqRZd8y^t*eeSDoX2j&t#Fjm~$2rxOAp z8SHGM0moz#-^(mRO`a3_DqNI=Zm?u=><~~NHI=AK#Rdy)-GW9lBo;EIvZRIqmja?7 zhAdXk?vR?A4jac+?hsP8vX4nCLLF4(>dve(g4(BHSCzot>tc^?xXrTJ|ILF187o15b)W zOMRsERvv;#ZRoj||8Opc=nMHbjgF{4d4|Pi^d^vO;mhE`AWy>s^K-54F3J}TFRG~2 z(GO-V6@m+?7?Znl)xtmV)ZieZLh5XF$A$R?>Tj4>2Ar~XL|?7u*P0*hPz|q73 zJr&0uv_MKbb?urV(!&=TicIK}v8Qb3C7ANvFLO$@*g(aY1iV(|sRSwF352Nz&oW_4Mpt$sUX-?C^Y}jNu{o;f0;oI>1v+S5XppaypFa>CsBN zp-Zo;Fa0IBD97m51FCwtbV6IIvYoV9$L$+3Ks2q|E^nq5dE`7&k!!gKf;#?GZ#>J; z?*SxQtV_gz3d~nCcBtt{v3HDv_Wx0P2#{fx%ftS%_2;N2jNN0~8Myw8EqhfbM79gx&- z7;tJbp4+P@)~2|Z!S_X(H3eyf+fTeJfE;YE*aZ2*xWtj3gVY^_+Oe&Pw0J$ROCT2J z96nwTYGluzgluUi5kr=A-LiQuX)}h@dAYX74)mC2i{VD7ju2VMNs;F(VO#N0uj4$G zJCU7bFFoT7gP#@Z#sblVCT#_KA#vX3_eB(%AFu(r1_ZmZn300@DuCWu#z0ZM<24WmWp~GKz(lRUxkgG{QgLDG7=pI|wPDrHgc;;8Da8dg_V8zl6D@ zfaEyH?{`dt-a|{rS{C6;gUDFvOKaVfFPYaw0d*EXX1&n+_(jG~qeuF~RU3Qk11uKi zS%l+l3jGGfjldMUzduyptyY2IL^@$n@!`kN;LWTh0CDEzdXct z-PZs_Sp?uU+^^!<50I+pq6m$T1#YelO_~v-)i?!Z1Zi@pc2iJGfdET zj&zmcyj1&$wy3y=^BE!z9r{P&13_*msCaE5BVtNu?I0}ZLp#06Yk#7&vQeEuqg?B7 z-11bvMxrnUm!P@oS2(rxDmooN!h*($<}*6!Nxd*8ZH7#tXYJF-lQz-o2{hJ!Fqlli zEry4*-uQp-2_NbspK(d&8#NVMcbFmr^X6=tXq`07z(C*V*l6BxSyos%y4j~RaT;bR z>elAJrW_Y(z|%c%{N<7bdAidl0#lUp^+?J^jrlg}2E^jmBmv|y>3II6{D>@Cdo62t}zCp6)Gec*w{Ug2s z8(+_hj_2f=1~`1cy}UZhhhvlB#fZ6OT)dZLzi|WBD1Y@m=s|b$f^q+idq9B(W!%R# zq`60&g%0z2_Zg#u&m2~YLUPlCP`SGY9ebA2(a>#MSN{WlA7e-vf><5jZ=V9ik7qqh z6MVsu)7g>U_n&Z=f9jVnDO0u|utO6c&MrapX01jbWfk9Dc?3=FH>jveTmVna+~(%r zOC{q5QlVzwLnRn-T}PE~70Kk!V+F=U@wzWlP|#05=e~T^MS1VX*DQ$jJyO)OSZ-^} zA-Y?NEUBn{vX3~85o<)$JlPG5S*+ifkA1aD6($*I>GE#hx=XvS2#)QpjEUQ*-Opv~ z(I089sKqsD9-{8&Kvzph2)b)Fi(AK3V;Mm7;zgZ_FABGfcJ0|OrMlaL9*o-D#-&09Y<^S?KTN@MC1xA{jD;NPd#f(4<5)G*O9n&1e)sGV1MLaAmv zLi($qvs7oT5+MrwT1J&4)?2>0sfl?v&jyqq>P6O!WEpHt@GP--L06E=BkRmuY*Z#U z-wF`ee=y3oAG{nWqWCrg_M<(K#{92}Md%};r^W3O)=9(p?0r<|>9eE&cs3KFh^dGw z|CN&fzvWQM`3SU6=_w*PeomPI{)rdT%LqSb|;a>Yr9ptGi;Lo3xJ9kF@H1e7a_@x&0jFXEBx+TRwUN5VR@ciw`jri*%H0elGk(6QA zo+N7D%B8qTIlg6@*@k>~*OhB+in~s?06-Rq%#ZAteT(Bn*%_V!_gcn{B6gPv%oLsG zSj^mw9iUW=;>wcDEk>1@RhW!F!^pI16+^pYYy-z(MjY& zuxNUT{o&Q#&Xq$N9&0JT6U(!9=-T2B*d*&K!odtURJxF_tYE9 zH7<;-Kh0IuyViD3>ofO4k)_u1Y?0IGKth{Fm7}O7V33eop{EQ4%J}s@R@E9p+nz&+ z@*I2u(mzzIvTl!Dr8cl2DI4UXu*@t}cYwL8Wn2?HHhcDA+$~ra`n5XiHcd^JY~*Tg zKi?r@7-f$ctxNfEtSFmr)X-z{x~7LsNFICw^_YLbxYbf4HRJ1wWtlFc9Kx+@BA)%@ zwND9BPZQP5JaOf+1sGlSJy78c?TOg5)cer()JYv6%L%DZ%!0Iw>RYl5(vvZRn;`kT zdyzq2)T~Q0cGX-$FT1O@24kd#@VzRm8mBI-t_MY3{C8nNEGxHM+nLG(Xrc$f7o2`n z)a~#|6tS8!6;Z8Hh+KfSAn2e<3T`Lq4W)3bAOd5Y(;!^505Yn0pFqk^_|#ss*sG0s zroeq^iD!gsyel?hhj;r^1mKJ>_RCDM&;@p`lM*|WyG0MRTFd1g{WAWBM|}_Cxk`f7 zN*6)Tdk(Hiq^){RX=vhyhVg6HnO7 zF0}T^jEU1n5?cElIo9rbN%a@IQuv|zhOA!3vrvN?{b4^`MHJ0Q@VSE6OQJX0uK))$ zf7{87B=xgjBw`A`Cg3i-{{+m*igvMg)v{d-z{21Oto#pH(~v8eE!}v%)5=cbx=?x@u575^YTVohC>!<{jzezg*Pb*_pG~L-f5?;_ zW_V|tUGKl|5FZ{>_JxKgG12*8E!kg1vVr%24L7}6mMgd+i<|O5JUj$1E)GS&IQ|)W!hlBK->A)<=*Dt8J;gk339~mZ<0MqTVTjR4f&oXS0YrPsu(?!115rqf1I#0K#ooeG%a8CYKzH=5?(`K_VEeaSe~y z*Q*AUi18bnV*Cmq-zaGt`r%#2lt_2myW4OJnKjF?no4Be^XMdp#zcrPWZdD=VjXBy zL_2jIiaBzo33penAMJlLbXIj5DyVH`pWbGGJ~WJY5yV>du0|TMJ{(d*uwIzYL zDYS@~0GliqyL?@%_Ro=7>DLE_12Efd!UE&!IQ;0;5+xjB-nNc|(vQ3b8a)6pPsU_! zxo}PtyAf{p3WxXtxa}Z;$oik@?ZVtSr1Q)SGuXig4(Gz<=lQ#Gt5t22A*`>t^?)X) zd7N;p_TYEh5zw;QA=LbE)>bWcm=x&}&?ysP z%X2E%d29hHfWXTWHmD*pA{`OvF=z}H8rd^SdM8c0m44Wcu~0;aEHS~fO`iUJ1Hzse z*gCAyvoTY-1abWC!EGbZCY8U>pz009a-GTxOQO+(46aP)xdgxOTb!3Q{L-hrfW;&$ z`$$}pT~yt~4k*vv{f;w8A)>l8<*Xl_Gj04wVnBsORY|R%=nJ*;rVV3HQ=)Q`mj~Yn ziO=HRf}e_c+x=FW!A&BJ&r=Ne{(y#wm7gcd4YVnii7A)t!wSB{b{M6ezZklPil}MT z!0(dOL}f`E>3D(>%1}G^%*>T>g>>8v#Pj$4Jk@t2(6731x?q2p>I$uWtC;#Za_b_{ zleIW3yMBV`68HX{AK6kb(nuCQG(%cr>|oWGT-K1bntvW>#|z$M+G$kPhv5~31!WdQ zX1;eXNhcyJvk-za{q=N{UI>tu(Xzw=&ddD3CM(sPK9|JvyNgbqx%I}Ar4t%=FO13AC@(tYg%nZ?n15P*P%v-CB!mweg{s zDu>UAgS?lV9lb!lDGeugEzMduBt@H^x*P~8O)7pX^kQeN`Q1~IntTc=E+`$TWkA!9 zrK>1WBhr?V+oF9*Ds#vp|9;zNmvh_8lTvXTLN9}dx-{+yuWE{J<&PFX^3Wuo+^`uoT zGYCSK@ho$G`&SJuVz{jhW;Z(8rt2N-%0i;cJ@|?-fqZF9%31VQzp<*bIsXe9=FoekjOhC8ymgzQYkD(( zu+hhOCa~oSD2JSZqeH3lGSxH$?3Q{Ng7xe3#W+l^(x62$$uKKTYrTxlihg3^?Z^=t z!L$L&ad1Dl6S0H{grS0@{>wm>;{UpHy{%*`UBaak{e$+fLX9u;h6@7TdRolR+X<*m z7kkApJ5M+V>$KA#I}lFrHk|7uxzVqyY7alAxfbZSfVu4+{n{H|v{3b}>AvZscGt$c zm9@B^ie=FczH9@Gabt!%*QGtU(chV#wII8(3SAiCG)rqmUAJ0Ijk8p+u}9>h&M6uE zA#EAa%br5nbWXp-A<7~F!Wm?h%jti*^6g`!Mq`RTIBQ~831SDo>CciNS1&2!1Gd9= zwGy0B#XQ~i7i)2@{TF60YS+?^V}xS?n9VTD%1ML-J;NMrZoFpV_}^5>xKcz#Esx(5 z?EkNK{_w9^_mnp&Di=jqxDLmJ9P{@5&8JYkZ5%JTc!k+TqmEDFO>PA-t&cb{yji9uDrS!@)Kn&LkEVugJV@4 zBS$8$p3-pITVB(A%G@_$R(%3i@tS@tzz1&bddyruSsSPsPX|j0chp|D_7^pERwL_@ z(rfnUEDNmZ>+i_i-@|w|V^XqPj*GLE&2=|y(%9>2-2$H++}~AY23_tQ38)RZ#(Plq{bPFPKGMBt1eK~aSdNPH7vs?B5FlMz37Bn^)tgL&D+r8 z$B%rfqWN>2hgXcDmr#H1PTz|?o8^l+G4gHeeq6r@z++*%GyWlaP&Q0-LUr{KWB1pN zr^NJaQ0=y2lePFI6kd?Uvh(~qSBl}IL+XQ!=OT0fg>S^B)9hE%Bt3}wtoB0Z%{8=b zRW7U+kKNBZWcERcVc%9IGeY#c$TC(FYS1r*O)%(trUtOLKI1)p@|$(2$~-3qv3%5@ zUHdyP1A0Yra)7(|f397Pc;0XcJ9` zQ|kbM*^q4*?V(L@AJ%iBxH6j?<<@vZ}XeSI-;^Z z&ZpWT9#nSqYv&h?MS7Dr3sIJfL*v6h9+YY&L4&Bj@Sd~}Oh|u|jD`z9U>4n;Q zG*KH(+H#G_3|%tuWW4xv;KsA{(5J%FN*+7`oFDFkFzta7%}CG|pNY~0H`mt&Up4d1L7DSvox{Yt1E+`EV#!&e zLGCPWmLw>s2^C)*$p2B=xQfRJ6Nq{|4S;5=lR#6W33ollA8`NDjqSKGPZ~U4y=M5SJetQ-mrZGdLxP(>S1T7Y8k#SF~7X> zppCPFC?!1p!}y#i8$PGcfY^~*#Yl*HKIg2!ewq<_zHn}L&`V7pzU8`M6d9_m0U zyx37FnQ%6q1!rD0+I+Si8deFF+f9O&R0cC%D%=%^DizF=E>)&4v5Kb*`)FL%x`L9; zYx5imUgFufth`TrbZ_=yOtX#@a=xoqEX^&0mWa+qhJ@(E)8{#=%~l-cV;YI)ei1e~ zxz+XhTU{9!Y;J9aFt0lyja1xi;EvCoQaLaY}1N92cw&!Vu4P zsYZ8mZJU~Zi~F19ug4>h`h#CPiKmmXAY1;Wo%1+^;vz2C9gL$nd`eD+-%772&?WDc zfj^Ah{MAj(0iXu-z*X1{YI0IDr&*~^>yZRyw#^5$E{Qbwr=K6$npN7}nVi%n-H0p9 zq6*IZ3Q73)SrIPy(Z!%A1OEd6seB=4uAYDzOw}rGP{9qk#}VF9zKEf(ObtL)^TbYD z{?^N0*5slY)oZ7zRJTH2cxaqXO_EdZNOZ5l>w=paqChIt_q%gRL)9QWGlEh7`dA64KGnuSl*)Y|YPqY7x! z5z>j$gbNM)iA%p_GbLwOPfg>>nv92|zHpTPBy(qM|gHrfdMmq!(y}Jbqb$hZ)x>WtU3N6BNa0pZW;y%|r-zrUOsspS~L;gjufvUiK zrIXV92wh5IOw=IN4u(9|Jj`gsM*l_=)V=X%%|rk1ILYrv_RrY|$Mj^m@M%fvoXik2Oh$CdOk=6Y`lk^oT54$9oH-w_x)n$tB;C5a*-*Iy>2UGt&_Uv2Bg$~-c8 zk{BfDs6|_s8)*LUN{+}|!=7bb=(YQ*0q^%D_gV7D7=Ye*!ti7!cRkZHY9Z!J&Qr6* zU)0okkvfDgq#@u6367=DN_(d%v@G{~VO65i`%0jSW@nj zd8)j+Vai1m(~n#gDVK6zI7x07Z8%w359PfeWFF-jQUWzRQ`@QrMqWvWsL?e>|2q(_zAcWf_D-MAT|5_)OEQ zP0{aRVUY07;K#JwpXaNd{Gy#_g#BoOMIXJkbZ&hSG2C|M523?fYc29$l{{Xd8h z;n%wP4g`okBW87WcNaXNqs?0R{#?AE^MxMgx6X#5Pofw44hyd2B9>b*+OEXIric>m z=nbS9_)E=*anTvBBh?IGSHC=|^9#JnYRWlFq*&>gnNstk!9KFC);I$78KW?E??z}C z3{iV^pct8=NiIKt2!@?A&*bPdwxX&xTZZBdwrc%2ERDHKf2e;dKRbp0Nlh*sG_(j; zL}1V-%-}Y5XH^?3Q5Ch1AipngRT$^_FG~?9 ztL*tYcTgF0O5G)4S+Kds{R};WxC_MVZF|uuOlunWsbPB%QV8f$F1%LfM}Aj^K%Q_(aUW) zWBnO(9?y*9!F@$W+V|g!)#$6JnxdU3mtEW$6(s)<9?QKgQ*jN4Z*Oj5`a37$R!sxG zSBz#`ISA$CG>eLlE92Ik@r1}~hUi!86n>YiBPEgdpQ& z1Hn4bzkR4M7yu2kBx^vzI}V7mX7u^4v0vc+rx;eYU7qxHkxWqrmKsFFsBsA@&J(ch z4DKu$L7axCC_{%kEOQ-KqbRE?-UEX*I+I5RXC z4Z3qqe~pOwSsTR~npw!|$`Md7m;q5YZ{Vwa=al8`6HQcwb0Yy)cjvvrQKjw;m)A96 z1-X}^RpfO0m?XU64dZIG|Dcc3GM&laUaalV?>9H?`>58mM;iMr{lb^SVC5gqOdJ6?-BowdvA<{#^3v%dXIm{-s8ov3bzF4Az+Tt_Ln3lZqQB1lri z4?6%Rxj;-rL2H05CV)zW(uk2R=d0L)aeqBP9GOjKKksUB$*Szl~Czr4`Oz>O+Q?@R4wMu1pI99CXrw*>fE z#mS>$P~IIx_{L@bq40&om3zv?pq=p1P}E11XC4!AwR;anIIcMU*sXrJ8RthKnJn$b zLf{#fZso9~A(x{-oTZYXr(a(A@}S>C%;?3D#Ge% zmeV6Qe_v29l@M_UYv`8>l9GbmY};~wZ{KxWW;L;^am#tIy*d0H{t-_uVRN3#prK72 zNVO$@Li!NN95JAVyY<*kY80Q0{Z|)lAiLCpkX8#>)B12ZiS`8>Aqwv+Qud=#2s=Pw zK6T;_4CK|iHSAOSfNC^8GTh3#f&|z7*kMtf;29SRrcC#nV^9k#X|&1FBQ?$|C0I|b zFDUCxRKg!F5%EfI!A=rqgPcT7usQ z?}mI0y6n!>Uijqv+}2 zYgYAC9+pRH>;L;^oXas_jpX+XX0iQNa=Pt#5mkh?k!l-)ha|hE1RqEcVwY`1q&b{*)AN^5 zoaej?6v6GRsR2sA*tKc46;}K&-IG+v2e2a>- z>yTj^Ervty#dH)AS|-*kljL~l5w`PD^Tf?x7X6$9oThCyMU}GYU{BM^;cAoAj`xc5 zMGml^3s|v;y2fk^vv;R=WWK^d|JLW{Xck!~_3{UV2)|)Hu3W#}seQc_{8@OWS|>h4hH{t_y_>O$k<1>wdPi4$Mcop-b2>grpko(lG4W;D7R zcFVd)bB{*<%i}HhlT&iVU_qD4L0C{%CZDK7`=nd+0hH2BNCUt8{Rjrk@`%BWoJ8n}U>iA1s&m`yI9KSyX-S)N}= zWvz?dcRmZxl;EbxvC}!f_-)RtYUwz5!s0yJnPKzV6|-qEa!D$4O2|4Q%L*8b@X*eQ zBo(kJ&5ioyVeUsXkElYYXVpo5u*IVU8xsrdnYH&8@SaZX3&4Z|=_65R4eyw)S=v6g zRFk>_fed_MVL1-|U~+;8TN-0r)_L_Nso9$<#6P%U!S)JOWqwZ z(kLD{tUqh7=CRG~hZ%+l`w7=2T8QceV&eIu^9YxQvBeWzk~loF*Dw36y&(gf(D3dz zj4X!9#3c+40)3<*M zu-UKHsPtM34CWGpw`|IFd*!MIhJ@6TqZFU(SGp_~71lEfu%*mB{a!*eZ2eIPpdkaT zC0;#ktfO*7o%{&h$Q$;ahws;#$DEvqY;bWbdw%9QEO{qMbL?(2G&c8r>L0%^%L8Bf z=Etk3-4J_URBB1HS{2TfAv@vi2>{;)-*#WdoK(cb`ZQE%u3SP@EW5c5H@O?<#IzLc zN`3cpck*teRRM79=3enrvdO66s=EbZq3OIq;I8|nF{z@86dW%|yZK_0@a ze2cXAiewVpb5GQL$D4j}U=*U8-^o8O0laAwObN%~5ABj0O$c91A*? zo{mjcIbG(`q+kE3Ip3}RoA)r^GCZ;9=y&6pEf=Bwa(IF?#&j%SKwh{3WOqent+%Q> z)ayZbuevg;&?1ej36VUWC^=SYIQEAByzwpju+J+jhQRD^0E1{D1K7h4Ok$|i!9}3v z+kYWKyw{T36x^A=ej{l$8f#MrbrJ&v_v5yHbVe@WNK?f+4ARsnG> z>$b+-wejHY1PGeo9$bT4fW{@by9Rgn#%bK$CAhlA zME0&EAm2Pr`f&5J%jV^Z3?4*IqYh9^b-r^$0|U)y-+hVDPUuqZk?_DUyy+VC9DW+! z^{E``Pc@P?Rgx=c%Yzgw(HXA>{ju^~#Dxu4Rg1AKh+~|49=i*IKO7<2JV4&B3 z9zg2ORulZ;arVM^{sUq9H7b-(nFAxDN7Y@h zv`p)^39}J+ZG6Z5?|+qNbZ?Bu>!%5J%e>DFfQZZV22ST> zPWhwx@BTyPk$hn4QvD8r06@Z5mg9b%&0+A*U+_eA<2}E_9?h{o-;X#%dSN*xP)*&h zns}i?8@~W5U3%Zsze4AaSM2A znSAodR|Igh|ig#%5XbJmANF++)f0P*8I#3VyQ>+o(@9u!n==-X;?gs z>RITLiSN^~C0G>=q-lT_EYz!vJg>D3Wx@Q98V)*U=+Mt^ub-(<^Sdzn?q)>)gA|b! zdi<3~%GwT?Li6{MOd!Z9!Zb%$AuI<_fb(n>@a5JLbOmE`ZDotKCAQ=a$zw*i5)%G zxjeQc6yFBI%jK~x&hk-3|5K+L8a_`f3?36%z(egYzhxC7JDR-g?X-@z-i5elffnD3 zoGHB?{GBkJqhuP>Pj~>lPEL>B_PkFy6zOF8QzVzmnA4jv9{{d4rhD1s!#(?@(4%DH% z-rgl~BwdD-?^YiHD>dE1T>V1mPlls-)Xy%)T(nZ4R8y+Cl!MOs-rzZWPOYF8(GZ47 zoWlFLlWwIWT|dQCUJU@PRGch&Y8wKp87L zQC~@XohwjkNB%;2nEh$bt?()N8j#*bN7JjFm_I zHm#{rdlmA-rk{OPOhJu`AX1jer+UgCPeF##JOU8P)~D2IX_1sy$*@1>H0{ini_fjN zy?QhB${Q+Aldf=tVH!03NL_w@{Gno7!{a-^8#Y<4K)8$VE6x4Ch!1P33=0mo6=ndT(i;MoDkmeh+F>xkU3KZqi z_2brl(Vi(&hWe6I?6{MTN5yIDEIcDfv3Vw6+-1MU$Ew$%OuLzL8YhjQK`aoD_IVw>@MgobyJ+Qu{anFct&@yL!w} z@E*#uIdhhQFbbWHB{DW3sj#y_T1xe1J*7?Qg|3%acVQgtv}&E`9HsvL23z6kCoS=@ zzTFAxn;mYL-Zq%MY*NTpo?Q-Oh;B#qFkq_TxJhx6;TvGjN|V~tqO@%nfqy+pJj zwW9;tG?{Sk7q5MWOb>zVFgx@Tw?n0MqW-FXN?2|L>M^$~-m~{xZS23xNE5T8&_i2V zI4ETd{g+&93O5)sFUg7aOIDOeWSfjCRo7oSdZI+L$ zB@ndy+?B&=&m5yF=I1WTwj7}qXZdrXBj(0Jx#FOAmG<}HQp?!_>Y3-sR9LnA)1Ngr zg)E}H-&X{o5{)ls${F8_EDdUQiD=enBh>jC=6YZMfanW{AdxeQmBfy+(fG-3b7g9$ z63$clHGoo4E*z`f%Y#|8xNh%JPK?=YX6~OFLs*+r#cw6b+7cujLn}zEM&2~`p8h%R zJ|vTa55=Oq{nf6C&g+KBdlV>`l^Cm##~9Vypv@n>KC^`%IldPFKw)zs_B~|BBhR;? zG+KW`j}eEN4^q>$XFGMaOFs?qd)r`G<$S0o4^CU;iAYfIivUWAvs-t2=xv6;9tQv3 znsLBcs@YVfteormZn!mQso=BcZB6ZL+!?f4!tqK5XwVcB4woia)-(yS#I2C+P3xdH zP85?60TrDWY!e!CS&!xSnAO>7Q^$GqBN>O4>pkoyvOj0}>3$m)yCfam+JxfLS`G-a z7N8>kfld`LZl_fh2dE>o=(ES%l7dh@s1o>P$(F(^yx7$NI;DmC)5Lf2G4qKvZ;ri^Q8GT zx~aFc#y6YT=H0>;>Hvc>?9r$HL7nDNI+!Nsm-;ZgGDJM{_l_!3+vg$9-bPyJ;(4F- z-24FW zGb`BndGGK%25D0#U|93)_W5oRbQHM+=fjI2kMfu;nIz&z-TbvNX1YTKUiLk|Yy#~S zDLA?=4)sB=yu>raj~2mSTUlzxhPVt>lu^-}>Ac5rcG|bSG*0*V#Ck#fTA0#t;UVo< z8I56}6;&iyVBl!TCnRG8r*VK;ZqK=WtJ5CbQ8D@nIe(jd{Z7elf$K_(kIU;|&q{^q zp!704+M0kSRi{)GlB^fxt~I6}nTc8x!`tF;SC=u9?8hmv-?XD?hI4MJB%rfj&5zR4 z{cE?$WW@chH6eb~PTz9&!O3sfD zkVa8c17uY0G-|HD1Y@IZ*5HG!59(3A=(&6Tx0m{TjcCJJb+ET`S9jqdDSR^{&<&{> zP-ZtDxIZ6k4jERq2Gfc2;mBFVe!I-#vwX_cX~u6d?(Qw{rT^At6dEF53$SLKaW?X4 zncXzdyQ^k{%LTz*`GvsKEhn*hSI(;=s1xcr(()FfxKwcrzOG_*ezlK8hlR5-aI?tJ zr(|b5YaL<4{aW}ARi!BMj_wGxurQ+Fqf1BfqP+Z?M|LEk#MNsnarsJKo+v8}_s#mA zI+zgdr!_3E3;b;7vd8&*b14HswMo5VP4u7Q>S*o%C8{*Aa%r%wvH|pd-;p$rR^H?| zzW=q+@6Ody-sEH@)w0Jzd<9sI*8oDkOH4+6>ynD2`%?@V4?SsX=82LdI;ZS>nnT$V zV_}k)k=ERAM4X_Ne1G)R(#1JTwZvNb+7j%Ts7G?B$SV8xBi6b%nLfy9B*pH?BT}Ld z?sgsT!vojeHE6n8Zf8TwWWig46At!0D2@eE%+4T z!AVNIv7SL$yj<)Pqvs!8>=9BEYdiUc@t$KM9EJ42(&lA}fCZ^|!}0yaeTFvY@C6>| zE^`IDgY5^&%a&8dXsA_dbEPu1&h8}1xVQ6)DNui_!WNE1X?#zMCD@a^RpVh zRrMhz$x!F1Bis%EHunQLoq7MZP!n*x-9vC;^MUFbn{(%Ce|GeYrRAe>T~9xh_#Fyv!{fO<5MMN1P-w9||KVY7Zs>}&-RYH47m&#TcqDC~PTjNMs2n%TIqKm847 zp;LfK=I2Vg`Vt>x2SZ`ij^@Ob9MF)qf>kivV7#mKPmE>0tzQ!G)K?n&SozE~#7mFq zD2Hs}BCd@spE>JR!vfF}y%F>YWp_+tb$`4m#?qIUXNoW|R9S}jU(Vp8hFrqKZM(Hp za^)(>!oG~0rt>>LcUP!Zuk>!XY1LGk0}2<^DmhwW=JDw9V}B3Og(Yc))2qxVuaqF` zOrgqnEKN*MS3gva{KkA{#5L+)@feYTgtFe~brpf7ul5Qtime4By26@SSg?0pLU1RT{Ib4lepEmQ|~#Z;ib=+5e- zaO{W)kzHIqCc032V(M{vKVqr=``$e7E=(eP=44l%x5oiwMmcAiNIx&v*=0$_0mr^) z(^xo|q)+|n&4R(5UY#?IGPwASvIZpc;q(P(BW|;$k zQL;{};E88&Uw)|dr!2I9C(OyS^p)n!rJV=7x)4c^%a*GJnLjp|Pxsow7ynkdB8)SI zSmH9ft*TLQ$&TQ3edoHei;t7+`6zH2T|P*unGwN3oCqeUHwmDdlD8!g{yMBtyU0?h z5-pwDC1qY1$S5QwMvL&Q@(rq*2(R=1=_O#T1kDR7T&eJ6>A>Xq1fFBdn1lV!MQqoZxw?AyjT&v$1@bp;I zZ_eMahSXYh6rnWL^&tFAFClBaS?Z)-6u#=YO~%K~NlcwOdFogAXIHjFe)WFHJV*IF zYF#8W$wbqg&Aygmgg$3x#5bp|W+E*ekM`Rq$D%Dvp}o z8cyP!Q_$&cc7*-2 z5+TM@2-mOsoJ6?Y$!9_?Lk^#>x*F{Nt zF0z0?geU=%ZB5T*Ww@Xm_zoh!DKJ9=Y5;zC5!fWZ0(3G-1ikdt*V5sjTre|a>=(z? z)_=dq{$KI^yDb+@_1jKnMy!+%azHm(wc;lHHW^2AaW=!F)$oL;^i(|hi0q|PJn2aQ z)>c_FVrj5UyDP`HX~D*qUIcLPaFECC#)|e5N9S>sj~Q|-pgXVTm*)J;v~3}j+Df9# zk;3M$y=~Q-k8xC`Z{j2h5RF>T`>4tx8@KJ#OlcbG;GhW08uBv7|hkNTCJhacylI8`H^zQym+wpD4d=hVNlD0aMUNj6Kc& zi_CZ*F+C7Y)v35lJ%wpPn&M=V`9?8baxVy+R_uyUrO9LbBmz$tXd;-Uqi4w8UHm3e zOpp%0%YMrgdJD7!$xRI@>6?KuBcE3aLP#BNR$o)Dis%snytuE*NE%S1j5~J< zx<{(9#1|F|8>hBI((;wZ2NKE)(n(B?{M6P9)EU1v&6OPQz?34k+i7Bz+w{J7G07YfhX5-?h2w?5*ruuXwek<`*5FOe8UKoG#gGYqbF+XJ?OW z*?}9!F|W8Z@@c5UZaB?}D8;|yUuX&M^kyp|?&+)%C?KX*2mFW{{9{`z4c^PEA@F{*&u19R} zz@9jZB;LenOj4m)D>&C%S;dHsWK4L#T`xadNQ#?5bs!ExaSV`BA>Xbr+VqW!-q( z3Ka4Y(#pk_NE{+QP&pf8qsoVH(7x6L`L@6iZRduEq@{rj$+^a@%7J^^jRG&UpDW}m zl;}mHS?}Pi!kMYkzv8N!rAcs14@FuP7fMCZz=&meRPS&6H;-b*l<Ptg z@R-BeT|!8JakeM3-y^-E2Dhb(MUh&NbjMYLmPxkB-ws}M1cWH&IczOX%&O6tWQ->> zH8IwY2+rSxE%S{vj!Hjfng1}qbSlPmf#RwyFt$ybOtJ*0J@S<_)924FNcS*9e%CY> za?mBMgGi~?#>H+O|BmT+S%F4_3kQrE=J8|j5R;`-;Z4l0^D-_m9}oOC z@&L4r0*;huJ6Iv5qgYSI6c3#;p|aRFbiKT>fQv~8=0g}>N;D@Sn)=Gc&DhbfcUtxs zA(q&%3|b1i!N^2qw9VQBqODw6QMc8$WAnfupK5$ABU;qHb|T3sfo(F@9;`B_l%%Or z?AUn0XErT0BKnLe>5r{RhWMuPrbiu5=k31*GfXM%<==Zy-u|*JdQdtV$oZSL^J@8+ zT=5R@wxPb{Nsn_8d5>X-^Q7R6+R0@#&(3!lF2Tt{*R9MW^Wg8Sb#xQ*?-&ZC0N8&2 zPT(koRP>7>Z&_~TwAPX9{vEEf?Go6x=NWt&2F4Iq-#;&9rCM{Ze*esqy`<0yL-_|M zP8{gBX>v*pe>V)=k5Pf_(Z0F8p*2~m9@o4ni46*tx63&}-H}m~t-H-g?Q14}9S1y; zfuZ#fU|eH%x4JJ#N(^&&UcT+A!-nTzMYErz^^DIW2p@GABPM;5#~ZwBh%6s@g=S^S z(h&QdD`JTigEf#}qe%Jx+BKrX=CGH-dN67u8~)0Ie|qJbDst{1k0@U-h4o#uH)3sH zT$UDFH%-={0TU3Z&OH&6`f;v9Vk%7Ow&Lut~mn>*cYc z(g{@df2?Ig>}1ek!d-Q9z)mhoaKCzyw{isNv_ZdvSPW#~j8zL&HP|j#^|WFnfwrzP z4Qmn=Po?W;qL|oSn>Q*A!L$XBs$+@--mX*qFA91bPmMIDtzJo3KJ#mmh)+@&-l}t9 z0M(hbo2aA1x|!>uD?ECQ=IqCgYqkUH5-b{l4>qKvUk}nxIINCKtVQPb7o4Ma2%^Eh z$iO4bekB~GU!SDU>O}rh-+O+_Tv zE>~bLPOQ2I*n?3(EhNoik`v?kt-)@h z+55Xt$=*OuyBH7sWXd-t)4eqAC9Y%$0ru+MhO{140|&gFd(Q0B$dwe<1^2t&U&5G5 zH*k*&WMtI#|3A&-oyh8>g^*9ptnHyQ*p}BktRu=%?d=*g?~c~ce0GDOd&0*{taz8x z<)|L0eiNja94r)(1sBH1_X~5944(YJo>jt#7{AIrJ1oqat*fI?@hkrrFUSo|^DQBmDIi7?{vVHdsD< zl^RKzo$T(Eky0Z_TW$8~o8F`=ieFyrFjvTnJ7u+AVQRiP_Vu$peoWG{y$Xr3mY&}` zwN;NY{BsN{;c<>gUXsfxQ5o+-0z$*R9e_pJ3->5o&i_QX@Nz{}l;F#H1K_?~#7CS& zF3gc>&|%N5$Zy>C{$Sv{SO3am@BtP}j1{#tf55PdS|9SI$S1pI`s?+VxUs{9OLLEKq+RYLl>7uAaB!!Lcwgc5`6 zl1*(V{~LF72`}_T%3qH-!%yrcS?}L@_rL>_W7v&DXgRDX|b^eP!NS9^NbNYmuFwT2PA?Mju}=ac^mTdH3JFBUw@pRlVWPNZkxH!eg;> zb$JT?r_|x_w^Nhbqw|Dj#-q~;0Jo19j#^v?F;s^a^8*@eh<8E%Uc9`rm}C_X>*)MS z^^388$k(Pg4Lw#)bQb(N)0(IC8y-&)putu2>|%`EU*{@Y#pB(6yZpj`T{pSx09TW7 zl6Wm#$dB7q`t&ZS422It;halmGTd$%@XP+#Y%!WH1*=uh;7_J1!zGN}W3E7vqIjwA z2s`P(Hy-gDoL(;viEx-w4EP-6u_{?!J7)h*ggFKr_%RFfP34l<^0$oNv!(4lcy5r2SiUyUU{R6zc$m(ImL>% zd`h2=UKeQ+fqf|^F6%y}GNgZ>*-EDG8f)ucM?Um+3S_HO)Syz30 zp9TjgiGuGZ`yr+jPt1ccUUc0P>V`Eb0geqxJRkQNXlq=p_`H1?1SL?QZ?f<&L=V7D zqI)tAv@7B6F?-(kJewcis}R1VQva_0RBwH3`*T@hE+!;cZ-*^!z-mo96X&kDjp82k zW4n72=qo5vYNu0)9iHtQ?{XBsx9Zfp^98(QP_~xX*l_$^@Hkb&0+gT4U zTvo5M|F3y|E@9Ti`Wfp-6G@09M!@lVALr6prfXM$N{oFxLSL(-ISyIoA=|^7f!rSWj0nt8^IMRFNWcku z>L=etKnnK$6~OId0zpV)qg<@M$vrI3Ui4>0nn+lJkLjy;xXt_~mmP`=A>^VWwxnHD zxsNBAVl_@9IB4Zcw*;QJ=tK9s#X1!Fb2XpaUR8+97^FS*LL|mwq{Elof)L7D*K>7~95Ls&v4&wg^{1{&7-DER(cPiB&uKhyk_i{jkru z8><-r$d@7$PB!E_>Brj^$SxT*_KY=aa=p7b19v2ju^L-|K$PUlN#wXz;rRVeX-(WS z>Q}zw*@iV|PyRLF#-zb~0u$;*uJ%%snqJR@ZE0Q)>-Jo&khj{`N%gWg^OMhm>NW*b z>hj@}hJcsRsoD)Gku`5ay=r>R#+w3!or;8%!Dt`#-S0xZAwhmH*_AxQt(ya28QH^q zOLke8+izXY<=!9L_+MXY-?e)gL6Y5jojjTnyt^<+-A~mCv=)QGi5J{^D1VK*ch6sv zkF_z^q*=UAj490^jMO`SHOs*%in=yfOUP2*BGz&FrL&*77+Ul2fyM=AJumU* z%PYetly>lQY9}gAyrqcZ53lC#rEFIMW8WU0Aod#*a9;!VijzDo>V$C;4S4+fj`N#N z#T7_z-OWC2G<<4cr(kwjW?V>Ct*atDPL@)hSZfkD`Qa^(CKP(6PI(`X(}PB3Q8SqS zl+U<`umLq5)lG_=3SEsksQI~~cpLLqPrWN1x8Qi3M4&xyIMY67Mx~u%6Sac5fc{_e zjNs>zr-LuVIbP7bzh|tzIU301Q*RKKcTB3i4vn*XB|h(5%3S~$Sm;B%LKjLIga~TE z2pG9duN)oOckc>JFyRP(MLP1Jf7dCmDR7mCQB8BV$3aH7jgcZmI?rmAs*LMT z#z1*t28zT723EiI(Um_l1<*1SV;+o9mE?fg8)FiR4p>Ka*&$-fm?;Lc26@ACH~ffC zN{-GH30+=#`%5}{Y&@xj@w?5J(VF|N9TDNP2JIGX_KkxcUkJBJM$MT)+cpL4FRQg? zn`1MCawQ=A6Bke<`M8Mp#v%x|m;Evz7jiw`TU%HPR?m9iub=GQO?GVjtn26n*w$eB zQ2LdI{n?LCu~%GARhpPY>;b!qfx-Rlm&i@^EYX8PylVlROa91sK&I%&lse}bLs2Th zH$DG7b6qOZIJs0Yzw+UsuDaudwH0A@1GLg`*-!o+h|9OT0k$&I!lx=d#$7d(1NNb` zfsm|b7C5iRCW0C#f_MY&UbK^?7Sz32y}mChgEa-5f`JA%xiq=e90m&wP zEu$9(zH-!Xb4=3Z+fdPmWP#&T*HoXrW*)Vo{{ zZD0q@cQ)lSX;LJ;t_~7 z5l7=hljVQ5VpIfWz6ZBa@&Z?b$61yqGacuyJMlH)I(qdaDQ*j!-Y$Oc1%c{wxE_PHGflRJ@73ic}`irlc!gj1wm_Q zVlverLNvYBI(}fb3kWq_-z`!dMc9u$VSox-@MIfluPD<}!W3=6sM{=itE2Vhm?_G3 z>*6n|=RfVD(U(6?xw`Fk6051HP6p*JWR7dO5&tk+4z}#15l(ly*atXzfFp+c5Sq1Qid=P2ZXId|Ga#2QZUb6*}>~ z`bGt=_+WXQwe$rGnii`S&qvu)B&~W0ZPcazlE@D*$id2%kS2OmV7T~=cMg6V)^;ry8xQ=~(1SomXFH4w)cGgi;o|A!>hMIX_fO;i z+%2*uH&@eg*0vLw)Xf=>8rEI)0@E^>i1dYxpV^?(0Tq_1U70jwv2%tFk|v^s!2j zE$cNHX0bfZX<0~SOFnqPMr;OV3r<>{kY#FkmIdvuQr6Udm(Vce-Po+Ms)vs{?$dvr zW#2`9CG*_@3xgRM;!LR&&FT$p{(dXRmv^R1N_g#@BTA{_D0^AwrL7z7l-PU#Y4eVB zR9D|ii&kl^0kjg%6j<{{kiv!Q-2Wm|HFply%9~$vIe~dwAFaK6p{ci!pPihKnrP>Y ze)ky|636_Q&+c)IyPtsD-pnFv2;7=5ydu{a(DyaigKLz`CgEuP|1y*c`Bk@JU8Q0Es{u*!M>OCoHw8hME$x#BdjCp` z-1bFZC8h%@x(9Dzppya}Di!GW!~G=PH+-Nb8Md&i_%mMs0>yPN*Ej9oVn!;H3sB~O zpfpG=6E)j=uz0Mh^n8|;!D9@`-?wCij!jSmDN+0G(5dg4T`)E8GQ00l+wrUbV3h#JPJH*xyc@n{M zk*DEn3}#`x3aU23a|rCAs-}zM$)xx$GcbnHTHw}mD`N&d-|49k<2cxJry9lh66DJzK(_JW6@t4TrFehIdC! zcR=2cl3VQgd99)PBc`GUC9h+TSKpr-7yivAm4*UEoKrq^3)lJEsk8Q?KshVOQ7Toy ze@|xU7nXjNjPtVKYifxmJr#qa2>2dK#|ay=s1x^d@7G^abzD#H+*gt6=7T7DggaRe z8Tl$su+X#E2UR9rjVlIyJn*m1u}8@eY|iv!XC!j1G3NLb7H%24dvvMK>#6i`aOpihxYIv7HrnO2z3_nX>jz zNdRWlFlyYkg7Pm8r4LpE8@?+aZCHM`0SUPc?_a}v#Mp^dpMNPUk0enKu4|vRppa|f zrUyYV4Z7?%>WD&bno_57JPp^F-R>A0-8e-Zj>~j8{@!bRa+Q`VaG;Kn` z{NV{ID9`p>q_-2$VSc=hm#T~mF?NQU-;Dv!(a$~i8Xw?v44ji*gC%(W-K2PO!PrlP zln=niNb1X0Fv|W91$NTefF*m`J-~9KMCNEXdsXWnB>>$#7Ko41p-hhs}O&6n+-!B%3Tk zcgOjgnEA$b^WZCmDrokO>w_fbi0ZrLlW80qFCe zdD}5rzSAOL*q5$ONE>n8L2@E(LvLf~8$-tNX+2lXGJDbh3vuAf5+=-k)^RY&_Ooty zgpuAwq3lMd6cf2pSCCgX2YH9a=q=Q9$;LH8v3(?&PVIQ7;yP&k+H7mqZ_B;fn-#2> z`=&C1L4|_qZ#-jOXzAkJODkzcJ{sUc@`->gY+#e@7u92`48q_dq#38{th6Ye_#@P& zXrXTeb>tns$0S(M9GT$>x5DPH_w+l$_A#|;?6Xb>9)AweYha-J1&Hp#L4t!8P%`sW zTw5UD%BNS7u4Ksln5wr(kFG+aAmMhRg0rgX(I3@z|AedzYO32oT=RC&U^W9r&Y-QWs6f%O@(5R073E@=r z%A_)fGQ)NfLvw|g)T>K9o_%5DnrD#|c~bow<+~ZC-<~>Jr0aTi3ja||qG5^#u353_ zLCCMxPhiDLbpX_)!3Myiyu@AiKxWhwKNowm4iB@<+2I#GD)bkp)zBg`;dkgU2c>3G z;FBgeLX5sAS?g9{e0E)ZuqLZTLhV_8tv^9cjnq@8II zeuj4*?#Rcu7MwW0@!rJ78iCSax`m>)5|+_S778jy`N>+((vW!l*E~HJ-S0(4bkr*| z#%!>##^mkZNu3wBF5J17B>nDVW0-a>D4mdxTk1BhL^|};7*XxrurY_eMm=yH7?y5+ z$j>CzQbdPlPDcO7g}As_SGu5{q2&(00h9d{NAr1 z=dMORv~tr{gSxUe&aa5SsWO=H1Q;=xfH?+Ku3x_P3F2gA7LG7>PaJ=LK#=8j&Ji;QEWoH z8aASZSsNKpnc*%?<(ImAv>WjbFXV1Nuugtqo0EH385ncQT-}T&-G_xpp|S74B!pV; z`B_al$j)g!%O@+a(m4?J`e(B%PE>sULf~s2cB@wfu9s5wh;O&oN}`wXb{Vk!E&4Y^ z#0gc8%Qhz`-rOJJrcFX7cKM{}8)!1&ZrPW{5%zt&!bdPZyW2%dp~GpHO_2mt~Dw@ogj34wZOO+&ZQ zA~;shge```86t5n-+sKogYr}b=A!`)V_@V!Gl6(_wo`CTaM*M7AHJ1!5y%XNy;k8r zz^#q_qm8Z(lVNsyxCiW1TYh|T&()y&+sfmf3;Ko@a<#Am-M9y~9IXRTkm;_@5!6^MIUI`%5HMb6>s zA)yB`D6G-=xq`&mcX^g(N47t5ihuM{&6~iTS>#l zX0}bN4ga8K(=ev@{L1c0vg1+Pi=RNRLKD>`o!+H7oz$zkI~<+%+sbt^>%6?G8F?)Q zgeWB#Wo$_r?GWw8i4~x2u5k;d?4|BGba)FEf+fw|fH*)~BaK0PV}2>Hccm<0#x3%v zi5<2v;go17&Z!_QzoJ~wg(SzsYnU31HN=Q4Rb-r4w@R&>cF=MM&=)IeuciF;n^YKg zx60wSK$25gt1X)*md8->%xXR$b#Fl#(3)jk2bg){v%JE8!Hizk24>SwqqCfMQRg%~ zyyX!jwK_{f^Y}sJOtp^$*8}tK?0k-heK3aA{@77S@(%`9qaFnuGH`wCv zl4%~pioLYP=JAS$lq28`SJ{Gn@W2adXAybV)@pU-3VVm$6d!oipLI<%e*)Atb1wP1 zOKi-|2T?cvP(=40C;UdMA{q@jpgwzcXzT8@N$a|+z2K4ZSv}+!NBUzep1u7=JrO8g zK7V5tfHH&BIg)IXM}8WHI`@A=7fKkATHGS{rdaMnR!-*i6^(kh^lKM~iJ131fp2aX zK1rSDj2Okr&eFMFN3yhGM}DL&%7yel%qZiZve#;mi`&rm9$_2N)y z8vJ#ku2)Y~Xk@xNi*Ks(YLIt-A_GM(YsjO;mNn^zKE5g{0p6zHaZ-}*#OW<7Zl{pZ z9qBYo-|No$4 zq6Ww@9eXVTYq}g_E_j@tJ`0Hr$(yN?{;EDXpI@YXN0UryI*ee#TLwJ4#hARF%(HAL zM6R1a%%qE5ck!<73UZ!LEp!@gxHi-FlXiyQ=?z|~@utJ8Q#D(#qe5XlcX{O-A^xr6 zNfOQh;)`@!a5FymU@Y&Ks9oOnde^t&ahh0|B)a&#cWQ8T_`*0+bSAF-I%zlpkUo3s%GcU~}!Dk>pJ95?brZpkmp{`C)irz#s zIXnZEZ@>xfko(teB>m^ZEixS9l}f!59TA#KrnyY3>g;-({3q;SG@oGgz^7_Z(6Qe# zhrG~+T{+Qm-!_qMmhQ_M#+<;;D`ybnB6&t{!zmuv1a#|9+sPJ#M1)FsX>>#efhr*` z5F_HZaz@cF_EY=lgv4#-Q{Tlz90GTndOWrgOZ4sCkuOJetjvIr5mJY+m?4WZzKYVR ztW8NOb=XIZ)SY(6vP_mg>&8?i?`bXQXjJfIH%lx6CdA@hs59XHwISq4Z_7&TZrzGM(+p zd=sm!o4SB9RpQsl0;*1yzvOS&xIy>pyQzUa)vxh@7#wXUIjV2#g9=px)~F=I z%?91oZk~V@#K`X3IOhqO0k@>Cp^6l=A9Nt3?85}W20K7sT4Qhesf_;HD5#Q zMKmt(uDk0d{k1G~em)E!ml1ccXUPaIz`N^Ke1(-j?g}i1+G*b_HF8^qi2tlW59bHB z0cMG;chJ^PIv6cu;G2vHI5j-n%5PF5mQ-gBEeuRfeN!1)4*2;1_?-m%TI{e-BUh6B*8n;37J+B)1?r>|y6I@F7#HrXE|byKJdI zmMo8lXmKO=9vfEW!k_BY{M67lAK^9ZZ1~NzKI+8`*6YTQsds?sZBY`?@`pE(?T;9P z-V=M~;J0eL4@X8xE*WRK;SlLiD=e3dt{=k-YI3uvlh|Yvmx6sUpNma20V`S z(Om*kprR~!JNDnn0L97alqc7PE0{9WAT)9` zLeEA_>@g=-182yv%ri}6IxwlN<3Ll7mMs4cu3mEEwYQ+9;Q->C$U~S$2f?uh&lsgd zs~1#K9Tjc~BE?KviNgZj7vt8`c{+c<6pGxtjG(rk6A-7lw-+?V4ZG=l-#5C>4yAZT z|2MD(@A9l`W@|N%&Qc3wwWWJ#6+edbjNZpJu6T5+JjvBWeGsW*Se8aW;F zj8@c}10;pE$oUOsjB6FT_%+#_1iO-mHk>;^bzUy-at=LN_`$gjatE_D)uNUEC_Z4p z0P@E-ho9M==o*Z`&?RG0sLN?`beFp!41^7^e=coWPBu!EmND394pnnONrP~9k;9ya zed-p%70;#1N2nIs;fpNj8^PT`hrft&p3&lug~A@wC(K7%yZInMlk116NW-f+fiAXZ zS7krCuhe(PWcs9QHqVvWU#HD0a_|Bp)?PM9!)?GoZH*pUn7E;yrK4EITI3lpzto7BJ&RQ~A4;!X!1Iq459c%WR0xNgusb1{lI316AcWr29Yi?D2qn8ctL; z(LJaQa2X5atbbTPiJ78wntv$o_B?;r#_b?omSNB=k$>KSERTxT9`X!0zYRD9p{vFr zfFH%~FWiP@c+UOQ1G-@dm%EI%*)~;}sj&?q&^GrqcIdq?si}s`0SW%&rFoaECaTpL zmxFHop{WTn|8QRKKB5i(F&=IH%LlAvMDrI7UvV{k)S);w)Y~60Z5=L1G9z_B!Ncm% z3Dz1!7%f+>lvRuRF?~;I=kSOH0coAcmtcw!ydwGTp&tnmudtNdiIeYnr#pPChm0Kh zrkGLV9Yu9Nn7I~w4F+cnfdVx= zor^}SPW7}na{`}Ah9v9YJfFX=Tslcp^WUW{y9EHpO_|Yr1qiJSfs&tgX&iFVnv3iJ z;X4N{<=x?}`5KQ9%DiPf?WcRjQ6}mND)!K3WPyR_D{c&!FU<4>7Cg;!!MV6)HcaOn zuyX{Qj$6!(`WEpGd2a-%trH91l0|g5e?TK%OdC7zcJ`83gzM}qiM)evr(6T$j}0sb zIw$9^F5S8_1}_nl;Y?Xwo2I+IyUJ!= zX@e1lHZD;Hr#6Q;`^D#;&|?_~{vTKGz*uM3b#2FP(#BR}+fHNKjlGjJw(Z8YogLd| z8{4*xFE^h1%KQCBLNt zxMRFFm`2vYNVp=0MYpP~e(lB#wxiz{rHe=WK@q?C1QFvY$ax6-QB1wD}baNj< z|ISHs)S+)@k8yFTZjhq8Kv}-%SMZ@POCVm+_uvu-zO)WC`18fY(k3&Rm{(WlF&Kcm z)AO$QeqF`Ud>CbU%Mfv@aH|xfBsV-wvDzhyBytduDUBM3d<#ZvAFK5!+d%9McQosd zC_%vgu2Dv;QWpOV!}nMTYm8KrzFc^0qNY%%g>_;cN2map#atPjsll8B&>1i9@>m7B z<)m867B{9Op5+KDR%gYs9uc?cttw(ZQ7Z;g-m%R-ruIjn^nFFM6z6xq8IXr*1j;z< zjR~ijYb_syf^Uk-GtpI-*lLI=emb&vhCG7Ct8pn?U&28V1Lbh4St52Z%j;*C>k`s2 zYFdN2xL z-Px+TjCn1R0*;FU(DuSJbY z!ltmYFaC`#ldcin)a8AsIqAml4Rpf0o&2xpQr46MmimFvy7rXYCB7zqCf^fNC_JMua2!6)erhgQ+Auq7QLk;$=mbI34 zuGJhe_cPQH1}?oLPH_2I>dQ(l#E)9gdZ|-YtaZ@ZBuzvvD7?|mzlI+tFdx-kjY?wV zonpWRibBGVH*K(=Syu`5s7@uyTT}ZMg=#2eLDOCvo*YyF`e%UxabdK0lhZV)z3ldw%L7Z;8$%A4=`XrTWvS z5hU;N;k;iRnK4Lr`w{W6pf=t9A~7y~RgY8fa^8wDg89y+c^vRpDq%FI2RTu(f(ch} zT*NyA`?I zeqIy?{V)z<`qpC$==utMs*ZEQ>!RPF9a9c$oX|c z##Xc+P44!>@TE{`B>75?!dg>$4Tp0;vu`ho>q7*y2JbB+RfHhed2H3&jgG#iYnPkj zzglP;MrAUTql*mgg|P!V>kiZ4TmQqrslPyPTPoWmPgWy!x9!&&X?4IF8haAhSfu`e z?e>z5B1f-JsQ1k_M>oVXBW7rehjE;M?`z$M> zjGao~%yzo_9A;#`FD{))(}RtoB$_0+eg7NQ3UD>xDvrnbQN%wV?m~sStmq&IT5S8p zL~(wsKY}2}!u!CXVeVY2`(n`T;ggk@_gECTnQi#Tu0U6n651C`ew0Gp$q*Szlg7&t6=ES{*uz3UP6VE*{a0=@#^{njvjAKsH@^usgkANGV5EdmyLG_2sCH@ zyoNcaek4k-AQUE7nC*quG*d>Mev|7hs4YBj43wppPwAO_A1QpnN^w*`$dEbO31X|cD}7fo>;Ro#3@Hig$nW>cby3J}>jR}`G4 z(Z`!R=91ff7)G;}Q8*pI9E8!%6B1~cmD2C#w#3Sbr$$N4Tq*-c1AP!t(J;l#Mk|Xr zr9aH;!G%+g2xcFfKXiBym{3(+pc|Z|sYT_djE^ch^^7Gu-IY=TKMP-Uw z4}yd+jgM_i0^ILo^Dj<4X>0!?SAWg8&ack;kcTMeuXtTD@B9ypFzM}hG}D1C-U%2P z;D`%TDEBkyB|OfVu4(#yCI#ve2SBrvmi$yy~Ih?!`u>(i7#jMmLZwrozdP%LCSY1PtV1r*@9 zBy6WKX@I!!jTH%BN5NsL;E^W&PlvkIvtA0&^!nBDbbF zT+bMm2~Mhhact0dn6_n}#*c$Xd8RQ}kEWohv+P7r7kP0TQg~*mNQl=0i+^IJlAK+d zQv5f6=~*)-_1m5Su200jp)#-$UwLm!+=Zz8XYU0?!oF^;N=n2zY%HO_Y)Ue?_`)@Y zr=uR|Z@n6?0XOfrz{O9WQqC(BU36g2y^&;%VX{f(B%{Zawfm$&DZR;uL{qXEZPeXg z+iKr^j`(XAk#nHqKES@~*GV%;H;*5cI;#LlUg2Ysxhd2H2;wJLdExF*4e#p?b^1>8Cdg|VVp6d>tWIW$LurM(*nFJd@6xdZJ->_7{ zoVMoV;#^`x2j|Ki6>+3!${FcP#am-Tzy227N}=(EUg{rX!N0J`ujK0J!2O>$sS_ln z{S~Bc)ic7@1?Nd5dxy$Ytz3jomL#>M(my(~fHh6iC!I{({8`SUMAgh`n-Jj^anBGJ{m;`hxBNO3o0D^&5*ZbX@9WWNLG?0x%a<>*r8FLNr7)EKa> zKdfXk4U@D{bjzFQ!NiI+frjBj@l2FMoyVM7G<-S`vMo<9_jbiR_RC4p+ZmigPG+{D zoo0-vVjJ1Sr!|K8s6nmg4MQSnwxv4+fj2K*Bh{nX{ub}K!^(!11kLjK5CxwK?9y^^ zE~wv_JN2LA;LZ3W0zP=@x&%zCU>UzDhr|mC$B#30=$Y|Pk@Rmemn-1KEeW?#UUJ)V z9F)s);i+{qIN1QmnRt2r{Km}~Me|qa@IV~96&VK<}dYu0O zvX&R3RE{)~8ao#OsBDry)%szHujA0mi{tFv78Lbgz4?yu|47_4{}A?KTHO58msA6q zPD#1+8vRF)*9mRlxWyG*>2=Ba>5lEG!e#uF2F0ssWYk)RX214S9t;6T`y zsnpDX827Y1bpUGyDmti!z`edQ#xOL>9@C?!E%=&1jlatywe~ zMP}e8u;bmC~HwIiWVP`Mss+t6K^a<95aY_iumbvDreVTcD^&ovx?Yf zNWwthSVy1!$ejwi_u_Yff#@~e(6H69bHn3};i83xAddBHx*3_PBEssBT&j3gPB#6k zH*Kb*Z{mG$1nr}Z^A^{o_EYuHRlx^EEs?A`G1ACZUN^S~LI9=@O3zGJE@vYEN3;2Z z?={v@i_8if=46^PRS(7F#k44` zd2+P4>$xIpG&g9gu9H4#M?GY(w3>0~rxueT9pykB_hA9(uRa+*x4&vMy$2E9H|(?n zoi+e=xGT^ITm~2S$Ao^4UquQHLq{l)Rs_PyzV>A7j9 zSk%Z$oM~IXzc)!amcuRGfngc7iRjK%|HOo9O{g7?5AYmT?vez;-*`H<#Ae4l&_+{m zGB0kLFq`t`3E54iFtIeS99w)AkDyYJCP!I{m6b6Y`L9pbJRZl~>#RD5MSBdxCMfv0 zru8TK`(0OGOk**7I8ar-izx9RHwVwuNk0AMh^nUVQR#&)_QPhF`X2I#?6jNR|R4j^sb0PGS1;LeiG4I%B}Ltn0Sg ze-_)IBQu3#cM$u30F($NAGEXqW~nn-eQ1zi+g#sObZ?v3 zWwTY`iM|PLnZwCNP^}5bdb!VBrqVH@Y_s+ln&FuY?Ua`lOjph0LxIXs`WM(l6*xru z)kmJe2_=->J{zehdm0b-u&rF$Xs*E`V!xp^%BCpoH0~2PE<0(A}boGHV zPW;=AY)i+{)I8_x)FZ#vl$}o)`2^G9TuE-dc5C&yhx+Hja3*c$B1RJY@Rn)RNAr+L z00N@`=eR&Q%%FEw+D>DF#da3)>@T@;-w$6_ztgNz(o!D3MEd=SR#$-=>sDow+R9)d ziAM3vlC5AcK{J0PwLmb8Tzf^-X{zPubXX>DQPlzuVePBz|;%Y5Gh>s?S~eW%Ic zvxzCVym$1&DN6k3lfTIfdCZhB-gSi^Z9hf&OQK&;Xw%dL167u|$}ewuG04ewH_Fuy z33Tb7L(gfJd`YMbni|6X&lW$Oo%pGYn7Mn!xDHM_(e|BeCh=oFPliG%QfVdu zn#Nt#U#8R`{pdEM^B#l5pFq%`AMwycRl zJc-kRSHr0;wJ|1DXXJ11;8#!#R!Zy{R1%grW$snG(=4wRzurR3@|9h-EBnTssizdm zIJfaf1tCMCDa>ZWxXKEnTbdM;IW9XEI^Z)z8^l6|6vbR%RYg=3`k$bkfuG{-2^>WD znjzu4B$0zf16_ZeAZ%GM{=s2I;Io0NjrP!XqK@+oQROqVUH7%tc9{{GH3ASsHR?k0 zdr!hQ#b|{~vZ~^A!h2WeW@=rL7_n+%G_dJ~kGg7xt{D>{@kcRrN&Zx3OhKn_qW!7* z%~v&fQJ*(`MX-7B>(9}NrSwSaf#phpw3|{=&VGs@KwyHWjG>_xBbef;=|DpaysGIA zICM!X-2!2rS%p=<5KjAj3D`txkWVb+$9`}DHiDxw&(?Hi1~}|n z{8B+}Fj#e2qgi@*4~E%H$agNiO+*;=Kdz}9DbQVOwz#~@Cbi*`TS@w@(z%;?+wtFA zlbFDy8h&!i7jqBz;3_jBA;6~?mq&@;i+TZExw?=w`uMIIS?I$&)tYH+9CGZi=YFm! za}~X1o1j0GY+B^NvnZM2j$rGX!o1hE+v6f{CC|JN&#g-Q6nti|&CGIfpeMa*D%AC| z2Eh%*i&oh$+bs_ropkP%X~CRgCdGgVHszNHeiZ#r#y0XlFCmaca!!@*Z!ac0T&NB< z6PbmhO__gY7h0WzaU0qmg3HP`5MSBkw2{l(&RuWKw%k$3BF(sp{gb01JLmIZu2j8C; zT+o;0)L zNc4f;Z(~)aaXXb{fl6uZGV_mv>pgOrlT0*kAL6i0IYi8w>9;AVPP`CCs|-rCMkYJZ z^5F*!EvqGwR{EbsfCC%o^5Trli-RfnwBHpY!rrr#&YI`yFcJa(VVy1|aE1Ex{w&{l z6jlDFmxDt6`X>enX?Uifa9s@%#oH*V#prsBb`aYz;B%g;|Jatq`%*D78pP>Lb2=m5 zD(4=Ab3B^K35p$Wb^VBcjNP-5_@Vd3pWZP5vS&6^h-WZ+?-tPw<5Qo+}=$ zz*y|V6uFy~*}L%Wob_>AORXvG(7d?&Q>fIh|9d=EO~mu86x?I>>_Xp0)tnWXC6M^i zTdnV?f;w^W#ES_z2@07Zf=wx$0R%N|(`s@_*%MRM@IIT3$vZ?4LbpfCTa}JYA~&}Z zh>KjREzjdbk#-7g7X$>lRRnAWn7q^eFN%!Y=uHCD%>KRHa)F7q!uB_SGx%GesRww6 zJO7{mfKVaZ64h&nZvP^o-f+(`WR?G3UuG#Z(JfSGT6Z8;h3J}o70eH2XqSS|5Cl~DKhdxYFNho5hYA_eGCU>MXJ4{w!OSr zLRHtT235EnQ^PW_?HXKKhDeB!nCqf>4KD}vJQ(gwY9PY=q^ zV=%E`@EHKOgyn`MJ*<BKzEHRpg0ut`k%vbzxNxg#3_V*a1BbTRN_Z=J za8UODpNK*ssy)xr2#+@Xco6+veEKc=0_}Yjp;1PI$vAs}CBldQK-h+3DW3-;R-N#6 zLqdn7bXLa;g!oCz0hON_Pes6RTW|4H&8;WB)>mw8A?~7B&i-&_ck~o#xV~Q+vmUCV zfdb-1tEOokI{_O3C2GZ)6{GK+h-&OfJf=TkdP9+^bZpoKu_)PZ#Fj-qiXLyAGey~C zDO+BISF>bKH-?7J6mfA*e7vx%90f%7CzR&sKd^Q`@%^#p{v%oVImlbKuLy0%>ruYr z&U%=B-a>to^fGd-W}^YR8>-sxjmBh6?sMO75>CJdiRI5G4)6C-g1a4>=;%#^-^Cx) zR1_pir=;Xoy83To28#hjw{?Ogfmqrv1nOO*#Qw%zd=dXbrU?68G*ajTc7eaYqmucG z#PHZKQBKE4q!0mSc=X*#g-wrjJFKmiRwLNFJe>2AxjT!-K-8oH zY~&Aau-sxUEj*6M+$|^5^=_DR`1jc?PsV~HdUyJ6w~PClk{31n7nnk7je5tcsWy5( zZFV&p7$Y501gj-Ln_Qqm3%X|c39nAZ8SyFe!A8vFyAhAfHTxDCBRPHV^?_w+A?!=l zuH0pzOTBTT42K)r4}fAxs#W)ZtcKii=-z>dGR3KzRQ{JK;e@cI6YzizGZX`})?5p> z^D{n!qGrOl2x9r=h$BoXIMak%s;ZNHRbA(?D%I{6BjK=ivPJP+1xHo8dgw-4o|)$s zke?dWdu!n$I;Ugl`f_JazN^SM5dPSq=HSYOxEIbTR%zB^o0N=QviA(tkEK?0PTIYH z3};OTA(G9jtoCMxB-D`Y*_5;;-#1zW60j-pk@q;bw+y#R_fJ+U4%{jTF}RyTRm6#0 zIr?v>{G?FPUk-tv(S9ZHKkHtL$VbWKoSL}?tfJ#Tlfi>zxhCQY*jG)Rh_q`tplbdL zR&7^l)Eqw4s8#=mtiodsaS<(09JYMyV!+()g#wmO<&|V%Q zVzG>jSZN<)>B*v`8CZ-Xrcj)GzOK2>+1=7+zGH}el@N;Azd6XWs>vgP#~l9f_^q3n zmKR!mu+Y{CwAIB9xRJr_*8&EF6WVbAwm@BYD+K@b7~K#5v3YV)7fyKgrw4f)A#=NG zRzKxFOlz-s{>)CQie6C$DH=4ZE*!DSmPBVD!oGTbSDm_w>^!S~(~GwQ~YCQ|6Q8|G|_Il$#I-FxrQ z`~30ELGP=oYkyL+D}XWN+%*s<66Ht=hp=i$7_IEauGI#XkJFuR%1B2ULn8L4a{?Sc zEk6omvMl|;siTgbW+OOVdoGTPojUYe+t8Fl3p%vZmOa4%y_@ARYj?bcJ({(U=JL2% zQ5fCgG}Y9mE^oB{1ILw2yTZLAk1~sxZU-t3-_cz1iYir#5yrde)?Yu@);H&Lg@68# zT6h6n*INtu4D!Fnr9O`M*Z3;B9}}SrcLBOhg?{Gm*Vy1sn2eFeU3y=PkRh;5YRmra zbt4wRk=VS70+71`F-|{XU|-VQEp!Y`8A#`VzE2xfleKm8aOJZcHaKG`8SvXDn0m%9 zIt1^buH8v=5@3#kxZUC%3m7ygTkiUS;i#SeC9!aDV!U(O&{}gzvf(K_o12q%!kVG1 z-{bQ!VTJuS7H%|3Qj4}Uu0*X|U>$zJwp7jnnOLIoeaQY!I`ClHrl1-|=k6zo#B_i> z$Wv|@NcKI4uSP*OWM|5)_xy8N(tUI^{{cG5%*$IY539B}8W+DV3g`Wlxr6i#_H9R} zF{1`@?;t9V#K2>H*+{8{H=uj)r&&)5&deFTmxo;DH=i)ANg%0KA05>DOhxzwrJ&z>w5K>}} zo`=pcN-wRCRNFOc(^Y)LsnG18DVWiCzb=cl^M&cY)y3#M!g0mpB1V;+;jN%Fg!|n= z-uF#zk6M+Hy=k*JQf-_S22_gXd}>z7=!Vq`FLkoz!)*Wn>wTjlt7>9GD^o8>PX! zXRGXa>stY4E>iV7NyHL z@YyIM$wl|2s5wTp0emdRor8t0IKXPp2HTLjFtr7GXdfoyf#eSGCMuYTU5j(`d#v21 z<3>|Ecl)UKx(Zm&LhJQ9@Zcx0)KeLC8g1AcP=BRU5bK4r2%TXI3f;A;nu11Y1Djr%*k> z@T7VSaVt4OVn6WEv>t&kKB7xd6jV!Ozi zvjQr#sZ2^yI#yNTpv0$r;X8%1^A9ae>O-9(nP3+Z*1+!l?XwExcrI~FbQvJxmUZwR zxM~=}&J2#c=(Z0;onP{1=;{t4Ew^c{v1#)%OGN7Y&ecWSdI5h_hZSz&YNY+^OCpz5 z@hlbLE!xkcP8GT&4U$$9W>BxuK00`cjj=m94gCtor`mjXbLI$WT<@ zd~WS`$O!PCS{|4yC1eE4t-tKVzQ`$6@V}3Nk;tzPWNfqKD!S(jRB&@lb=FBDl~9-t zw@ynOHhC?Qn<^Rs1I?{4YCfn7PkX96w$tSmN~!3@8+XEn4aVlJxiHk&HLf^$ID43! zg2;Yecemy)G08G^=1{!?|*`o4+WQo)YDEbj2*d03K)e;!zEi)URdEDl0 zcrrGV!3QNl8Z5V;s?vwUUk#$0CtQK1i6cDvg42g%Sx51Lnf?Cpm;LDY)0N6pc#jhN zj}Zg#WhqE5EbO$NJFpyAmT} z9z{QgVOH@BhF;4Z=0d4;<9sS9`6Lg-#=H`jJL*M6f^bkhO%45kYI}QYyfBXF-6#pl zuZSUD?;jA%3Lim{ttot|fpSv=hKGr)gb8H9NpP95IV<{}J3e*qPvWm+sphYKJD;!fpQ;)~5y?4J@AqPd%VG{bWCG z%NH154V&{hQ(2AlBE!G+PP~?jGC9i^7(z?ahvO-^`}78kI+ToW zy$<$a9z{SSB(%WW7wMPQ58*jqaY;{T1L~o>Bo8!ft5X_RX-S~ogN3MWOI0h^cA5(s z-g~DYy^20?`J5Kq#>RaPU|Rg`>IdRLs(Bf$_^99QkSl9yiwkulYQ{{=Z+T&q*oDNv zUfYh2V2JTABJCOiwUEDa-`udZCqN&I2IG+4Eb*P|hseJ7SLON%=i|dQM3RvFJ*7U- zxNtONvF^v*baZ*M>89e;($bGM51Fld?Ml5!44W$0pUdE|o`<9w38*8O%DSDoqc?SY zQxBd2mJ!A7(r@KI@;DAre!497(+rnAd9TmMs8Br#?^Id=1)cr_q=k9B?9<4NKE?jb zE}k-jnM3H&X-}OPYDXggzYmsy@BKxa$H1ZY!DVdojf|_CdyMi{<_K)-!>F+d9yg2x2Y$q0Y@NED6FO3=^393su!ldMRML3)WTd|73(hO7 zaFCI*JOy;%2eB=CKdcSdPqBKEI?uRaOjPlvldb*0NNVReseU_(tB!n?##!s(**RE( zAjdU0Q3?m7a)$LM%uomPtz}2HVK$00Vr=fK1jpD^xco6Pp~t=^#8mW2%;~n${|#sB zkZV-1f?kO1{lF~8Jd9AcC6;^Kxj9elHW+sq*@NW$Dvf6G_QI_sNw6pxhg6S4ZP4XxIz_!1ZGjFx6q=kEk$E4L@> zL3e>^m8Ic}hi$G6;*3%9nYgg{6$vh*IYg?Dz4N=TcdxJ|(S{=U#qYZEJCrrtMRx*! zAY(0@@exWh`YF_TGAii~BZvMHCP<%&9F_Pt-1hAzdAohmweyR2`{1iKz1D(L*F?9L zXT5L;u4B78eM-V9fG3Z{1aV zZN9?${~BG$5NTU){eV9|vZ$#gBKI(A?{|*A1s%h%^e(mX4*ZokPWVEn7;+o=EPgtB z=k2e3)Z`SIu#}RFImg*RMCg_a+qK26RAUtJok42cC?8i%+pL)mctqpjk9R{Pi<3|r z=$5CaP9(22*8U(0?zmnH!3sBE9@eLmrleiAmbKDWsw!gRi+{vwbpy-g$l_fY#u8Z@ zu&Q~tddTgiQk`z~<`PqOS-r(tuMj+P_6)61Y5ihSeX9ft3JwDRm2NMCLk)*kGruu$ z{AQ#PZa-|MCW8;Gt+Q2VxxK#P>G>h`dS70&ZVGQD?*HJ``OyB`RhJ^JtsVWk> zd)tw`O6*gaD8Yo#@LYS_t;0toYC*rWkj06$z7R^>-;#%4?ovu_+(2 zFv1ggFd($AFO;_uALMsUx3z-u8g%;JVa`!OpEUMfp1E*+kMAD}?0V zNpJC@2pG)Z7j(1S($=$en-(oon~j}?I4r@ug^3%b$vaA*lIA6INVIMYauDUfQi%+od=$4@Qp;9vP zG0IebcmZ`~7kxv0ms5%RuVz~DjLs(2A~+nst(xO#OXq$6Ia$yLocvAE(FCjy&hkV$ z^VaZGpw57ol@BCbRppCPf<*JN2i9xsCR$Pz{s@RS4|L|bZ_G>eRHb<4aFY+jsff-GhA56tqAZ`3 zX!^i04Cw60Zcj#;ZM3Re>Z(4DpFeWiasETlRTzd;Y=u6zm8PWce1*>3(333D$#y8n z_!^BeRJ*iJ(=2OyBTVC$X8z@fJSxF?K#Lvb|lIw82jEGi1Y$Azow zlc3`76T;a}l`(y&)gv7mUndm%j(VOz3&jxb^>Tn3!{i<{5R*-(1W9uPXvc-iUkz`e z7S;Xdl+hqJ1uN7wI8-UOY;3N%BJajdCD~ z@1$wAWxhFQs!6M=MVR7|BH=w}-hI2Hq*pX5(y9HMrk3=iffB4e^(BuJjdBcx-oU>H z+<=mIM*Y(*(&mRrxP!XQ;Ym7bf}`l@)&E7Xd(16%zoHqL%#TkX+wlMa$eLqBtkvffdao5?9@&`shRr^@ux9>Q5Ng zYBs#Ajwtwr=`J44m3;fain>G^J3ZY%evxL89D*S-z;z_*HoE>HUY1yzq~}J|HgXex z1iNg0or12-xK_7}2O$*XMX;vY03&k1>G0<(gnIkKc6%Zy{=5BZ_vGLgfN*3!SWl={ zgQ8UAx11XOvSPc=hMj41YIB*blf>i#b)3$`$G)Vp)^_k>we~_8(=qsWBPgyq&q79m zEzC>>6oBxkIQOXJSmh<#fK>E}R!Tm3$7(Z}3P$Jip;hgAJbay1EB#XUZa(4Pq9Yc6 zn@ayrua>HhB?XZ!(X5C-s(>;X;`|zIY>gK)zl!qPPbka028lY6qU)_MXmG3`P78-- zim2fnj5)CXhU=Dlk|&=_L<`M| z+0hxnWOTDm*(@<~_ix5+_0uU4j4ikitPU}Si;DSXKzBG>Kwyc!B5)A<#F|9>h!;MO z#5OyYbN$WY9*R3dO@N($^%$pT9<-zBHd@6t`?8r}X%=`W4eFYb^bXruu~A6|0|idv zEd!&8t)#6M85&U$hMd)HIg&0~>C?Yz4%Cm-A1@%jEYt4;E75a(J&zqD$5jujQ0x}H zGFGjQRd=G&F@Moki5%>F3KwI8`(OHn@Sd80iDfjYitK9su!0@to|=09`*XCqRBp%L zGk6K&L(1uEi?CFXf+7jYpICc;9^}q_`)Tq8ji}KHgEU$V#<&B$8VunQ^KNG^kFu7x z(c8MPlnq1;a9tiUg&3AgGqo37eN|qsX_rBTYa1*oRf=e_?u6k(($AFE-l*-v_!=Lp zRQOcgH^Bj|nb4{daIJcb-?pCsOGIj>s9DYtkm`n4!DmK^KiMcVeuh=UczAa$b8;3I z$H>o)&1_8wfB8nphs)q4o;hnk6PZsqFz`-7TJAY5Nd{XUf!NEUE{n|my~=N`{7$zE zv7@xaK`~#>Gm8{lsk5^{iT$<9p=vI0H{IT@Itb1MKjg8)_;3VHXt+Jii<{cc>?}FzJ@y2RPnBz?q{cDMpTnm!^ZjbispX(J=bwE3)*K zryJ51CmA%%^ddslI|5YY98=qc@JCuaZ4H2c>e$Vd3HAxv3I9NyGO@nOdQWgw&JZ0R zg2IQC43=_qgO;0{AbE`=#;9LqAa(cbFHwL};6X!QBu*Ft71M|Upz;|#4-0Nn$O&h- zc@0CD3KJDTkkxm?%mWtM6CbGP#3Ql&W|(kqVFe_6x-1Y^EbAyS2M%YXmhH-|_OVx* zuE?PGz}bs9hEZr(SQ+faVy$dg-^;my&e|E&!C9O$sxIRZ-SvabIn*tx!3NtP_AXQd1Ez62VQm3gBiC`y`X1D7Gj2sNb8qh92y8Gc5 z#Gdo|Gr>V-(04&sB+Ff^al5sQ{W)SQNObYBveY$i$GW2)qFzt*7DAx>DBGu?-YvzD zI0r$~iome$I6{QX)uaGYq(0@pAERAF4bck6zLcs)sWM2BzKf8SIZnKoN`;H_YCpqG zm%7-)d18Jff1Q_=_Ffy}HbHJH)q)P5isZc7s|j?iQ*drjCUQy?UcgW@is%h*{&0bZ zWw$`+>?EBI+@p2*8_^@;e`g-dzOX=kyP*q_>}dHs_z zyd#Mmx0auPK6aPOwCSGLyp!DN#JNmOkh~JD!r0yqeb#QqvMr?+STFP2RjDtWn=BT# ztzD7=lGSd*hjWsQIl-E4RWb|JrN$6Ki*nk8`0GLZQppcNOGZ4-y*DrUawR2ZEtRk< zn)%1l;)ss5gUp2=V?A;f#Ei-qfn<2T36`@?1(LHr)Mqpy^i3ho?2?@X&Z^;Uxg-Y@Kzc&d3#1>9V1zX~!aeu3z?1or#x2&NM+&fkKcW>s52_VLBqg)ORWZME%a0 zTyptI3&t2(dU7Um7VOw6OLHFK>^S)PJ0gjS z85zoU0Auy-7H#3`IKJ-v{y(t~x?fUg7l_0WkXi@P^zB=%#f|dvC(qgy9;fi;adU^H zlgc~pWhd(sVmA$KG~B*;E1Z{H`?k983z_5Ml~0a1avJJj;F#-2j%_#klx@yuguv5W zf26;aZP@FmGnynKYOGI30X>iGRZzQ2vXR`=wdSNXpcRQP>5h%FA?OzQzy(Obahd%D zBo?P2iuxDDj>xI)Te*>Z9;aZZ-P><#8>u)g-Ir-Hfge?xN4P-WmnJa{+h{@D-t$OA z(&txS0owO_>7r0#h6=-5hnfXyq;yjnNEn*ixl>Wt7^2l$jsr-)G_I<|2|6l9`xe|? z+%ktjx`;T%0p~v-w(w~qm>1lO13hTyOfCJ|TCR?9SNBV=p^>z~X?^gx=1Co`NWtWT zhg+DH`Hp^dW`*quE3%f55T;(w9Rp3j?Rx9 zDIhHQ42LVD;Me&ZUNT0nUfh?))w zl4VnAAyDs%CAQN{Xs+JlC6m$Z9>?X3)jGqy=}g4vJIj<08m^yE3v+k*&o%XSAJuto z5kk%XvxNC-0rBkz>O5~+^7v=J|E_yy;5uuYuJ$xO0#vH?s8sdnYweQS8}G0u-GeO$vQtTV@rw?_QK=Jlf^=QBe|URgGS<9cnMFR> zH^o4=DF!ADu7gNbki`&pny9>x0w>37;Dj$3{hOU(m<9U)$4POC$@1%0SJj4scFXS8 zn4a>Y7QdpqBOjS{UtMM86V{1B((62{L_X@V9G`x(YX)6a0cVlxrwqT zp(_lRRB0OD2;}kjXe%uj5FNmxx<|&QjZ~DeTZ|Ht)Pb05ErscnSO`Amq-lCTzq|~( zwJ7AnvzyC2C2|*ORlZw;KcGQVn-=s&fU>kN0vQS9vH19eUk-%z!-=YmCl7A%(YvDi z$CeBtMAU>3yW4-S-wXoIc}zk6Y06$t|K{X6tq7bSfI*O#<*%THG(=0^0V&IbLEO<| zTaI$L*|NlVZk2rE6#&02_v?b>i0UFRb`1+UZ8W`-Y!16)+>mSNniJQG>52hXcU1u> z4Z1;`rXLF2DO4e+of`)^B8rt`!hC}O`{2S*iaDTnwJbU^LdAXrcQ5z-V+{h*Ed@`l z5x>oMHAZ7uDG#m9bpoPK7qn}c4FGr1L#6>(!H1-w%Zcriq~$!{xH9d>wjOG&y=kxG zb=JEhUxq%dH6)?E&_M&fXYE}~*D|fpTo69aGpnPkxL))TXs_`|wlFPO*TmhH0G%dJ zHS6cbys}4bgzmRk_e4LeLDIyhiO4v1C%M=V+b^rIQVV25dRyT9M$$#}%4K%QriUBt z)VCs4nVQOjx|j#S)R*SYQB`2s@sx#Z{!~K?H1*2kI+9_-aF+FVTK(2PI4!Wtt2{B? zW3e=By@4Kpm+9G}dfR8prsWSUuFaowNR1%5M9jF z`E}@T1O9-JX3eMHRwcLxzCN?3qLaYS8tO3C-d!R)zaO5S>5z+ZiQS4g`3@W*HNjq3 z8&L6Z>UlE2whMGr8VC7vWR;0Ost2-rRYSHkVY zZJris?uoE)YWukY;So3l4sXu(QmNakLmTtq^; zf&+tOH411mCPQE+^c!N41a41ZwouSr%brQbf?4)~)XgvS>78>fwr9oPCQ3h5bX`C+%Mh2e)|YtjyxK|&cL$wQ zkVUv>6y}+dQBpW+{PZK4w8atnbQcBDmMMkA({FK?1eYz4ViM7kvdATPaE&djk%P1G zPuF^^34(cm%t2%)<;-E5A8SV6$(GAVPhq96+UshATB%Fm5*rQ~b4qWUQ8CINXxMh= zfZm3F%pE{XqeVQavNxu7MwXxYA^)A9t|M|+6in}{uMZZ8^)EYsm4T#1BkOcy^Ha1# zN_XtYZT5PqHCZ&nAEtircVC()1x}RsIDl)fpFEaeh`Gp$mPl-a0ohn>3JS$k=YJlt zBKP0e_TtR*AK&@K0~G7&$Kw5NZ+jt|AE~iR;{XQX81LNlHq8C&{nYPg z;gW3l!(1_raF<3S3iXRiM)^Obt{3TH#DvKH&kQJebM(nD{fgh~r-iLj?(hweb-cV|^^LJBlhXMm z!C~h(e@!3#Hl^DnWSeP|%ngVV$^v`GpP+=NnsARZG>fvMvrge-;np6A|ANE7Z0gnf zsE=5$suBHwyUo(o$e6a^b2;c${eM`rkDl@K?=I9xK70n5)uu!f!Xqz@($!`YeNb=W z`P{3MX2_@-CgrI%jw*+lV#5x-9i(kUh~jvZjq|gK|BG>6Mdn`-lNkVobpn*f1?i|( zL+y!OR!A`SlKc7fM2ZPb*8@ws4PPZH+~426%AVd-KrvWScBt0^rV~60OWg%mcrnOv zH@Kv_7O85SI3N>qC;HZV9V@+DO7Jo)qK!qF5WC8$4ubCslQA-5<6wpL$OK11IE!Ub;N1YDnYo%Ey#h3Qn_I#vc!BEfYhfc49SlP0UQh=#b?tThij!RO{NNe zx8nVQ^AW?#N3c!97TpR2QvyiGIA`A~c<6%Y*ZK>oX?k?FvVM)^gv1Pm%kLpF_x#CA zkMF?NtyPrhcYWA;qqkY>58e#sgb@^wgo+@2k=^1jNNf)4FjMPs`BJG@RgzIxRX#LD z-2i&)8?X9I1w(y-}0`p=(O=^ioCe_zjx!@4QLUcaqcX0`fHo{veD`-`e@pS z47o4yVIiKfE8o>e8hvW=Ye~$7AD43R#tf-eW+CwUIPV3xxA1j4b1l#%%d=t1EuJuS zz;}{Dvv1E;Ken!I0X*qMFa$sW9nGT>ttD~sHq@9Y=N_SK(r9EdoXlc=A#UDEjm#(y zi{%%LlS%!JIr-OB%JG)HP^P7IRmURBd7YK&z}ao;43S@~;&)}CKVpF9BWJjaJ`19I zDvOtMeAN8JC!29#rZs2xhe3{mIX+T2R!v0AVVv<#>0k!V$_wk~&vPB*bczqE45l4X zW8w-F)pcVOb@0Q6Ct%j(<=#FxCdjvjzN}S8?+ksrCtYfpydL%8HQ@^#GX^ihP!hPP zxuBr+Xgacf;C9pUv}T+`j(O>&cRghr0=>2$;e;({0cS%D^NuRS1a1Mq-feiN%WG3L zvy0Er#J38wN}GN@+K_2hX?_Wu!hKMWliu7pRX0A{`n?RGu3^FG zPC6ktDBeUDX@VT{*Z=a(!oA@1!46NY9)Romxc@1)1z_&(c6; zL5+_WH|(P-p6YA=5Qb<3RJjOb9L*ssQTJ7ig3ofESH?=`wlTvuD&32|PN?T40*a^Fn_s?t57Vhm|jpt9w`dmP; zPq?fA);om>isZZ<*0O3N=Q6BdOtMFS=ET{N%(@>5#^0;fuK`T1c7+NSBa9D;ijkil z4}@&eX=NnW{e;|ID+NypZ+}ls|Bmy$v!36Y^Htwy9aBe;Pb|CWD=52W!xHqeM{het zJO9MRCZIzU);t+)>=B!>C^q?z1RRh+>soDrq2K{n@0J?T{Cjf`NJ9A z%!01%d=*CMe(4(@)V3(atM+=gUu93{c<)1$=Yo=WLA=t&5pXTW2HJKl9%lBb)q%TN z?$|-WvNv?^#Ai0M@~Zq=+xwQ%#PHJ~=cAhw_An}Ihe->BpOINvC5yg-*>sl!i=`DQ zs<2Hi{2_(9d`OvwXd44r*Jv-;ZCl9=hN0yZ(4K?dzzsdqr7XiCp*GGa8?8!j+VP8S z%o}n>c*`hq`Z)22y{vah|9pbxb&J>CI{!H44{9~7&71c}wAjmdXBJQ_pS&W-L&4*& zKLJ*pL4|Fv3c)!7rIt}HYpkGQZ9m<(l)fAsL5J!~I;p)*})%)S0zuP|oOAPsSWpAA)^v?0 z*lNSBuV~28;tF2-9xZJs_|W!xCNuiZ!T0*&nu4`)sZD7PMvez-D{bEX19dqAuzEU? zM~7EAf`Ox-zM}Bw<6C?FsSSYME7O}#Tr8haS)vw(=FacZd}!Z#hUUsqQVov7G)bb- z?NBNZwhBjaLL(gEnl)o<`OkN$F8I3#!4C5C!to|?#A zLYq5Dpz??^;+5&=VbTh@rBXF^R#6?j4C3L9O44~IX6?zw??1SwT}m3aOe>DQDU~<+ z0js{7(~KxFUU=lxhCVYf;@GAta3rj@a(a?$>;6eW(yA>@OIBQ6AwkgzuGZp+y7h8yd#?lUGpj3;R@3-?<>ziTeOZR(Fl~FdJFF- ze!=053$`^|rgM~`daW9%dyfV+TZbcgjaIg&6>1?mi`5|W6)rjih-4K|u^#O^XwaofD7Rh2n{W$rC2 zc_6=~8Am`ZYMK6&BMm)``T(@USC=XPm$Lpy3)ulNmr*KXc!iDKUn!V)l#=Au=NExs zb+>jxp}TVTJ}E0`W=_J3gFK8-^HwmYW~5E1{`JpgeAQ*Fx%XRPzRYLf^tw=p>kal{ zmRQ-|^~OcDUg_)0CPBXVf|JDG~P58j2;3z(DDO3wqye5r-_%_cc=kq1Uf7O^`4;&6W@aKAZ zQZYew#O7v(_RUE*b`S`?h@3g1sD(8}tQWK-lK$MweK6h+i742!w-fs6a7^&0R2!;0 z5+AG-Mjzqb%uKFUd%Z{CDV3j-OzrIg_1KG>XP6CtWq{ATIt|ZrbkGKhlB0{XJo~5Y z^llDQV@n$)pGT>r_y$|guH4M8L#qmf0!CmaH-8t~sY0akjk%=vhe;lal&(T&*>NT0 zME%+XYi-!8K@w*ox9UR^S}>pG;ub))kTs;npj!b>`6i{Xr*;ZpJQYimO;-vHW_>h7 z^3qJE_O~gT2NAqp-%#%Bp=kUUyDbi*#ACI?1_oq>`)A*U0Hi7H`JCzP1T-twsJB`h zHikO(kNp(;Xo#~dl&kbm`dDUmEHa+65qhPommUzRKuD2LKQ;d`#GPFieJRzARq?)0 zAJ&b`mMc9a0VT@s_SF()rcGG{7{A>hymwy#n~!M?V$1t2p^1A!zlAs_aAbt~mE;$- zMnQLP1pcL)yRtK?Prl{q3fvvKl>ax}OO{uyu3tr`p;EWi{>JFmV`WdV`0ZZW|HU|= zNczp}H0tnHpcw(d${PCG8ijUM+^tGIqNb`m$BALb{s(dbMwQFJ6|UD?v=)INNIpQP zf<3wbPgeLpL%dJ2g#EJUSezk53Eu_n)ww_@JBX&HoQ1!l^D^kx2TAE#b7J{ZZ%E?*0U|rcSKFO{5ynMy+Qn*g`RKyv%|S3 zt;lkR#Qd1qrNWD5WC1?DQj=HVk(_$6Dh@oM>5VHkzrPtV(*t@&x=3k+J}mDiN0zZ9 z-ENnLJNPylUGKNM=iFyInd<^3W6ouk=a%JDFEIfC(?|v0pDJ^YX`r7s6$&kFEW@=p zs-}DTKjYtJz*KD@dr;9~1w3*8r<+4GC9x;_hu-4Gb&#zvVrFwl1tQ?;gl18a^NxRI z_rrmHbt4p|jZeHgf}D^dFWnYjm68M9(sz*q;xbXEqt&;353f%3gFA{2hNF!$=HR4U zq2p30OvzQnj;@2YW4-V&0d(yl81@@7SH=p|lC#=4UgP}XwGjm++mZlt)T1-HRJh)!R~ZQ(b+J!=+;;X+?$)BefZ-1QP>()q z0yPn2qAzp|^VHP1$$g+l*L};GSAay=iXJPOnaD8D2$@yRbyOlFBqNw~sf%1cComc& z%1^BYX~GL1q3fVVc^@^^{OyMJ-niM+=HYj<*yqkAC5h-YV$+9O|Kz`8#~n@*KAb&u z>JKx1G4+G0bDF7Cn#}&RzuWLnVS-#JO31JW7hz*Q_Ir`%A z7AgzJhK^*I_VKIc5*Q0Eq`Dct1`7$K#0*p6rvOedlz8K~&bPshfIokz8xV%(@W*x- z>wK&OUm_IGIT3*;kt5ysf4S()lZ{Qf*!pcKD*n3=bHDXrU70nwFi-oJjcoAJ^}3TT z-G5Rw6*48l{}N)&@;h%OTu<_Pj(u#Edco3eR0{LBp1}y5@)X0rr}tZktshMix9^!K z$}&j(YLd-nNr?bPYI>P>H$SzR`g0;>1vHcC8xYyg^{U}-1bk@0^Dq}Y85R}IcnOk)q8n7Qxz_3$S*6V@mkmfRv#Y@S)C zT@jOi{xQsD#m+AvZe5ATPsb9{=Idb(X~k6}itF`~32LfW2*!U%o(|4x zS~`OAn;D(M(`tsRt!G#GJxwj!D}z8Dc;QaJRVH*FBvuEKWANEFBBw*FRocPVxLjk= z*#`%rtRD?cnbS&@$Fd$i@>Oux4+=A11ywzSi0S>8>QO>0 ztBbKWQDhw}J8RfkB$=mb$tq?nA zzkJGI?}{UY#*WH2H#Mi5?fw;4&0gMlX;3A`Oen?Qp?{%t@1EI%GXg+7ZTY$ck>#@S z$jXh@?FVsjeid!nY_t$*K>G5mr02SKQ^+MA3eCP@IqGp!T>qzxRIrJ^X{M{kJf zCZP9*NdDA}$YX5zqCD2(zZVn6nMh#97wyB$8d^XpyK0g*+9EF7{SrM zhrR_=bvd;rFmb~TjUol>Z_%q$4@QM64|hhaH8k7q&1q4Kf$A>j<35P<)EAIwQV=-;1^7 z6W&fwP0-QbVTtbj@%X8Gd@Wo%A){AMvp@-4M>9OUhx0ILR>F8ZoabAw8K$$288m16 z*B;Q(HO^gTjS8o)!@io_k8Kq-fvn*`$A?`e%JYY>UybX^TYj`892uA?dJp@5?L1*%gPD;SY6_CqGK{D% z>Lsfu;D_T8TnUjnPcz3&!OVPN|K}e6d~_7s8`%*mmgaM^%(ZPJIN3ayUvc4x(`)-jy6I zsA`&6hNYI(5Of>^ZrXJop*sKZN~wsnf%$-OjByP#*tBK$=1tFE6u97iX&|1*0y<-G z*Ik^REAT%ZIp4>The9RIXEr*2t0jtYeX#fWWkMu0uf&^~A=;s;HF~2ICX}dqW*9A2 zOo5Z;*F!Lgx*~8c2LM*^MJF(KqoG*bI#i;Q^}eo1j`u}IxZ&bQ?+nv7Me^O89 z`&bo8RDjvqR@Vtp=8JhBOdl)uu(_fa9x$PX8kR}Z|7EiXS_zNn@(VY>!=hn}XFca( zCHnoVm?JI*YoXhd_G{9pXv*p;*~aA}iCKLMh}ZkH zO|@2rtc0wd`IYmA_k@?(I;j2xhYiR9<_Y8-_pGyocxc5t#>ZtaANZw0Li{s1jV0|B zW&w@o=h(Au=*Vqoa~1ID6fC*f%1<$X82pZP!9NiPiNuv0|9lK9TBaR)Q_N)5=5F#p zMO4aFZxKGhVRq08_Cky}r{~_nV4&SLv*7u~VvF3{_*jcQEp7po2VfyBR&=ezl>2Z% z3bnn~o6cT>Pu+*K@C8^?UIGZwZ!31R2&z%Gy1||VS5!iSZoO%bt<06{yu;w{^Swf( z^fXYY8V%YszQniOZ&L4M{<^_gFH>&7R^k^%70C_(bD7}0gl#ewN#JjiDs zTmxLtZ;W4S8zSp1*tV#w{IQP)H$TGUU)`@GUgJfT$y=j3s&2025MTIvB8HI;2FZ!c z)SEk4MzJ8K10W3@Ky4S@I7B_i$VvS*#tG8+0^~-s8uP>V^7_Wu*tAa{Dz!r566BGh z`o)MIR5iTfSA~Gc5QW`*)fKn&2bf~PeVnl)FC`IZ`?f!<=Q^NJkeppq|8P`}3;w=p z?ycV7r078=n=h?U_`f~3Hz~8dx)NM(T7Sm6hzAM$XWD*j&c=b5W)Mnc_ArsD-L#v5 z+OIuhNn0|w;I`?hohP5n0B6iZT&?@&H{KpmP;Z)q%~%O&A@bbUy<&Jl?D;^O8B4j= zrJH?Q*|4oAMH6>Ro&(Y!-`7YJ%Aj4GNBRQ>HGx+OI4F3J2}Q$DQN%>nrqiukCEcBq z&r1^Qg$8PAUBzV%YBcR!TOuLqfYM|4)#xT^VHNPVr1_!>oI*gf!1zTgSqTpve}(qS zahqY}UU%rZD3Jc$gW$@^&zGj(Oj>p&S$?k^qq)ad_HR_YQ@_-3H#otR8(#NB-4`i{ zX1(VR_dNXcdA=iJllJ@^8un7P-WVUdE*jdd*olFvcZO^?k^H48w|uNIR%c)Yx==D_ zt6ngIB0LsE$6WfkK4N&BG)N z&#Jhwvf_TR1cw%uve`0CaM@X})57>bvuxrL6K1VQY4*6{?fX(?9Y#6ODOVC*yIRa< z(?MUx1D`i})>O%4WLFuAHj5+qeMaeWmD`jn{|DXPF^#NJ@G0I66<5z!NUk81atlnbFktED7Wg?^wDD$vuj~oD2Vxiy*=yUA-W2(fGG?{VMVU!8s;Zv=vQyy0M z7v~i@T=#a+_w6s&D_aG7%=r*EpZfY=EMH?JbXT@@^xo2)b~o*@S1i&;l>%?f{my_lLRrL!P-sJK*quRNh2^ zys8&!-3Q0|4WE^vCN|HqqH6c2Lnc)srfvHfDCYbB-n0*Om(aOEb+`}*MxWN@e{e_?Ethe@W8 zz~bRTftfahxv)J2RWQ?5C=1f*2%b8zMC9EA`N}P5Tg~ zsLSJ{&*lyLQWM>2E9zIsn2RqG?NK8H78ed(h|0>7>OKUk(I_W-iC!AH?lpv>vVIEN zhl@F+Ev`TRd}?ojvq|r{gU7NKT?}BSs#g{dVLKKw)MMHe3iK zGmkqmmR_s5n031(8=4%v|HI8#*(F4gj_29gy6HGmL3#=Y*G7MEGi-HL!qX*hS^b}W zLVPx5XJ!n0>_X3{`ry$l6|bdyYOEssA?8!>y|$Q9Za$Q1LkoVr!aQLU@`#&!V;1jk zOEbB0J6Sz2+u&E!6MDr(7Ez)X`x$c=3qgLSyQ)REvbEnCk&@M;lj0K~9Y|C^^kzdZ zlabd`nh^RP;RK13Bt68z61)3P&0YyO$%WQ}Si7p`-0%n=hS3pTTSm1x=Ypcsn=b5g z%-7(@Uo41B9Zr##C~#J721bnd^GaCfP5jq!CeTvqIQi^pB`b8t&-fbQ1}o05D_$^M zZ){tK1YR-6QKMliUy$@K^5E_mjuxcUpMF*ID3}{N|E51#MX4`H$rB=CjP2uJl>a1^ z(-PUUA~ZCjy?Y7!sBIxB_^=@#*Qn+1YUwLhU8=C5d09Si84=nz?Ic=1lTkiRPmavd1N!U=Y>J4d@?)dvRfZ?I!0_6S_jLq{4<8NS6!0nrhUtetP#G$W z6=MQZAR8A{B69ARSU`@tH-nD+@vk}k+U>nBA-OH(I@)#jl3YSACA87j=XLFc?C{J} z->M42YUCx$xI_Q3g#qS`Y`E4Q3J!ZHO3ROJZt}r%IIPh4zRi#ghs>n zu#c_U7a1uqNX_%~T?9a@=drY=#rNb+nS^qgNVRJwXsor07k$b6|3PIebD;Q@0Q%Iy zuI}0rKt%fYbrcMz{y%CHu+(QW(NIO6`bo_~3f)-SsLYClL-{mtH)-V+Yc{iMdz-x& zn3yzHK5_Qj^-Np-OB9jq{`&M4m5DM*+N^D*2}=6qM<=IOdMEA&FbJ7$z|2#Tbd}MD zSnU{paUiG0cfkpgfl09N4ff2Tz+&PIrJEvC8H6~;Wo?9XMd4P(1$K2koIyjDjq|8< zMOM^&n-QDhVpA)%aue^the8n*GOnKI33 zQ$TQPMJ@t++@R*iO2Ue!+4p-_`+k@82Yd%~nsZ5KA4Wp)A$EJ&&fr_nB~Ii)8Pz+o zGt4cg@eDijWt^0xb^Q6-(b@m&ULmI&eo4>ImI=E}`SYi+zJlGGm}c8!zJ%?Sf!e|CnkCA%&K2H;! zQ!e;H8FwDkCeKGwzs2h?HNz&ODPN5WESPR(0-=Rw?epNM4^7)a7h%Z`HlD*?b=BHc ztn`&t}sCw^b%u0hDhOq13n!(ab27#yCXyQwEqN9{%9Ca_Bj_zE)ZMaUARvapl?9(GO# zS+95#47g0kp?nA!cdyVWUx`h~K59V1MXm`PIn>y^Gpq%_T;)MDZWyv*_6@XOyzZfw z-R#v-7-$h{WSw~c5{%NMH_nPw*{O(?QvU~tZ^tm3a3Oc zVYRSC5fHz$IZOuL1aguRs_TBeAwd=#&C(bBGetOly^i@c_7(i zOw?F?SaUsOieIb}%~t)&Ib&m5GT1)zu_nwj%>Buc1&8Zx3bS#6foS}`)L8D#@MN^~XWP+Z@RdMr4K${J?@79eJvdSF8Ci#fleEJ5? z9vbL`pjxXw-xO#aM!Om8#6J9mr-z*hb#I{@eNH|5Ml+bsCjs!R1<#AhMR?fY&CYOi z%xyRZO}Z?Ot;|a0@>$>UGxhT0bNhyN!j$itEF;4H{rdVrw$nwJiPJxfq+=mCrm8OZYF4kuI)+V}b zTO;z3l=etRuWCVPCp+8&_(*@|q}a;7u{R+Wxug-P<1|dA`U8ezF-r_J^Til&8D^1h z%c^x`!?X)|O#WVVODMy?ZnK&@fAKGPJ!e#}_BaM=Fn)~5nC7%`Z)0*m z&A?$U^bX#w#uteubgkYY6Z&&yi2kV=!2+)h{< z&;?vKWvHPbvtvPjn6bx~aGdsm3x^3U0&)XxkfwJ11L)Ma>RsS{lsx7IV+6RIRId7z z+AYUPQpcB5uer7%ax~lq(S2QzYs(O(?23R>twgPtZnA>G#<#Xvo+=z$@kZuc72|W6 zGVx}`HGU6sn;0q8M0dD=6Wm1$>4uQdHFPCZM=LdsjLJh!$usCMh-!|w>?`HkHs@b# z`8}62sHk86W@}@rNdaoG$0y&!ozSDTN-kr<7+Tmej!-zR>HUk(OUE!y&B2U7oUd6b z5n$_+@e^9X=AkcI#OAUJo3b%)0Q^l?b_VG_Iu)bpT04Wz!r7aU5yC!i02kg)Tzp&p z+)@@}9pV%(OwI)GczPGsOK#Ld@;my|rtpuQpZTU6g?BScDs_1%cG>BWMU+K7ehgaQ ze9+P^I;ZtAp30)M^*n$>jil^*1#?JT_5UG&%mGXc@_UMC%xBuvWn8BYxGq+E5eXXD zWjzUs+^H5H?@YyfqkUZ#qaqDb+ez=*X&B9x6A{B;I%2Rf!NZB1MoS9}R)^?`~vk^|L>Fzz!X78pGfl}1LSEoIoZFgVqpF(Y5F$_TSzyq_DJ(+XZ7pmlq>|k|0A~iD!<(k!2)#Efi_Mb>pmgyruA!@n%Y@C zc0tzPmr@Bze3kjIM5JPD!*p32K<9h~k**mW@rSV9XdO|LVC%PY7kflr z7oN?AFwYeOq%T}J4@d^620t@Gv$4(1RpCUQ4wQ6l>t7)Po`7hKtm=s?i?keI^?7se8 z{e&5HqowE1_96ogeuS->Vy(m^{0bF{DRJWJL}xz5?YJU~ocPvSgnxKA5;8BQ)}ZmR z4iT;CiOchuA4hKcz-U^#YMgWIIU=T^Mr!X;_j&L=+bT}u0n5lXeRN{RR1nIL(DZq3 zzl=6WU6kaGr`e1ch?RWFz?wu?5&fi)q0|EKI;;fqgN0*tZQ%^WRU=sAh^VMIZ_~6w z#Dtz45v=SvMbqhD$3nCMxofNE_dAhLXm2;VDB6@I2{hy%=@=#@7p@yJ1s{Ei^Q}$h zB8cmbO*7vYAi-cp-y^XuuGhJf7K-rN^-?wFmf^9N^wgVOvx~oQ?rwG`7mPZ;=MxcW`oS9gvh%~2Xi$VjffU|d8{B_sDI1y%r4$`(+P zD;P1F*825wd^Oe)*igp%v0__~J;EILg{7e@_cXiYALk!fXl4~^St24zUZ%3492}um zUYB+2T{lMpu$$2Lh%~9WA*tlZHOY5Y@au!tb?EnQCx>`oJdwpw>y@;mD4f95IL;fm6eF)*)Zt1PYNV%^6TVP zl0fhZ6dqep&{d10fc-kk*^l!)LTVK0msCaq@vNc*3lb>?eRA)_$FQtHwyYdo*$PjBaW2$iYZlYm8OObX4y>L&64z7 zSqni#)PDj)B1u?s9*`i#0SANR?z*V#tYBYOVG z)ba?e_NUc>640nFFd@|WBR2y}nb5t5%tV?zwDb>Xlyh*|7Ub!lr# z@ay-LAZ~Yw@uG68jU8BJU_4ZuwTt!X(LM2}q$i2I@~t~QlKgv%3|wtrv#ZQS)#Wdc zEx|L~8D7(ndoO+yx&=vYMlq%GuzR?~PIhX+*!O#I=B2GGLnBe4&VbpI8lq5!gw~UCMA&FF&Oh2r)a=!Y-@{sCNx8FY*vXlT71u^{W-v8y zy?vJOB(Fn7W=ul4lVmvZIjL$A9wNV4{Q67TG;w5Refnduj5Zd8R*I>0OQQ4j)4lo# zE{<2aHJ)vp&%Wz8>AxZ~Yfp97C3(&;4_R8mh7J4`>2*@WFopAdknRRfu+QL;SqMtX zrN+7smuEFOh`TQN^qaZRA3)LCb2MD&rAqbbSeLzjzVth-hUYLH&+&0S^c+-0j-{Q~ zGKr(fN2G-N=F4tuyNTxYRPTOR9(~J~!Eu<$xVfxXZO910eax)l2l9^Rcq|+nj{!wn zttSjq=lzj3NIYomSRtEE@J20kn>~xO;urJS583mVxc$pO%r;M^O&&SyfuBwt6pzPk z({Q*TO$a5L^!JrmU&xKaUACj$FKKP$V*?mGl*)PdV-ulPr#J|X|D zJ9|h)HBOU+bm*yT{?fRi2Ir#IR81?&E=4Okr=kr#@u_KX0RNzU&p)c_Tg#SQqfra* z$`ptZA*-_El!aWw-JQm+3(r#1JuEs82&O8*z~UfSc=^?+isMS<`0S$v*LTl-Lb_o0 z<~zQ$w=yq`Q}1($^NQxEZU%PHc~Z``=($h7Ls`yz2Y$!64w(=IlCxtk^C^|35s3jz zO&>VU*OsmFuflt}Z3g@7|BwEN?D``nREDsBxJtPu6QHsOqd{Ga&W@JQN7|wbb=kp9 z-QYhc3DPaqYkgbH0gC(=fhF2n;1g8itj9HQ&)h9cTinwUdiI0LP8#3K{a%ENz3lPO zv`Xn*=(8-dEmbD0brH>EVTLJuP!<{M=;a<)T6-FHXT%lBy(+Bu>i=ENHQ3{I|0E?>wIeIl3x5R($w5?ind zloJl45Fafn;SuC&F=+7t5D0RTM1$;?0Hfu%iMEr$bnKGcikfbVfUi{n++Hp_=ZpMK5I;YV?r^wa!sQh~@ioF{Ogpz7B%y(gwkM(QB$p zN!u4R32I9Zw29&^)Db9%M0UmQQVSgyZk~UN(NA@CrkU*w0iz<35-KxClfb<` zY`E{!r#6$ew2@;2{Hzq3WTY`ek|ko$tp)MO_8vyR|0VR1 zc8Dl8_yfuvS^UFv#3xJsj)@N4$$it12-jeZ(W+c<#X%Tvu8l>NV>L|IDD~yqanvw3 zl@A4i+!HbjDN$+dJQSXH6p}VA0YJbH_ogYmsIbd!y`?CN*gmR7fK7A~GoG!L?1rF? z49Bp%-awl6PZSesR5Rk>TftF;}n1lk*YWkMdxVI$tf?4wpw7*rvZ-wf2dVYn%*f()Im_@>EF z;v~HhtkxI(PM_;Z*z|xIqXYCxvTP2-W&Tn z&Xlt00ODoCz|!$kYn6Sm=dO{mqA#&=C*{>~!7Yl64g%vJJ>$CZrYDn$?!hf~sNhp( za1N=mD=PCK5Muy(|@LhiY_W=Bx*%-2&;PK;zl zt7*~?lYyNVdit}k-S4cqAKP1m|0o4|6e-CnWup1mvi^qkfYXjP+zW_Hm`?WY?et_zBZJWQc z>sUs9Vu)lf^~^{6jcu&`UK1)V_j3G|fI5Z_dcW#VJJvrV@;_|~QehEcjZPD|w6%6* ziAGp-n*Kdg%Ne3{pb~1;lKC=ER4xY7;F=fmCndp?p3Wt$weu+`4Ci>npD-;GrW$z*Q2I8vGkbF*bx68_N;tr5WIRb zey<&&kC2%ECE+LTxDaRh7gAz=J!&BMryyTUQ9pvpYIu2v-P53>+n*#yOEC-y+v7~+ zWyQkt{>U28S0Iy-vvbv>CNE0l>OGA5!#u5`@y-@?z$deK>EvC1&qj#^o2wj|vz%df zB3j6;_%W1Mwfad9=Q+S-*!>&CI6*KSwel3uN_gQh&d%LXO@D$}A^JX9PsT02Ti3oK z8D10anXg@C)4lCChXCO*)hPNe89c^RbE$k$=!IvGKEk2PF{Pt&clcnUsPyJx7p^7| zqWY8XEeX^MRdrixE0~%b7fqYU(BOJvh@ar~cLB350^q>aW9cJt*c>t+^2$(vqedK; zle3e}C7vRpCev5v`y#~gp$#RA>u-@-`HH*J+VC9OIJ?6M(Qhr>hJt^FJc6YmuxS*Z zv-pPj{}`nVdZthJ*OikJ_IAkykf>g6_h zj(`|P7n5Ay7%YNYm5+-qTyxPklAf&RV5To`Vn>L6uU)2ue{a$(CpA}N(V2&O{ zay=)4B(=?~?!Tmbp<`b(|57G?s#!E`#M1LYtO3NXotCthL^o&e8vnOh@P=&`OHt;) zR#I#HVL?ge$9|eB`-nB0h*r8)&*@%LN_CZ`$+Toj_Y`|ta}wTYUNcT+mU7baMLCiX!zUY}PO#>r< zwVGF6Trp4FL>m1Jct6_snm8ARwn8EWWEA^XYS{W{E?^c{k$JNPEv)s*1bqo;|B)Fz zT`YfA8iY*TLn3UKG_A-7{J_SrYMh9&_a~X<#D^2~_=UmHu$bQ7)%}ca9#%JCT)lLc z27O`x(r6Lq`H_}6)sdFSC|vi{`yc4-pC-_?r*{evE3KaWZ`0ZgE5XXo1Z8G;JcPW=U4m{+_=5 z;e)L>zucdEooZPxa33cq_l1(EUnwwK0< z+GI8~7Q8PjiIbK8=M*j6l!aL$$CS@2d0_eZ)VM`>TKD+;_?U_!e*HsDH=t!$ty`BB zwfR|>RhAT_2pNW<#Hrilvy{{%)JK#~t>FfP$?V3(k0Qb^pU6nGWKnZD_`F{B&90=R zFRa`797AUGVJ;o@7}k%BcRko~-weh{4NQa!8Dba4-(X%Foq=l9o%}cpwh+r*emOg& zVaRIk&(-PR!w*1wncLyCYHRqH#vko$fphYG^D&+1q)BZmduZd;7kb$mw8u=#o6Mj#LEYcanRv-&OTYpo&>CsY1G)MR|N zM}EKK8~$a!X()t@;@$iDn6jzQgbEQV8Q(yiYw!F&uK}X)y`+o>c;UO_Er*VxSuiWl#w1`roCymSDLLyu+-0=U{T6?i{1rPAl;AY~ zn-;7mPmb6OKW>1;89iE7B6Pil&HH05Qt*{oe9pc{u7BP{b|S~bOneeXGaHK2-G=2f zRdW6XA);;47OY`S-sNx^(%{S#^8;HrZ(~*+bWL zls&Mnw!~#OPcuo~z4><)*^JeiODX#k(Ymj4FIUQ&mIVn+$A7~8?E8d}agC{k%lVdN zio7%1WK7xmP7>rxN2q-fM+^I*4;R&K5T#lzw??!#`3pr z$96281f#XvqaYT>r_#rR%oTqapbwVOP@{-Q-!srlAZyrena(IhzO-zF*3JW1hIAE4 zAe^lm7GIuScF;c%@2ra;Dc|z*58Ru93`cBySz|{Bw8?&Xc2&IF^Vt?AVofZr;GN~Q9G|NJulO(s zZ2_5kH-a`?sY^hH=qVxfd+pp;41Q6j?DAqP$xo^ZN6|fgJ4t%GvL0e_)G|3GH=qLd zrgC;D^oA8UGfZOvY`&P<_|G0$mQ}!WxifC()S2dgl|bC_VVR62e=JDHJo`aMi_t`bz)$DdOu;Ux zGMgrfgkFZ&&Cz(d(>NYb1N&O}O8}efuGBoxNGRj?ZhEhuGAl9=TOg&EIi#`<@9w-B zP$kx}4rQf~Pzq+FubIO~%;g-Dy0qenSXz^CO%t_W zqoSev=8l4^B{z0+$zDr_4cxth_NYGsN&n*a$(n5b7EgZGZDN~s-G;QA1Qj+BC~nQ| z#BDH5&3Yb7(W!(;j(aDo;8N>vF?(rBo-M^QGEe#xV4C-h#gc-`v16k z2lu?9ZhJdUo5r?n8%<-|w%ypaZR?3`Cr_L-w$<3yFXy|i^S(XbpRo5{d#=*tT#i6u|^3h-`0u5*Hr(wOI2^J;$^7{UgdA zIJIHBD6I>-aVmkV1CgaV8$28&!6va#+P1m)VR$UABvP@qsHkc)oWc3?H!TVl)W*Y&u`aHrf7O@Y?uO`erWnQ!V@LQSAsQ~`jMVm+^SYHB zJx?6k6#YlWy`bg5u}Eo{tpr7yDz>DJJ0pP=S__)qwG=Sp{DJ+ z#Lys3k#bW(B|2PlUnN`o@w*d_q;|$Ns%T$tO=>X8;7t%#bb9wxk7MCmv zgh=irXviv`C8Aqs-FsI2A%Pl)ilW+=HtO299DTjBe0#1r5I>r6-GZwXu4{_bi}h^KU-?j#Eu-;haQwfz@a( z%^_RjI%@Rt?ocOcLDAV-MPe_L`saVPVxrrxFR=6Owy{(jBk*5L?i3c6-~xrkAjZ>; z!jK=l)u@Q2WE@S?JsZQe2LBYbdwz0Y#c!`FEENBned}ocOb#ALciU}undY9A_#;#P zgHC$~s*yRura*P3a6DV1rpt5@4!#(p@mHP9rpzkJ82b7Z*>!4s;jyf4S`53#01p=1 zd?e2|yms0kC5hXQs0z-_``e&iwb%=Db#3Ayp>(>e^jBxyB3=u{>-z>Vzct_MP0R z>;&lTI$qJ#vp#24(t9lT>O@i1&qSaVjKh&>N$ z+ZHzfv$IN48@X1OeM!v;epPo}D0PG{J7xiX$`0&58j{Ea-E~Nz*zmfs#og4@<%Er| z7X>0e`IorRPw?OfLMkptYsN$0PBr*ju=1eCn@qM~Y z)byC*5hMyRpJLMlu5nUQm}5@kI_jCYS}#fRvLhCCez5}*^8HvSc^2GNjBqxwe%GS?P=2q6>70) znCK>5V>GmSqezT2m=?xSN1Ff)COuJmaGY8<*d9fiiwDp9*dS5Yh1!c7g!A6^$&(ho zbHgG;V>97`@OFREc%uobotj6}I+}VO?kEhZ0sbV1<^P?9-ME%FPWe{qi&%1X(sSnN z_Cr+h69cxet}x>x%Ixe}$L=7=SKcb%+Ily}*Z5XTALeKK#E(|v23F9{6g0Wl2bEiw zVfS0%Zc=#p&%6W-cF%DeSqbUo^`YyAY>aqV%_HG$ad!3-&J8s8q=n_m#nGJ$x* zVAVZF2Xe6t-bR8u*pZ?PXwW-S(aTYRozpCx00SHSk}C*jQZ=HO$RSG79* zP(v3PO5p6dH)+xRFlbu=lkNOo`@#R^1;hl;X0h0E@>*IVZ>>*C{vv=4=Wwj0Pg_@G z`~ekM$M;QbR7eGmN`RxwYq4Yf`Aff9LstT-anVA=D5>6E^cr74GZ9^Yv7}Rg_Qbi}S9$31%ftIqg>ha2iQHfsS_&bWEV}B;sd(TBT<~T!e?3R1LTW z{@+RcP4DVsf?%xAZr~{OB%o^)O7)av8okV+uIN6eK03$ z5T?+~qx&Tt@$^{LD)f1-CXW_Xh|0cqKSBnpaLos!0%(%(1#9V=T&sTW9I!P;c?bTK zS2_o1GQ}?-?2og~Mmze_njk|uB%;EhKb*bX{=)`ET0|Bp;M^9YPeQD9?BMUKT z)J=h=r*$`?p4`)4o|F3sQ&{0_4^~=4)x;q4KRa~P33O?00VL7f{t+l5!Aw&MS8?K0Sl(~32=6=8l-v?$ef9OR$1o-^(0e>Oy-c z_)7QPUwpSqCLPC=DHX66%^nCJewi%`4VJO=|M6Q;-&4jUNs-Hs-1~dygD!~e+Rv|O z?&BjKikUQN+yU`T5kb40YUASOS2|Qm9yK_5&{=s6T z82vSC{nwqtuh=tQZ*|R4h;;?~QAyMuZ)j{ZkP>A5pte_S49rDk9fVjb0W*%c`i{3Y zTRJ1_{M^sCG^?1abl{lmoQBuE%9+aLCH>smoE85YR^=9HG(J=Ef8;~lGuMbU1dsan zm5?+Xr#fnCtI!|@gB-awiCkyb`aMjrX@Aa66?9J^ao#ux;a zShq3{{K!5(Jl}fB;uedvue)~cVru6ei#+y@~T)M+Dhx z-J{YFE8i$5hs+}#QD>m>kL6NUT#3$ko?gR{mYl04Y7Re1%6;^0DnCv2cGWcZt2a?< z%V6h+94sia)dXoE-4i*?xBo2Vk+&~VF<+B=Lv(iJtYM%l@!dm_5Y6}dn;@O#k=)@| z-jW5_(c!}ba7udj>Nm@fu-!f_c#CsooHbLMX^!-9ByFx%ECZfygaRPqgP% zP_Bp$VPaE1%uy*pWin}j(eR~!vMj?By&TSoTGBIcCYO{8uG#EQDkAzVi!}s+YV--% z$~V7zdxcPEl@{{q`-~XdD$$H9`NF|;JW8r?+4f?-fiOI%aW^Bn?2j!Zt&Y3i|K0lVm<8a{ zhu9?U)6VO$6)uavG`mscGfdJkQmU(ODq27lOe*ljw@yyxv{PB_(g_M>iA}^A_ODmU zg*6$k(a4RLH#7bfI|FsAqCh$NmA7m;v!&AR5BnWP4FQbwNsJE(A7IyJQu<3xv^bK| z4N0_r-Rs|InTXS`sTtEGf3#+Ha+tgwqeB(lRNQDRADCvVQ*@0N=$ZbD<+=DTKnWp& zw+1F{r7&hn!-QKiU{Cfh+CDw}OI% z^`uzQc2{58WwGPz{9UKaU>36t^I4!JCNy8#m#r9R<7RHAxI2(LDd7VSe>5o3Eld0gCi`PYNU=5kZG7T*S3qC%WVDYy_020^2^QK!L_(&oaxuap@lH}ch1S*o|3QS$V=VdzS|;ikmto z(gr^s0YGqz2YtXXU}nOON!0b^X|yW>e+yETUE{!DbL7s@9^_)C%g9%pg@T z9zf2fVbeF7lb*qtE6X54Lz(ON@hHg|*3O`PVQ8zSj?Sml_cnQ?d@Cp&Z$ z&hzjG79ze_G+tG>EHZT(q#B$tXT8}^fr#0Ij=g?NBK(r1GN2~LlT9@}V-qA=)Yqh#93I+A2 zk3Pu>6lf(O3`GXMBgS)`O6aFsOedw6e*Ct-s`q2FF|~%$O=)_|6qSmGh<`#$;flkY ztyXkOQ!3T%h*Uqqxn7#IjdFbG%ckPhj7dB?@_*>E_VG8X73}tjMe&A|A(r+%9_m*$ z-_e$9lO;F5lI#3OZ4rGL8LwDc`nC6!^sJfj`1feg^)MJWkw0STA5@$<09MO-M;)+i zs;wHi?u4Q)=l<}+?BuR5^$a~Pk1D9NMoSiRIN$=260Q6{I|7&M*|@Zvy3=PATd}jU zwY{P!ai7MW!(-Lpw2EXBKJ4#;f{NY^MLmDV=_M4X*gy*188HoT(V!9N9Hs>e4x*=X zw_7%3@>e}l5bSR;Xy~>du7L!~%c)CQ`(CKqj+zjX(KMOObd{pgSp@fZbtmoD6xSK( zw;Whv`Ke>z%+`kDsu$Ekwwgu7u`$M@v3|2WvAY)?5V@s5?DehUvq}M4V8;?E^gFA0 zYP~yg29}F$*90$Vsgxhf=K7##Z-JA0jmx_Jw}12%0@MPPcO90k2>m~3Q!x|rH0ioO zBdAY9nuBVsJ;MPcg*_^V8Qn`2rkDhnUEbYa39!MVhWRk0>!lWVw<`z{iKO8IFh<8A zYg|nOy_Q5Ln&VuA%1==i1e|a^&6jVH$CjxocXFf54BiVwn%M%=2^wmr_t z{rXkb$+Q8>OMVD{YrbC#I~Iea&{FhFV-~5F2dtWk5+54Q<2ofov}YwRqw~<99=fPtJFX z{P|=>ZM%0N(fWQz%#QPrk`|f>E_qYA4KDS?WNxjM7btW2X|1>qJ#*(nlJiD+Eqqxd zK^aK?Vv31w=QLK6!iJR{pSr3S0CE%_2Sfxnw4n98g@f6Y=n0PB8!@ZSs#v(Lo9yym z`r*s>7w+e@aLKJzx}3633wkVAj-rdcJgLoPdZZ!##&6et&Yv}hI73%~~X>+$W|=EdmyEpCTF`n%#n_b5qy&+X6D6SUgs5su6; z%F#}WOBLx4)#jb;$DVn$-B&$!b%u~>v6>!fK>~E-h*u!7SfRFGv7yY^gZdgXKEPu2 zJWSLM0W+9E-8j^f#lOZO`wm^R-9GJnsB8s7Y!Gf=!|8DtK&bVHR)W+A^3`%ESv}|p zz0lO*_i^JcX*c#FqY_XgQm@-?k*GRz9Z_gy({@?1Gv#v2dj~W=ff9_>o0clDrHj4x zm66kVV6br6b`%fS>bx8x`BHz3p1tIICiyiTDliQ)3awe-0z%3=1sAhjlx)m(Dd!*b zW?IP9Nk>{UKN7+Iw~X7dMNbcvI9z>+svSea)5jeVll)X3Fk~ zD{^m|)E_OED3@yLK$gVwmv$Nbr)K=cFNI`TmAT&`-TjXwp)>Ag0L<=yubRri4F0`z#8kAeuk!w=G^!_e&t7|xl?c0P`T-BeP0J!-$Y2j%U1 z)rBR7ANXB&I$BE>^kHU4&-Va6hYdP@X7jR;w09YG@=E-wjdry|(cGnVBWwWQv(%cT zV2+g7S!Tbs2r9fls`v2#6;L%hl17%RuSR>Ty$I`~TvS>PRL%QiJb1VDewi|6Vxq+a zKihy#HqN3~Z!xs`vzdm5<|gQ2wwSVh)J8QQb+LAFn4hL!G;0M_F zvBXSkpC?)`>HyCysx(XP;GpDA5fh*J>D&qHR{fJM`yLWH_UjLtRm!(I%|%>)`%Yij zarxhjs(4;_XV=~f%3ze1l?e-1fE><3p9at%l_$jOe%U%Ynk4Yg3+sQQOD#sMWg`vn ze1M6D1)m)glU-XmY+j;753ihD>a{>3Bihhby&=wsnL4h3hw!msfH>`EtW#aJ=tpP= z2Y{}>L~e?&yExuDzduQNlFIZ-em0M$cnkibP;r7+;E?Kpwj?~ogQ=tOE+O~R7O-f? z^<@|~ucb;tejf4geL$b-M}Jb%=~ctZg$6cC>+G_5$4k{+^D)esG%Y#a^1=P4lSiO1 zyQVtInj1y;J}#wOG5d4!i^5g9&4p$?)8CJ+!v^o4s@%0W_=5LE#+Tg4=YNw4WL9uC z&-d|i(f|DZ@80y8+x01LtF4jpQ^DAf4ie| zn(R%lt}9DbWc7t4Q42FW=XFBY5I%3^JBkz1Rp#t1mB_R--Ey{aIrh6^%+xFata+mA ztd@@-6O}1f&RiV$W%V(xS@dI;>4YWcS}59i$xR2l;ARu2P`hDuL=mug$KYBPcs^ym z7_?5O)@74)tYQ}m&)haX7P#Zq`^qd>Yp+3R`VR6g+QnpiF6;KVI4TIZKI-tm++>gI zn`h0=bkT-p59xJ6(}O!WbEQ!-E9%CW4WpSCWfc@fE{>M|X?Dd>c5u?=QZqq)sH8XhYOwhs)eT_S+Y7NCM-!g8G;=yP9vk@|l zRH`CKyIQ(`lftCTl9jnN_Da;y*kQ60=^&j`^lb_Iy}c|heD|aefXW&{5zzZQAla@4 zJYF&2tr64I2fRRGi)|KP7!}?iJPLFBrGw>8S87jvC3EUBzt}4za(eu%TD;X>O{h%= zL_&H3m`o4RJ=>MaWHA;;C=l4w9?9+_Le-(nh){XtfsW08V))LX=a$`87T*jX&XLfM zjkaIr0Gw;`L3uvDXIStetxjhGe9)BT;FW3f1$K~EhYus6++~F5z8@d$lr)jU^@%iF zF&q={dFCNVdunFK4u7?%2Hul2xom}QnSci-bT!Bbpyg;394KAl(`uW+4JcIk*2JZfLPA?b+xmfSIh!DqH}66 z!h)(vXGM`E1mcooHsuhCP}9*x$E);MNQe#jA2EWW|MVe1jNvKGxx8ZBqWdpBBo&V} zrV?@3c?R5)#F#K5YfIEWN0Vc4z%S%jdwiMZcMfotevgeaxw2XGU00Jv!~{`Tw#Seb z!nzodVcN5K=$+k^&r!-0Yzv^|^}AKy7@7uD$2TfUC15)nSLfnW_jmAP1*VzbMrouO zR(T|cyl_V9Ybr?%NHc-F$kB%`NNcaZ^apmxkS)J`;JZYlQVtGfH_OHES2T7_E*tx(>O1AF+Jdp{Fj3%r z!`WHq3YvUe62gpdH(gfwtR<4}H!+8Y+vWR*3xNUH#i1D6@D>vVEDRyb&>yj=B276M zE|;$#(e?Wac+07^T z)Yec%HBzzJ6d{ z`ZWL_1WKqOZ0>ULOu;o2gGNT_(Qov$$OP__LJ5IVP;>xYdTpuBT1I{o##!24>r2#11l@>qmMkh(;ph8Q8F zS5+;C`|tAXe`*W6F+X}onl30DxHUVP0Uc!6d?BCiQAOwAUUX{E@x-73FmGg;kWrDP zB8NkvoRw`xeL2IUfM+VDxVHJ*YsRf6`$KCvaM%~17~70rS0a}g?o7N?a*q|XhKG?E zbNJ1+L(_qcknuZTHd7dMiaR5`{EG;HX8tJkuxTY=-J22#!*HE+3H)dgnf#g~lsbk4 z?Ft;@SIU`24XZoF{mVL3gQwO+|CNTOE82XVXw@up4>2%*%61O{?B|41$`a(T>o*lu z*>(Ik-SU+!Z|`2>FOs04(RNpSyWmAKZ_+U3+wXu|6Ip0*{Ky2pb5szgS(#nUGYd%{ zLy^4;P^!hOSr;u8gt^cFu>y}D?7>Yky0MeVPm8#a>n5ZX{P+$NIZ6$N6)fbHymOiRv02|KDBqS!l<%(5q)2UX)3?$>RMY@j`RJutyG?wMI&jj_NX8JV^xx5PQ6j<7_do~g z_U_M(b}iTwq2+My0#xeukht@)8?p5N; zd6(yDR)qFB>#1RuZZS6xC{VMx@z|-{{JU^UcN<``rq)Q(jIpT2=H+jpHw&*Xh)I{1 z|F_^_bJUT4d~CM!wArtz>+H8Bv=@VJ-U9*QIr*}2lRkb|Q|iiFPg~0d`Zbdh5F$g^ zNRddXiMWswmM|iKiQiPD+$ZjspM8_(F#oe#F4T@eT~M{*`N(9dLH6E^t3!ogr6!Ek zpa!yYs>jL+&UGqmRvVPCQUmlIQf5nC-i>GRIEgo(xbx&5ANr=2DHcrkylYSFA4Os? z5;g5h65g33b>{Qns-HybYEusN;yrs4Et#Xdr*yH1>3_m59dOi`+o6aOK|Ll)3tNgA zTTES8OJ8Yhv7A8aL<%5tGW0(E{ar?Kd;-?fuC#mx#SA*V4-(9S~C+dqF}dQVdL&IaHfh(V7e4njnJ`Wl!(Ep`{!wC z2;m~Cie^cMoJdS&u}5xN6E3;RujS6+bT0!EgJeoknthaSUx3S@HQXWSbe1Ft0#l)2 z{>#hhx~9l~%jnzJ7Gwj0EjQoPHQ7XqBuDJ&!&@|Uowoh=XE}n;OLG=nJbXm$Ynp;I zQ53ULrSSc2ZwwYqxV|VOc^#*F<*(f^z2x5sT}cad)W3ZjXvAT~QldSpmqB94bnmmr za;|6?gPU~HqqG7+0aW32n8+H3uFATy# zYef|l6cR&FNJH~GAI#tC!3im-%3(v*9IFwq`oNEuYHLyCvrm}jAA0QOk%?E`ok!`6 zQ4giTZFU6cgD{GY2Ha<;eWs793@gbRe(c4S_KT7{(vCf<#6+uew{df@qSjksCeM3d z`|yZT)0QGv@Xyi)&6_Lyn-vf)`gehuc5HqX)gIoFY#Z2TU<@n?}#6b2*qoHjY>H1xO^N;6JQ zyRa*Z;>%rE6|Z6S+ou~t!vU8tH`)rZ-r;dz=|G0piq%zn)+4TxbD+!u#i*x6wu)#~ zBnha?G*P`131i*BxZ47aX5-S#f$gS}rKU@ljRUT`&IDtB+K=Ka4MZ0xCQN>E&V@(t zMmsE(8Q17ZSn}SE``VsNabP;hoFbjyIlZ@hA(4ODcl$bH2AP6LJf9z3!R!vYXT>&m zbz^Go2F9rI2fzjVY7q2pbHvL9=du)gT+zna(B@M4TNP@zA4;gt$=~U+sL=nRz;of! z84!L}h@?KCp3qmS$IQS4b1{mFX*2vlr!~#Z6o&??CGi2B#Un0um^?-aq4=rW$?z-Q zYqk`;E~MR6$Rzd&vYV%@SXF=!njFXs%+zvKjKJUelx_udR;s^*zJ>W>Zov9R1&4}# zi#AzTRIjBzlT&J^C}I6&gf6?fThl$CeI-7rF`8PgC-f}p3ofdmL48R|UJgn{%46DB zL)q$=IU1yG!7JFB_+h9N?siI7ZH|`oNwfk(a%*xsGB^---AivOI;)oi@*5>Gjz8R{ zfS*K|$c1{q-&@#V7dyu-pwW~bz1>i;@zlsebwY(&qFVp2&hYR*7f3kFTWqt}Gcsg} zNcx6^k|ba-xuuo(N)7a54jM02b^Th8S+%3Wh)~kKa_|;qmM%bD`FYhnJL+%#P22iC z8)N!AYK!YKxIt(~B51cLA%5zz8F>QZ&tJ>~bPeUu#_dxX3jUQ1*P3xE+!im8pBRYL zXlx&PS%Eu;u}(i>R*H)J)BC*k?GaG``w&$CRG5++>{2J$JW!F|k6V_GI1lf$lg!7` zvC@-!vmwC#XiT)HOB?g$J6GpcL76UPV9<3hzCEVal%4!Qq(2zGseAbJnIn$Ec)lWx zT^kW>*Y;amFnbH*kmwHSGJf-GuFCj7;}$IE#GvlG#^D>fA{Qz7{81%XIl*Eq|0n8|v9T z(usJ5Lz{5`5m0gAm7ygU4SCs*^-t&>{_&~S_!*8AG>K!4DTTw+;^s-^DpyUIbatga zdDl$6xbig}blWYea!1j08pxHzzP|aZjJ8K4d!Ex$+=nF7haZm{Y{KP>YYP(_K)j zwAnklZSdA@Vf4E-nu{CH4RJ8(a9a8Lmf>U_4Lg6aa{#L!PrcP4g2`da!?Eb zb>xl%^av*5Doa$IK%0**f@#;SN%kaCHKLi%u2fANPB>IHvDA!^)1D*Ipr_gr~Ajyg1NJM zX33e53{m{On5$9>T60rsBy|pbYc1kn7(huFITY#wM~d5n+mu6-xBG#E{X0=Lpf@O1pib0hmMkP%_ zqCYBy(1}92?+NES|JuB+_b2%qGQ0c^+=c2d3?V1(;$B;OmwH*Axee-HBzltn+;8;+ zP4uN3bs6}qBsnEs{qbU{PLwE`pG{21aguz~N9bj3A~y0zlEwQaI=iH91&%})Mzzqs zBw6c|($GkG+EXFTEduAPMzw6h$L5=I%QWK1he=i(;-Hg6pXER~d)Ga-xwFD@zT#l@ zJm6J7I0nOBw7wr%Tccm{acOex%Wy037U&xl9#pC4mc1vn)4eyL*+rPI>?q|~ETp6wM@I>f+dFVOK%xFPu2P!fLEq%$a z^^dY!iF>B}yFk0v(-{O2>vsS$&Kr;}sxBZkl4riZ#HglKL~@=1z2|kSGu^DeotVz$T!b&)Dd57uGd46 zX@Zyhy^Wlxqtjdv_ao7}L(hQOwrxX|5Ng}&GL0}81x!L_WW>L{b#!S6D|?=rO6UH! zR_Xa*5h0*l3cNWAbTG80ihlMXkH&&nnx_R&7cH3x-m%6>kFI&hHuEGPAyTW{1F|Y4 zQ>NNi^^{uIWjN=%QaX0DB)s}7zPt{WiZ#zaBMaenz!24$Ij!T{TmUU)b zYOh}PZqQNPTV!Fnc`Z!6>nMDyGTpE14cuxPK{utHNasCcvcYHD%!EyDw^uWN4NZyw z%j9-w%R?lsFrTlet8xYYB5a!gCvytM)%#=w%(7&0m4=F9=I1qi7u$JBPior@*g68` ziDmd{1+-q<&%@rp0_s>Ct|=AnK-sL{Uf4fZU=xd7HbvVxyhq%J{#%0taF_}1;?+58 z^oPfHZwjcn{f~#+dmYs;C`sy4-ZI}RaaRErKHKr-mTWHDpbmcVZ4SpzMy}QMFpuU+ zZAOf4>3fae6|?FXuSFK8>&B2@MYqhyygvhV1g~06A-KoAMUS_*6I;H!sy$P5s=;A> zr4y{k*y*6^xJFTL7+)MO(vMpCUVaOxTTeT&d)KL_`fBCsC6qD|3JW|Z4Kq-p8T;K-J&*uoc$YW&3rlo&U1z5K@?V2nXChs0A_%!8rMBaEYoQhbN=4w( zAk0yqg5R6z{Ized&)7cnF(n3pC%5A^wG?1ab&QE_)cO(ZOfbJDk!+!W;3LIKN72DU zNz5~NP&g*z5i;CO;qgBC==iuCAC7rgdhHpz2_70#_;G`lZEL$yM@6-b`br8@D0|&t zjS3`<9y&onS|5uL#m%qkO-nj0`HQXEJ#i4Vxv2*~!B=IE)3?%4WKjVzyzVV2JBQ_? zF4c*ZChIq>Ly|vrOV}%4Bt3anu0j)|k{0cc_C%^s6rRf%#jJKRW5f`uqBd`s0JFaM z2<77GDLvYbEC2ihMj+hLd-Y?{Mkay60AQ#|(X>oPcsg@aH3N=iE6}DX6V;Ci_@q7E zof9*PGVZY>Qlix~wWapFW{5CZ3=uYnbK#mJt~@CN1J)cw>2Q-cy;WadTJme)NkEooY_CRaDhf;bhzdNQc{0IgTu8;w3N998oQSfvS)2f@J{$a7z{ zsl8;1wWeApH220;eMn5F<~@2hqo0_{O>Kj>Z~k*qVu>yN2>^_@Zzhyvv-WH6pzhcd zZl@Vku-M+1j!`a@%-hNeva_!|BhWj#0rzx+r=ZP1+2l3AGX16C|au^-s3FcP#5rt=8M&?=4&E0gv_~ zw~w^mAXAQ@??a&Gl?_h2?T(Fk`+t#&1Un5Stz#a(80oy}m`E`PWNVLbNp#I~InQ7pC9HVoG}1l3(k< z^qqF_b!=JPpXf(k6nm0)c4jM32^B9Q9`7(BQ^H7UFAD-vsD*XsK|WJoZG-mfC`ur5 z{lofmc_XD^KH?03{aAZgqsYDyNkS!4V6~WxY^6C3>$4E~N~s~!8J7Iv8!CRcpP^C= zkmXA&_c3Z#wr?wT<$YIFxEh7w{NeQb$cDnZ9M3aP8SbUF?f>_+J4sS1^@j!qkWeU7 zobaIx_;1&U1Zb$Efl2C7^Pvz^hNHv#yU?xEKW6Dl78=H=XAh%N zpC5i@k{yKYt&O;dcmKvp17S>VVHuUDR=5b>MO(o^i()L8CP${C-n_4y3e_>H#mc?x zFHHz8!LhvHmW7CGWArG6|0ERL7lg*F_B78>_#k<8NnXQwz~RUb%^1!AE7Q5ZbgwH6q?y~PjET4X(Zwu_wW?+1y98ulZN zsovLofBrwWO2#0X%2YNKj;;cnC%j>Qy}i5;zIjdebij`C91OF|Y&G}FPLb)F+B6%) zVW{Y;M8pbD;2KUkFQ1bD#?%Pe@B1k?>zMAv$JdXxQzh9j07rEeQ8tlidm+rL4F;+0tS1w_Bu zE_v0s4vcl>jo9KI)@Gj?lf(w|Os@lEsyK-Wmv!Cv{{EAMW+rrKMX$tHz;#btS4TmO z^LCrT{Zb? zi(xIIh2HRY*2Jn~fSP0a&1kPxw8#OJwFOoMWH`v$h$W`%yD5ok%WnMoEJng&KR1JG zj{-U1s_#0#nUDTTgYiL}k%bk9UA6fa#g>`_WxXfw{hDct)*`IoF*MZ2?HW6xxIkM| zt0>XyppJ!eCmlvb=dvW{4y4^U)`cB0b!Lc)svK#I+CEd=q9e;ao19)|p&G>jgKQRL zZ7qr(i^J>L$rQ{IpO(mtC-QA~U*aA<1xd z+1}yAzlFNz?yR+DynP}ex2Gu&nI956>^|o{hsj*a96yj+`L@A)fT4WqQCvVtPJ#VS z9#Jo^uc!!89OyzoMhS6K57g|V7oneVtA1VhXuZZYUN?^nvV>rinHZu$U6ImF=kBVa z4k@|jT+PX-P-YlX5A*yGp;{@5$kGz%Q>b}8{j%CHc@ZOV_xNs(*Jc&B2Hv;5S2dH} zwDN*gCLyb(22$swwUf+01{7!EpBrGE{~SHy)$TshgNt6nNAv@lpa?-qdTV;CKBXE% zL}3RzqX)A=?k8R4GvPBB1>dlK{rDIdFH{aoYA_R%t}&2%Ta8wYEgqNU*B6?~Ai*>+ z?3OzH)3^BDQ=X^OQ3m|EO;f+|N61pTr%Bop728-<3BzA~~$u5>^jD zhCZ_!wABK)ZM7v-$4a){!LwMeQ-7>|H>{p*iL*f;4dH!NxuRm;d8pQ?({-~<4{4+z zNi6vr^H8u&EE4GT0d!b%=*Iz?fuP^jQTsp5o$0^{vG-)7VnzG!SAJK!yr=vzbAw^8 zy4#|*z<}ystz$5i=5KGi6hnlQlN!{cR0RDRU{Jk+I!$I~fO$}z#PN}$bN96u7-@MY z@(m(eD1ziO5&?yrYPIg0771E3>9%@gxR9V4Q#_?<{D$u=SPQWc&`ypy_%9Ip@TSnf z!r9WAl*<|PJ3CsJCPf>Aj-kvEaeGn1!qcQ66^$+ZlQghpgz{xRRsM&0bBn-B_Y`j&aDK_{BqtlzJJPE>5rdwJ5+o@Up+a! zgWy^0Pw65O(yl4OFa5;@|26)NClFxi2B8mk2KTzlCd86K0f3=%g*iaG)8KXxk}YtyY3Mer!p8 zPmu~}=*U3W$E|%wBPSYSvC-roASMq0K3Gm-MCBh4A^2WGVM}x6S31usijx_$v*D5@ zhL$*D?m|||Y9^>5>*;Gb{C8+ZE_gyLWaKX3mlmFuRgWgoAxp`!}2%%5obW1llFxTZ?P-|>H`){^{MXJx1)sT^#{YjTHwtf zAfbHE0hXmI({qiw76de>(#dPE3o8&%6pNnM>S+PSnowfA*%VDlNA|YG$Rvix~iGV>{}cF`E6;`)Qni&1y+o+Ogz6$hW@8KiN(2pW;Ee1ixSw*ICjTUR zN@l3WLTTR&ii~tR=@mt|rK=jtbW_a`R~XEWUsnrYj%S(O{S>*&bU6-rxJ{f@KTy2y zEn$}(>$&#C--_9!D@J6^yGwr49<+t)D5x3}&ONK>yiD{4w`_iU!?PdYt8^6Nc#D5a zGNgwYbj!r1tmEB)@zq3smx@S9N$kSANTYZ1ZBY~YUsc`R^C5PQ zPz&^9+m}?LJ+!z_k9RQrKyY(VC-Sql+Sp)q%qX)`smMZH`@UlNwymn7^%&+r3700@ zpRuQ=pwhTqbVMb$x5%=XLn8H;6rF`t9}AOq&{@G@qr{A;m7EwJT&gCX5bgC&HL28~ zwCxVsdeJuf+&`Z5v+A#CDQrWu8KVAzK#s;j#x_7RK9UcIu7%rLXPIY94NG@%^&-== zvN^MK^x}OCzQt!m^4r)d6o0c8QXHPUI*rYf1>?WvI%GoYagM4N&Wtu%g>#OnD28C_ z@K~cd$ugi;Twrl%%}{l*>95$7raZ`aYTNZ~FHgVWlIKtWb6s`WWl%Jj9myzL5yX73 zhkr+~1ymB`AjbjT^(YN|5*Q^GFna1MU1(TgEXFYnOV{Ui_C7`AaaEVg5GocKxi^94 zba5@|wOE1los16J)c1%(BT_>HX{DgSR*O_N;}3AvBq}|7Oj9Xbd*`U8e%JV#+@~Y$ zo(D-f>)xU7nijqU^Rc0+=ZVx{NKF0A=A;&z-^`V|(7+-9j+Q;Ih`$3_z&KX@ZHAi5gJx*G!T&5eU zDs{8E*Q$nznA^J}QzE&Y!lDtr+X5!MAWiRIU5u|jyKsjk9xZFb;=ZnOWawivO+%Lz z#d?Z0i%<5n+XJJKp8{yM;|)Qd_L2xwq|vg3jLxc%e*cHJ)#;RbZ7(!k%n4!3yhe;q zb^8Bpm0dSdw}UsrS#D z9NUR%M628dg}B*we$16cw~KhNybddO)i@pU zldLIo*I3eS2lyxW0RTuXL2)AtsF8VZFGG}f__620M*=H2+LY1+hN%>0JytT7a?&Fb z#5Fq)S0n3f0ejc{>%a+2i^3{4s|p^YQ$ZGRsBj_`mPbm_URY3c7XJNHi1 z!c-0&nSJ%=v6cUit+!x{b6d7>kpRKn-Q8V7f?IHD+zIaP1aBm`y9H>Zad+3??iL(^ z`(>Sd&t5tAxqqR**>lzyHQp+bjt$&ZX43o(L8H=8d)BKO5U@;zbtu$j&d*w0=j7E* zr|jPb?JIBPZ(p;u4mGcvJra{r>s%w@KR$M;F#)Azj%0?Ps?e@9ma}MC)8!C&4-=wp zUSY?F&DKjQv}I))OmTz8xkDaSfLGMU_I`0YtDoSn+XX()yk9z?J&Q&kdNywLol74; zp#&fU@5{_d(GP9HJ}t-mx`2Kde)^xLzU=#np%yjMNYh3gU`e-S_zUU9>f!fUg=7unpfqT88KNY_<^(<4KDV2z6EupHZgJvXnW9vS7lQ41vNh)+-IbBP>| zFu%OWT7&7@w{vRrt&dBM2*HTi`WPrMPAhtQi^t0rG9>4u(qzPeN~Gg%W@giHMZCfm z$W#-iSIu5s%a2w~_giu$ye`abBjSq%A1jRCL?+I9BVj+@*(XN1dVOKkPzQifw_Cii z>PCju*R_Vf0E4$u2re|6wlV2;IGgb;Xp_C48PMgAO!+UADOlQbFu4Peq7IkB>P`!z zW8slU)s!a`I>7m50Z^@±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