login_10.js 186 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776
  1. //(function(){
  2. /**
  3. * @description 基础方法
  4. * @param {String | Object} n dom元素的id,或者dom元素
  5. * @class
  6. */
  7. var $ = window.Simple = function(n) {
  8. return typeof(n) == "string" ? document.getElementById(n) : n;
  9. }
  10. /**
  11. * @description cookie相关
  12. * @class
  13. */
  14. $.cookie = {
  15. /**
  16. * @description 读取cookie
  17. * @public
  18. * @param {String} n 名称
  19. * @returns {String} cookie值
  20. * @example
  21. * $.cookie.get('id_test');
  22. */
  23. get: function (b) {
  24. var filterXSS = function (e) {
  25. if (!e) return e;
  26. for (; e != unescape(e);) e = unescape(e);
  27. for (var r = ["<", ">", "'", '"', "%3c", "%3e", "%27", "%22", "%253c", "%253e", "%2527", "%2522"], n = ["&#x3c;", "&#x3e;", "&#x27;", "&#x22;", "%26%23x3c%3B", "%26%23x3e%3B", "%26%23x27%3B", "%26%23x22%3B", "%2526%2523x3c%253B", "%2526%2523x3e%253B", "%2526%2523x27%253B", "%2526%2523x22%253B"], a = 0; a < r.length; a++) e = e.replace(new RegExp(r[a], "gi"), n[a]);
  28. return e
  29. };
  30. var a;
  31. return filterXSS((a = document.cookie.match(RegExp("(^|;\\s*)" + b + "=([^;]*)(;|$)"))) ? unescape(a[2]) : '');
  32. },
  33. /**
  34. * @description 设置cookie
  35. * @public
  36. *
  37. * @param {String} name cookie名称
  38. * @param {String} value cookie值
  39. * @param {String} [domain = ""] 所在域名
  40. * @param {String} [path = "/"] 所在路径
  41. * @param {Number} [hour = 30] 存活时间,单位:小时;不设置默认为回话cookie
  42. * @example
  43. * $.cookie.set('value1','cookieval',"id.qq.com","/test",24); //设置cookie
  44. */
  45. set: function(name, value, domain, path, hour) {
  46. var expire = new Date();
  47. if (hour) {
  48. expire.setTime(expire.getTime() + 3600000 * hour);
  49. document.cookie = name + "=" + value + "; " + "expires=" + expire.toGMTString() + "; path=" + (path ? path : "/") + "; " + (domain ? ("domain=" + domain + ";") : "");
  50. } else {
  51. document.cookie = name + "=" + value + "; " + "path=" + (path ? path : "/") + "; " + (domain ? ("domain=" + domain + ";") : "");
  52. }
  53. },
  54. /**
  55. * @description 删除指定cookie,复写为过期 !!注意path要严格匹配, /id 不同于/id/
  56. * @public
  57. *
  58. * @param {String} name cookie名称
  59. * @param {String} [domain] 所在域
  60. * @param {String} [path = "/"] 所在路径
  61. * @example
  62. * $.cookie.del('id_test'); //删除cookie
  63. */
  64. del: function(name, domain, path) {
  65. document.cookie = name + "=; expires=Mon, 26 Jul 1997 05:00:00 GMT; path=" + (path ? path : "/") + "; " + (domain ? ("domain=" + domain + ";") : "");
  66. },
  67. /**
  68. * 获取uin,针对业务,对外开源请删除
  69. * @public
  70. *
  71. * @return {String} uin值
  72. * @example
  73. * $.cookie.uin();
  74. */
  75. uin: function() {
  76. var u = $.cookie.get("uin");
  77. return !u ? null : parseInt(u.substring(1, u.length), 10);
  78. }
  79. };
  80. /**
  81. * @description 加载iframe
  82. * @class
  83. */
  84. $.iframe = function(){
  85. function receiveMessageFromIframePage(event) {
  86. console.log('receiveMessageFromIframePage', event)
  87. var msg = event && event.data && event.data.msg || ''
  88. switch (msg) {
  89. case 'exit':
  90. this.opt.onClose && this.opt.onClose(event)
  91. this.reset(event)
  92. break;
  93. case 'success':
  94. this.opt.success && this.opt.success(event)
  95. break;
  96. case this.opt.heartBeat:
  97. this.opt.onload && this.opt.onload(event)
  98. this._hasHeartBeat = true
  99. break;
  100. case 'pt_smsSubmit':
  101. this.opt.smsSubmitEvent && this.opt.smsSubmitEvent()
  102. break;
  103. default:
  104. break;
  105. }
  106. }
  107. return new function () {
  108. this.id = ''
  109. this.parent = null
  110. this.parentID = ''
  111. /**
  112. * 初始化入口
  113. * @param {[type]} opt [description]
  114. * @return {[type]} [description]
  115. */
  116. this.init = function (opt) {
  117. var opt = opt || {}
  118. this.opt = opt
  119. opt.initTime = +new Date()
  120. opt.heartBeatTime = opt.heartBeatTime || 10000
  121. opt.heartBeat = opt.heartBeat || 'heartBeat'
  122. if (this.__hasinit) {
  123. return
  124. }
  125. this.__hasinit = true
  126. var iframe = document.createElement('iframe')
  127. console.log('createElement iFrame opt:',opt);
  128. console.trace();
  129. iframe.name = opt.name || 'iframe'
  130. this.id = iframe.id = opt.id || 'iframeid';
  131. this.parentID = opt.parentID
  132. iframe.style.cssText = opt.iframeStyle || 'z-index:999;height:100%;width:100%;position:fixed;left:0;top:0;right:0;bottom:0'
  133. iframe.src = opt.url
  134. var iframe_mask = null;
  135. if(this.parentID){
  136. iframe_mask = document.createElement('div');
  137. if(opt.parentStyle){
  138. iframe_mask.setAttribute('style',opt.parentStyle)
  139. }
  140. iframe_mask.setAttribute('id',opt.parentID)
  141. if(opt.bgFilter){
  142. var filter = document.createElement('div')
  143. filter.setAttribute('style',"width:100%;height:100%;position: absolute;left:0;top:0;background: inherit;filter: blur(15px);")
  144. iframe_mask.appendChild(filter)
  145. }
  146. iframe_mask.appendChild(iframe)
  147. document.body.append(iframe_mask)
  148. }else{
  149. document.body.appendChild(iframe)
  150. }
  151. this.receiveMessageFromIframePage = receiveMessageFromIframePage.bind(this)
  152. this.heartBeat(opt)
  153. this.addListener(opt)
  154. };
  155. this.__hasinit = false
  156. this._hasHeartBeat = false
  157. this.addListener = function (opt) {
  158. //监听message事件
  159. window.addEventListener("message", this.receiveMessageFromIframePage, false);
  160. }
  161. this.postMessage = function (opt) {
  162. var iframeChild = document.getElementById(this.id);//获取iframe
  163. iframeChild.contentWindow.postMessage(opt,'https://ui.ptlogin2.qq.com');//childDomain是子页面的源(协议+主机+端口号)
  164. }
  165. this.heartBeat = function (opt) {
  166. var self = this
  167. var time = opt.heartBeatTime || 10000
  168. setTimeout(function () {
  169. if (self._hasHeartBeat) {
  170. //有心跳,继续
  171. console.log('子页面调起成功')
  172. } else {
  173. console.log('子页面调起失败')
  174. //self.reset()
  175. opt.fail && opt.fail({
  176. msg: '子页面调起失败,timeout'
  177. })
  178. }
  179. }, time)
  180. }
  181. this.reset = function () {
  182. var self = this
  183. self.__hasinit = false
  184. var iFrame = document.getElementById(self.id)
  185. var parent = document.getElementById(self.parentID)
  186. if(parent){
  187. document.body.removeChild(parent)
  188. }else if(iFrame) {
  189. document.body.removeChild(iFrame)
  190. }
  191. window.removeEventListener("message", this.receiveMessageFromIframePage, false);
  192. }
  193. };
  194. }
  195. /**
  196. * @description url相关
  197. */
  198. $.url = {
  199. getParam: function (name, url) {
  200. url = url || window.location.href
  201. var r = new RegExp('(\\?|#|&)' + name + '=(.*?)(&|#|$)')
  202. var m = url.match(r)
  203. if (m){
  204. return decodeURIComponent(m[2])
  205. }
  206. return ''
  207. }
  208. }
  209. /**
  210. *@description http相关
  211. *@class
  212. */
  213. $.http = {
  214. /**
  215. * @description jsonp获取回调函数-- 可以支持跨域
  216. *
  217. * @param {String} url 请求路径
  218. * @example
  219. * $.http.jsonp('http://webryan.net/cgi-bin/test'); //cgi的返回值应该是 fnCallback({'data':''})的形式
  220. */
  221. jsonp: function(url) {
  222. var s = document.createElement("script");
  223. s.src = url;
  224. document.getElementsByTagName("head")[0].appendChild(s);
  225. },
  226. /**
  227. * @description 异步加载script脚本,并回调
  228. *
  229. * @param {String} src 请求路径
  230. * @param {Function} callback 加载文档后的回调函数
  231. * @param {Function} err 加载失败后回调
  232. * @example
  233. * $.http.loadScript('http://webryan.net/js/index.js',function(){alert()}); //callback通常为函数名,非字符串
  234. */
  235. loadScript: function(src, callback, err) {
  236. var tag = document.createElement("script");
  237. /**
  238. * Attach handlers for all browsers
  239. * @ignore
  240. */
  241. tag.onload = tag.onreadystatechange = function() {
  242. if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
  243. // 执行回调
  244. if (typeof callback == "function") {
  245. callback();
  246. }
  247. // Handle memory leak in IE
  248. tag.onload = tag.onreadystatechange = null;
  249. if (tag.parentNode) {
  250. tag.parentNode.removeChild(tag);
  251. }
  252. }
  253. };
  254. tag.src = src;
  255. document.getElementsByTagName("head")[0].appendChild(tag);
  256. },
  257. /**
  258. * @description发出ajax请求
  259. *
  260. * @param {String} url 请求路径--不能跨域
  261. * @param {Object} [para] 参数列表
  262. * @param {Function} cb 回调函数
  263. * @param {String} method 请求方式: [post|get]
  264. * @param {String} [type = json] 数据类型:[json|text] --默认为json
  265. * @example
  266. * $.http.ajax('/cgi-bin/info',{'uin':10001},fnCallBack,'get');
  267. */
  268. ajax: function(url, para, cb, method, type) {
  269. var xhr = new XMLHttpRequest();
  270. xhr.open(method, url);
  271. /**
  272. * onreadystatechange
  273. * @ignore
  274. */
  275. xhr.onreadystatechange = function() {
  276. if (xhr.readyState == 4) {
  277. //ie error with 1223 and opera with 304 or 0
  278. if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || xhr.status === 1223 || xhr.status === 0) {
  279. if (typeof(type) == "undefined" && xhr.responseText) {
  280. cb(eval("(" + xhr.responseText + ")")); //不容错,以便于排查json错误
  281. } else {
  282. cb(xhr.responseText);
  283. }
  284. }
  285. xhr = null;
  286. }
  287. };
  288. xhr.send(para);
  289. return xhr;
  290. },
  291. /**
  292. * @description 通过ajax发出get请求
  293. *
  294. * @param {String} url 请求路径--不能跨域
  295. * @param {Object} [para] 参数列表
  296. * @param {Function} cb 回调函数
  297. * @param {String} [type = "json"] 数据类型:[json|text] --默认为json
  298. * @example
  299. * $.http.get('/cgi-bin/info',{'uin':10001},fnCallBack);
  300. */
  301. get: function(url, para, cb, type) {
  302. if (para) {
  303. var params = [];
  304. for (var p in para) {
  305. if (para.hasOwnProperty(p)) params.push(p + "=" + para[p]);
  306. }
  307. if (url.indexOf("?") == -1) {
  308. url += "?";
  309. }
  310. url += params.join('&');
  311. }
  312. return $.http.ajax(url, null, cb, "GET", type);
  313. },
  314. /**
  315. * @description 预加载某个文件,包括图片,js,flash --可以用于上报
  316. *
  317. * @param {String} url 请求路径
  318. * @example
  319. * $.http.preload('http://webryan.net/swf/friends.swf');
  320. */
  321. preload: function(url) {
  322. var s = document.createElement("img");
  323. s.src = url;
  324. s = null;
  325. }
  326. };
  327. /**
  328. * @description 通过ajax发出get请求
  329. *
  330. * @param {String} url 请求路径--不能跨域
  331. * @param {Object} [para] 参数列表
  332. * @param {Function} cb 回调函数
  333. * @param {String} [type = "json"] 数据类型:[json|text] --默认为json
  334. * @example
  335. * $.get('/cgi-bin/info',{'uin':10001},fnCallBack);
  336. */
  337. $.get = $.http.get;
  338. /**
  339. * @description 通过ajax发出post请求
  340. *
  341. * @param {String} url 请求路径--不能跨域
  342. * @param {Object} para 参数列表
  343. * @param {Function} cb 回调函数
  344. * @param {String} [type = "json"] 数据类型:[json|text] --默认为json
  345. * @example
  346. * $.post('/cgi-bin/info_mod',{'uin':10001},fnCallBack);
  347. */
  348. $.post = $.http.post;
  349. /**
  350. * @description jsonp获取回调函数-- 可以支持跨域
  351. *
  352. * @param {String} url 请求路径
  353. * @example
  354. * $.http.jsonp('http://webryan.net/cgi-bin/test'); //cgi的返回值应该是 fnCallback({'data':''})的形式
  355. */
  356. $.jsonp = $.http.jsonp;
  357. /**
  358. * @description 获取浏览器的版本等信息
  359. * @class
  360. * @param {String} name [type-类型1.msie.2.ff.3.opera.4.webkit|version--版本号]
  361. *
  362. * @example
  363. * $.browser("type"); $.browser("version");
  364. */
  365. $.browser = function(name) {
  366. if (typeof $.browser.info == "undefined") {
  367. var ret = {
  368. type: ""
  369. };
  370. var ua = navigator.userAgent.toLowerCase();
  371. if (/chrome/.test(ua)) {
  372. ret = {
  373. type: "chrome",
  374. version: /chrome[\/ ]([\w.]+)/
  375. };
  376. } else if (/opera/.test(ua)) {
  377. ret = {
  378. type: "opera",
  379. version: /version/.test(ua) ? /version[\/ ]([\w.]+)/ : /opera[\/ ]([\w.]+)/
  380. };
  381. } else if (/msie/.test(ua)) {
  382. ret = {
  383. type: "msie",
  384. version: /msie ([\w.]+)/
  385. };
  386. } else if (/mozilla/.test(ua) && !/compatible/.test(ua)) {
  387. ret = {
  388. type: "ff",
  389. version: /rv:([\w.]+)/
  390. };
  391. } else if (/safari/.test(ua)) {
  392. ret = {
  393. type: "safari",
  394. version: /safari[\/ ]([\w.]+)/
  395. };
  396. }
  397. ret.version = (ret.version && ret.version.exec(ua) || [0, "0"])[1];
  398. $.browser.info = ret;
  399. }
  400. return $.browser.info[name]
  401. };
  402. /**
  403. * 事件相关 -- 绑定,解绑,触发
  404. */
  405. $.e = {
  406. // Private utility to generate unique handler ids
  407. _counter: 0,
  408. _uid: function() {
  409. return "h" + $.e._counter++;
  410. },
  411. add: function(element, eventType, handler) {
  412. if (typeof element != "object") {
  413. element = $(element);
  414. }
  415. if (document.addEventListener) {
  416. element.addEventListener(eventType, handler, false);
  417. } else if (document.attachEvent) {
  418. if ($.e._find(element, eventType, handler) != -1) return;
  419. // To invoke the handler function as a method of the
  420. // element, we've got to define this nested function and register
  421. // it instead of the handler function itself.
  422. var wrappedHandler = function(e) {
  423. if (!e) e = window.event;
  424. // Create a synthetic event object with partial compatibility
  425. // with DOM events.
  426. var event = {
  427. _event: e, // In case we really want the IE event object
  428. type: e.type, // Event type
  429. target: e.srcElement, // Where the event happened
  430. currentTarget: element, // Where we're handling it
  431. relatedTarget: e.fromElement ? e.fromElement : e.toElement,
  432. eventPhase: (e.srcElement == element) ? 2 : 3,
  433. // Mouse coordinates
  434. clientX: e.clientX,
  435. clientY: e.clientY,
  436. screenX: e.screenX,
  437. screenY: e.screenY,
  438. // Key state --fix:keyCode
  439. altKey: e.altKey,
  440. ctrlKey: e.ctrlKey,
  441. shiftKey: e.shiftKey,
  442. keyCode: e.keyCode,
  443. data: e.data,
  444. origin: e.origin,
  445. // Event-management functions
  446. stopPropagation: function() {
  447. this._event.cancelBubble = true;
  448. },
  449. preventDefault: function() {
  450. this._event.returnValue = false;
  451. }
  452. }
  453. // Invoke the handler function as a method of the element, passing
  454. // the synthetic event object as its single argument.
  455. // Use Function.call( ) if defined; otherwise do a hack
  456. if (Function.prototype.call)
  457. handler.call(element, event);
  458. else {
  459. // If we don't have Function.call, fake it like this.
  460. element._currentHandler = handler;
  461. element._currentHandler(event);
  462. element._currentHandler = null;
  463. }
  464. };
  465. // Now register that nested function as our event handler.
  466. element.attachEvent("on" + eventType, wrappedHandler);
  467. // Now we must do some record keeping to associate the user-supplied
  468. // handler function and the nested function that invokes it.
  469. // We have to do this so that we can deregister the handler with the
  470. // remove( ) method and also deregister it automatically on page unload.
  471. // Store all info about this handler into an object.
  472. var h = {
  473. element: element,
  474. eventType: eventType,
  475. handler: handler,
  476. wrappedHandler: wrappedHandler
  477. };
  478. // Figure out what document this handler is part of.
  479. // If the element has no "document" property, it is not
  480. // a window or a document element, so it must be the document
  481. // object itself.
  482. var d = element.document || element;
  483. // Now get the window associated with that document.
  484. var w = d.parentWindow;
  485. // We have to associate this handler with the window,
  486. // so we can remove it when the window is unloaded.
  487. var id = $.e._uid(); // Generate a unique property name
  488. if (!w._allHandlers) w._allHandlers = {}; // Create object if needed
  489. w._allHandlers[id] = h; // Store the handler info in this object
  490. // And associate the id of the handler info with this element as well.
  491. if (!element._handlers) element._handlers = [];
  492. element._handlers.push(id);
  493. // If there is not an onunload handler associated with the window,
  494. // register one now.
  495. if (!w._onunloadHandlerRegistered) {
  496. w._onunloadHandlerRegistered = true;
  497. w.attachEvent("onunload", $.e._removeAllHandlers);
  498. }
  499. }
  500. },
  501. remove: function(element, eventType, handler) {
  502. if (document.addEventListener) {
  503. element.removeEventListener(eventType, handler, false);
  504. } else if (document.attachEvent) {
  505. // Find this handler in the element._handlers[] array.
  506. var i = $.e._find(element, eventType, handler);
  507. if (i == -1) return; // If the handler was not registered, do nothing
  508. // Get the window of this element.
  509. var d = element.document || element;
  510. var w = d.parentWindow;
  511. // Look up the unique id of this handler.
  512. var handlerId = element._handlers[i];
  513. // And use that to look up the handler info.
  514. var h = w._allHandlers[handlerId];
  515. // Using that info, we can detach the handler from the element.
  516. element.detachEvent("on" + eventType, h.wrappedHandler);
  517. // Remove one element from the element._handlers array.
  518. element._handlers.splice(i, 1);
  519. // And delete the handler info from the per-window _allHandlers object.
  520. delete w._allHandlers[handlerId];
  521. }
  522. },
  523. // A utility function to find a handler in the element._handlers array
  524. // Returns an array index or -1 if no matching handler is found
  525. _find: function(element, eventType, handler) {
  526. var handlers = element._handlers;
  527. if (!handlers) return -1; // if no handlers registered, nothing found
  528. // Get the window of this element
  529. var d = element.document || element;
  530. var w = d.parentWindow;
  531. // Loop through the handlers associated with this element, looking
  532. // for one with the right type and function.
  533. // We loop backward because the most recently registered handler
  534. // is most likely to be the first removed one.
  535. for (var i = handlers.length - 1; i >= 0; i--) {
  536. var handlerId = handlers[i]; // get handler id
  537. var h = w._allHandlers[handlerId]; // get handler info
  538. // If handler info matches type and handler function, we found it.
  539. if (h.eventType == eventType && h.handler == handler)
  540. return i;
  541. }
  542. return -1; // No match found
  543. },
  544. _removeAllHandlers: function() {
  545. // This function is registered as the onunload handler with
  546. // attachEvent. This means that the this keyword refers to the
  547. // window in which the event occurred.
  548. var w = this;
  549. // Iterate through all registered handlers
  550. for (id in w._allHandlers) {
  551. // Get handler info for this handler id
  552. var h = w._allHandlers[id];
  553. // Use the info to detach the handler
  554. h.element.detachEvent("on" + h.eventType, h.wrappedHandler);
  555. // Delete the handler info from the window
  556. delete w._allHandlers[id];
  557. }
  558. },
  559. /**
  560. * 获取时间发生的元素
  561. * @param {Object} e 事件
  562. */
  563. src: function(e) {
  564. return e ? e.target : event.srcElement;
  565. },
  566. /**
  567. * 阻止冒泡
  568. *
  569. */
  570. stopPropagation: function(e) {
  571. e ? e.stopPropagation() : event.cancelBubble = true;
  572. }
  573. };
  574. /**
  575. * @description BOM相关,toolkit
  576. * @class
  577. */
  578. $.bom = {
  579. /**
  580. * @description 读取location.search
  581. *
  582. * @param {String} n 名称
  583. * @return {String} search值
  584. * @example
  585. * $.bom.query('mod');
  586. */
  587. query: function(n) {
  588. var m = window.location.search.match(new RegExp("(\\?|&)" + n + "=([^&]*)(&|$)"));
  589. return !m ? "" : decodeURIComponent(m[2]);
  590. }
  591. };
  592. /**
  593. * 用来设置window.name的属性
  594. * name的形式: ;a=xxxxxxx;b=xxxxxxx;c=xxxxxxx
  595. */
  596. $.winName = {
  597. set: function(n, v) {
  598. var name = window.name || "";
  599. if (name.match(new RegExp(";" + n + "=([^;]*)(;|$)"))) { //先验证是否存在
  600. window.name = name.replace(new RegExp(";" + n + "=([^;]*)"), ";" + n + "=" + v);
  601. } else {
  602. window.name = name + ";" + n + "=" + v;
  603. }
  604. },
  605. get: function(n) {
  606. var name = window.name || "";
  607. var v = name.match(new RegExp(";" + n + "=([^;]*)(;|$)"));
  608. return v ? v[1] : "";
  609. },
  610. clear: function(n) {
  611. var name = window.name || "";
  612. window.name = name.replace(new RegExp(";" + n + "=([^;]*)"), "");
  613. }
  614. };
  615. //本地存储
  616. $.localStorage = {
  617. //有些浏览器禁用cookie后会导致这个报错
  618. isSupport:function(){
  619. try{
  620. return window.localStorage ? true : false;
  621. }catch(e){
  622. return false;
  623. }
  624. } ,
  625. get: function(key) {
  626. var v = "";
  627. try {
  628. v = window.localStorage.getItem(key);
  629. } catch (e) {
  630. v = ""
  631. }
  632. return v;
  633. },
  634. set: function(key, value) {
  635. try {
  636. window.localStorage.setItem(key, value);
  637. } catch (e) {}
  638. },
  639. remove: function(key) {
  640. try {
  641. window.localStorage.removeItem(key);
  642. } catch (e) {}
  643. }
  644. };
  645. /**
  646. * @description 字符串常用操作
  647. * @date 2011.11.30
  648. * @author knightli
  649. * @class
  650. */
  651. $.str = (function() {
  652. var htmlDecodeDict = {
  653. "quot": '"',
  654. "lt": "<",
  655. "gt": ">",
  656. "amp": "&",
  657. "nbsp": " ",
  658. "#34": '"',
  659. "#60": "<",
  660. "#62": ">",
  661. "#38": "&",
  662. "#160": " "
  663. };
  664. //var htmlEncodeDict = { '"': "quot", "<": "lt", ">": "gt", "&": "amp", " ": "nbsp" };
  665. var htmlEncodeDict = {
  666. '"': "#34",
  667. "<": "#60",
  668. ">": "#62",
  669. "&": "#38",
  670. " ": "#160"
  671. };
  672. return {
  673. /**
  674. * @description 将字符串里entity解码成对应的符号,如&lt;对应<
  675. * @param {String} s 原始字符串
  676. * @return {String} 处理后字符串
  677. * @example
  678. * $.str.decodeHtml('&lt;script&gt;&lt;/script&gt;'); 返回结果为:"<script></script>"
  679. */
  680. decodeHtml: function(s) {
  681. s += '';
  682. return s.replace(/&(quot|lt|gt|amp|nbsp);/ig,
  683. function(all, key) {
  684. return htmlDecodeDict[key];
  685. }).replace(/&#u([a-f\d]{4});/ig,
  686. function(all, hex) {
  687. return String.fromCharCode(parseInt("0x" + hex));
  688. }).replace(/&#(\d+);/ig,
  689. function(all, number) {
  690. return String.fromCharCode(+number);
  691. });
  692. },
  693. /**
  694. * @description 将字符串里的"<"、"&"等转成对应entity
  695. * @param {String} s 原始字符串
  696. * @return {String} 处理后字符串
  697. * @example
  698. * $.str.encodeHtml('<script></script>'); 返回结果为:"&lt;script&gt;&lt;/script&gt;"
  699. */
  700. encodeHtml: function(s) {
  701. s += '';
  702. return s.replace(/["<>& ]/g,
  703. function(all) {
  704. return "&" + htmlEncodeDict[all] + ";";
  705. });
  706. },
  707. /**
  708. * @description 删除首尾空格
  709. * @param {String} str 原始字符串
  710. * @return {String} 处理后字符串
  711. * @example
  712. * $.str.trim(' somestring... ');
  713. */
  714. trim: function(str) {
  715. str += '';
  716. var str = str.replace(/^\s+/, ''),
  717. ws = /\s/,
  718. end = str.length;
  719. while (ws.test(str.charAt(--end)));
  720. return str.slice(0, end + 1);
  721. },
  722. /**
  723. * [uin2hex 将uin转换成加盐需要的那种字符串]
  724. * @param {[type]} str [description]
  725. * @return {[type]} [description]
  726. */
  727. uin2hex: function(str) {
  728. var maxLength = 16;
  729. str = parseInt(str);
  730. var hex = str.toString(16);
  731. var len = hex.length;
  732. for (var i = len; i < maxLength; i++) {
  733. hex = '0' + hex;
  734. }
  735. var arr = [];
  736. for (var j = 0; j < maxLength; j += 2) {
  737. arr.push("\\x" + hex.substr(j, 2))
  738. }
  739. var result = arr.join("");
  740. eval('result="' + result + '"');
  741. return result;
  742. },
  743. /**
  744. * [bin2String 将后台check的uin序列还原]
  745. * @param {[type]} str [description]
  746. * @return {[type]} [description]
  747. */
  748. bin2String: function(a) {
  749. var arr = [];
  750. for (var i = 0, len = a.length; i < len; i++) {
  751. var temp = a.charCodeAt(i).toString(16);
  752. if (temp.length == 1) {
  753. temp = "0" + temp;
  754. }
  755. arr.push(temp);
  756. }
  757. arr = '0x' + arr.join('');
  758. arr = parseInt(arr, 16);
  759. return arr;
  760. },
  761. /**
  762. * [utf8ToUincode utf-8编码转unicode字符]
  763. * @param {[type]} s [description]
  764. * @return {[type]} [description]
  765. */
  766. utf8ToUincode: function(s) {
  767. var result = "";
  768. try {
  769. var length = s.length;
  770. var arr = [];
  771. for (i = 0; i < length; i += 2) {
  772. arr.push("%" + s.substr(i, 2));
  773. }
  774. result = decodeURIComponent(arr.join(""));
  775. result = $.str.decodeHtml(result);
  776. } catch (e) {
  777. result = "";
  778. }
  779. return result;
  780. },
  781. json2str: function(obj) {
  782. var result = "";
  783. if (typeof JSON != "undefined") {
  784. result = JSON.stringify(obj);
  785. } else {
  786. var arr = [];
  787. for (var i in obj) {
  788. arr.push("'" + i + "':" + "'" + obj[i] + "'");
  789. }
  790. result = '{' + arr.join(',') + '}';
  791. }
  792. return result;
  793. },
  794. //可能会溢出
  795. time33: function(str) {
  796. var hash = 0;
  797. for (var i = 0, length = str.length; i < length; i++) {
  798. hash = hash * 33 + str.charCodeAt(i);
  799. }
  800. return hash % 4294967296
  801. },
  802. //建议使用这个
  803. hash33: function(str) {
  804. var hash = 0;
  805. for (var i = 0, length = str.length; i < length; ++i) {
  806. hash += (hash << 5) + str.charCodeAt(i);
  807. }
  808. return hash & 0x7fffffff;
  809. }
  810. };
  811. })();
  812. /**
  813. * @description 计算节点的样式,大小,位置等
  814. * @author avenwu
  815. * @date 2011.11.30
  816. * @class
  817. */
  818. $.css = function() {
  819. return {
  820. /**
  821. * @description 显示某个元素
  822. *
  823. * @param {Object} element dom元素
  824. * @example
  825. * $.css.show(dom);
  826. */
  827. show: function(element) {
  828. if (typeof element == "string") {
  829. element = $(element);
  830. }
  831. element.style.display = "block";
  832. },
  833. /**
  834. * @description 隐藏某个元素
  835. *
  836. * @param {Object} element dom元素
  837. * @example
  838. * $.css.hide(dom);
  839. */
  840. hide: function(element) {
  841. if (typeof element == "string") {
  842. element = $(element);
  843. }
  844. element.style.display = "none";
  845. },
  846. getElementViewTop: function(elementId) {
  847. var element = $(elementId);
  848. var actualTop = element.offsetTop;
  849. var current = element.offsetParent;
  850. while (current !== null) {
  851. actualTop += current.offsetTop;
  852. current = current.offsetParent;
  853. }
  854. if (document.compatMode == "BackCompat") {
  855. var elementScrollTop = document.body.scrollTop;
  856. } else {
  857. var elementScrollTop = document.documentElement.scrollTop;
  858. }
  859. return actualTop - elementScrollTop;
  860. }
  861. }
  862. }();
  863. /**
  864. * [check 检查相关的]
  865. * @return {[type]} [description]
  866. */
  867. $.check = {
  868. //是否为https
  869. isHttps: function() {
  870. return document.location.protocol == "https:";
  871. },
  872. isSsl: function() {
  873. var host = document.location.host;
  874. return /^ssl./i.test(host);
  875. },
  876. //是否为pad
  877. isIpad: function() {
  878. var u = navigator.userAgent.toLowerCase();
  879. return /ipad/i.test(u);
  880. },
  881. //检查QQ
  882. isQQ: function(n) {
  883. return /^[1-9]{1}\d{4,9}$/.test(n);
  884. },
  885. //非法qq
  886. isNullQQ: function(n) {
  887. return /^\d{1,4}$/.test(n);
  888. },
  889. //检查微博短昵称
  890. isNick: function(n) {
  891. return /^[a-zA-Z]{1}([a-zA-Z0-9]|[-_]){0,19}$/.test(n);
  892. },
  893. //检查微博中文帐号,1-8位
  894. isName: function(n) {
  895. if (n == "<请输入帐号>")
  896. return false;
  897. return /[\u4E00-\u9FA5]{1,8}/.test(n);
  898. },
  899. //检查手机号码(微博支持所有手机号码)
  900. //isPhone:function(n){return /^(?:86|886|)1(?:(?:3\d{1})|44|(?:5[012789356]{1})|(?:8[065879]{1}))\d{8}$/.test(n);},
  901. isPhone: function(n) {
  902. return /^(?:86|886|)1\d{10}\s*$/.test(n);
  903. },
  904. //检查海外手机帐号(香港,台湾和澳门),微博专用
  905. isSeaPhone: function(n) {
  906. return /^(00)?(?:852|853|886(0)?\d{1})\d{8}$/.test(n);
  907. },
  908. //检查邮箱
  909. isMail: function(n) {
  910. return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(n);
  911. },
  912. //检测合法密码(非空长度不超过16位)
  913. isPassword: function(p) {
  914. return p && p.length >= 16;
  915. },
  916. //国外的手机号码,00开头,至少10位
  917. isForeignPhone: function(n) {
  918. return /^00\d{7,}/.test(n)
  919. },
  920. needVip: function(appid) {
  921. var blankAppid = ["21001601", "21000110", "21000121", "46000101", "716027609", "716027610", "549000912", "717016513"];
  922. var flag = true;
  923. for (var i = 0, length = blankAppid.length; i < length; i++) {
  924. if (blankAppid[i] == appid) {
  925. flag = false;
  926. break;
  927. }
  928. }
  929. return flag;
  930. },
  931. isPaipai: function() {
  932. return /paipai.com$/.test(window.location.hostname);
  933. },
  934. //拍拍多客服账号, none@518810189, 用户名+@+一串数字
  935. isPaipaiDuokefu: function(n) {
  936. return /^.+@.+$/.test(n);
  937. },
  938. /**
  939. * [is_weibo_appid 区分微博帐号的appid]558032501笔记使用微博帐号
  940. * @param {[type]} appid [description]
  941. * @return {Boolean} [description]
  942. */
  943. is_weibo_appid: function(appid) {
  944. if (appid == 46000101 || appid == 607000101 || appid == 558032501 || appid == 682023901) {
  945. return true;
  946. }
  947. return false;
  948. }
  949. };
  950. /**
  951. * [report description]
  952. * @return {[type]} [description]
  953. */
  954. $.report = {
  955. /**
  956. * [monitor description]
  957. * @param {String} id [monitor上报id]
  958. * @param {Number} probability [上报概率]
  959. */
  960. monitor: function(id, probability) {
  961. if (Math.random() > (probability || 1)) return;
  962. var url = location.protocol + '//ui.ptlogin2.qq.com/cgi-bin/report?id=' + id;
  963. $.http.preload(url);
  964. },
  965. /**
  966. * [nlog nlog日志上报]
  967. * @param {String} msg [description]
  968. * @param {Number|String} mid id1-id2-id3...
  969. * @param {String} uin
  970. */
  971. nlog: function(msg, mid, uin) {
  972. var reportUrl = "//ui.ptlogin2.qq.com/cgi-bin/report?";
  973. var e_info = encodeURIComponent(msg + '|_|' + window.location.href + '|_|' + window.navigator.userAgent);
  974. mid = mid ? mid : 0;
  975. if (uin)
  976. reportUrl += 'u=' + uin + '&';
  977. reportUrl += ('id=' + mid + '&msg=' + e_info + '&v=' + Math.random());
  978. $.http.preload(reportUrl);
  979. },
  980. log: function(msg) {
  981. // 这是一个不存在的域名,我只是为了在fiddler上打log
  982. $.http.preload('http://console.log?msg=' + encodeURIComponent(typeof msg == 'string' ? msg : JSON.stringify(msg)));
  983. }
  984. };
  985. /**
  986. * [检测浏览器类型, 以及打开APP的方式]
  987. * @return [browser, openStyle]
  988. */
  989. $.detectBrowser = function() {
  990. if(window.MzJavascriptInterface && typeof window.MzJavascriptInterface.isMzBrowser === 'function' && window.MzJavascriptInterface.isMzBrowser()){
  991. return ["meizu", "location"];
  992. }
  993. var ua=window.navigator.userAgent;
  994. var matched;
  995. if (/android/i.test(ua)) {
  996. if (matched = ua.match(/OppoBrowser|SamsungBrowser|MQQBrowser|baidubrowser|baiduboxapp|QihooBrowser|UCBrowser|2345Browser|Firefox|MicroMessenger/i)) {
  997. matched[1] = "location";
  998. } else if (matched = ua.match(/SogouMobileBrowser|LieBaoFast|XiaoMi\/MiuiBrowser|opr|vivo/i)) {
  999. matched[1] = "iframe";
  1000. } else if (matched = ua.match(/Chrome/i)) {
  1001. var version = ua.match(/chrome\/([\d]+)/i);
  1002. if (version) version = version[1];
  1003. if (version != 40)
  1004. matched[1] = "open";
  1005. }
  1006. } else if (/iphone|ipod/ig.test(ua)) {
  1007. if (matched = ua.match(/MQQBrowser|UCBrowser|SogouMobileBrowser|baidubrowser|baiduboxapp|QihooBrowser|Opera|2345Browser|LieBao/i)){
  1008. }else if (matched = ua.match(/CriOS|Chrome/i))
  1009. (matched[0].toLowerCase() == "crios") && (matched[0] = "Chrome");
  1010. }
  1011. return matched || ["others", ""];
  1012. };
  1013. //调用微信api通用接口
  1014. $.invokeWXAPI = function(name, param, callback) {
  1015. var api = function() {
  1016. WeixinJSBridge.invoke(name, param, callback);
  1017. };
  1018. if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") {
  1019. api();
  1020. } else {
  1021. if (document.addEventListener) {
  1022. document.addEventListener("WeixinJSBridgeReady", api, false);
  1023. } else if (document.attachEvent) {
  1024. document.attachEvent("WeixinJSBridgeReady", api);
  1025. document.attachEvent("onWeixinJSBridgeReady", api);
  1026. }
  1027. }
  1028. };
  1029. // //接入nohost
  1030. // (function() {
  1031. // var _sname = 'nohost_guid';
  1032. // var _src = '/nohost_htdocs/js/SwitchHost.js';
  1033. // if ($.cookie.get(_sname) != '') {
  1034. // $.http.loadScript(_src, function() {
  1035. // var init = window['SwitchHost'] && window['SwitchHost'].init;
  1036. // init && init();
  1037. // });
  1038. // }
  1039. // })();
  1040. // setTimeout(function() {
  1041. // var url = "http://isdspeed.qq.com/cgi-bin/r.cgi?";
  1042. // if ($.check.isHttps()) {
  1043. // url = "https://huatuospeed.weiyun.com/cgi-bin/r.cgi?";
  1044. // }
  1045. // url += "flag1=7808&flag2=1&flag3=9";
  1046. // var percent = 0.01;
  1047. // if (Math.random() < (percent || 1)) {
  1048. // if (typeof window.postMessage != "undefined")
  1049. // url += ("&2=" + 2000);
  1050. // else
  1051. // url += ("&2=" + 1000);
  1052. // url += "&v=" + Math.random();
  1053. // $.http.preload(url);
  1054. // }
  1055. // }, 500);
  1056. if(typeof process!=='undefined' && process.env && process.env.UNITTEST==1){
  1057. module.exports = $
  1058. }
  1059. /**
  1060. * [Encryption rsa算法封装]
  1061. */
  1062. $ = window.$ || {};
  1063. $pt = window.$pt || {};
  1064. $.RSA = $pt.RSA =function(){
  1065. // Depends on jsbn.js and rng.js
  1066. // Version 1.1: support utf-8 encoding in pkcs1pad2
  1067. // convert a (hex) string to a bignum object
  1068. function parseBigInt(str,r) {
  1069. return new BigInteger(str,r);
  1070. }
  1071. function linebrk(s,n) {
  1072. var ret = "";
  1073. var i = 0;
  1074. while(i + n < s.length) {
  1075. ret += s.substring(i,i+n) + "\n";
  1076. i += n;
  1077. }
  1078. return ret + s.substring(i,s.length);
  1079. }
  1080. function byte2Hex(b) {
  1081. if(b < 0x10)
  1082. return "0" + b.toString(16);
  1083. else
  1084. return b.toString(16);
  1085. }
  1086. // PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
  1087. function pkcs1pad2(s,n) {
  1088. if(n < s.length + 11) { // TODO: fix for utf-8
  1089. uv_alert("Message too long for RSA");
  1090. return null;
  1091. }
  1092. var ba = new Array();
  1093. var i = s.length - 1;
  1094. while(i >= 0 && n > 0) {
  1095. var c = s.charCodeAt(i--);
  1096. ba[--n] = c;
  1097. /* if(c < 128) { // encode using utf-8
  1098. ba[--n] = c;
  1099. }
  1100. else if((c > 127) && (c < 2048)) {
  1101. ba[--n] = (c & 63) | 128;
  1102. ba[--n] = (c >> 6) | 192;
  1103. }
  1104. else {
  1105. ba[--n] = (c & 63) | 128;
  1106. ba[--n] = ((c >> 6) & 63) | 128;
  1107. ba[--n] = (c >> 12) | 224;
  1108. }*/
  1109. }
  1110. ba[--n] = 0;
  1111. var rng = new SecureRandom();
  1112. var x = new Array();
  1113. while(n > 2) { // random non-zero pad
  1114. x[0] = 0;
  1115. while(x[0] == 0) rng.nextBytes(x);
  1116. ba[--n] = x[0];
  1117. }
  1118. ba[--n] = 2;
  1119. ba[--n] = 0;
  1120. return new BigInteger(ba);
  1121. }
  1122. // "empty" RSA key constructor
  1123. function RSAKey() {
  1124. this.n = null;
  1125. this.e = 0;
  1126. this.d = null;
  1127. this.p = null;
  1128. this.q = null;
  1129. this.dmp1 = null;
  1130. this.dmq1 = null;
  1131. this.coeff = null;
  1132. }
  1133. // Set the public key fields N and e from hex strings
  1134. function RSASetPublic(N,E) {
  1135. if(N != null && E != null && N.length > 0 && E.length > 0) {
  1136. this.n = parseBigInt(N,16);
  1137. this.e = parseInt(E,16);
  1138. }
  1139. else
  1140. uv_alert("Invalid RSA public key");
  1141. }
  1142. // Perform raw public operation on "x": return x^e (mod n)
  1143. function RSADoPublic(x) {
  1144. return x.modPowInt(this.e, this.n);
  1145. }
  1146. // Return the PKCS#1 RSA encryption of "text" as an even-length hex string
  1147. function RSAEncrypt(text) {
  1148. var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
  1149. if(m == null) return null;
  1150. var c = this.doPublic(m);
  1151. if(c == null) return null;
  1152. var h = c.toString(16);
  1153. if((h.length & 1) == 0) return h; else return "0" + h;
  1154. }
  1155. // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
  1156. //function RSAEncryptB64(text) {
  1157. // var h = this.encrypt(text);
  1158. // if(h) return hex2b64(h); else return null;
  1159. //}
  1160. // protected
  1161. RSAKey.prototype.doPublic = RSADoPublic;
  1162. // public
  1163. RSAKey.prototype.setPublic = RSASetPublic;
  1164. RSAKey.prototype.encrypt = RSAEncrypt;
  1165. //RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
  1166. //==================================================jsbn.js======================================================================//
  1167. // Copyright (c) 2005 Tom Wu
  1168. // All Rights Reserved.
  1169. // See "LICENSE" for details.
  1170. // Basic JavaScript BN library - subset useful for RSA encryption.
  1171. // Bits per digit
  1172. var dbits;
  1173. // JavaScript engine analysis
  1174. var canary = 0xdeadbeefcafe;
  1175. var j_lm = ((canary&0xffffff)==0xefcafe);
  1176. // (public) Constructor
  1177. function BigInteger(a,b,c) {
  1178. if(a != null)
  1179. if("number" == typeof a) this.fromNumber(a,b,c);
  1180. else if(b == null && "string" != typeof a) this.fromString(a,256);
  1181. else this.fromString(a,b);
  1182. }
  1183. // return new, unset BigInteger
  1184. function nbi() { return new BigInteger(null); }
  1185. // am: Compute w_j += (x*this_i), propagate carries,
  1186. // c is initial carry, returns final carry.
  1187. // c < 3*dvalue, x < 2*dvalue, this_i < dvalue
  1188. // We need to select the fastest one that works in this environment.
  1189. // am1: use a single mult and divide to get the high bits,
  1190. // max digit bits should be 26 because
  1191. // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
  1192. function am1(i,x,w,j,c,n) {
  1193. while(--n >= 0) {
  1194. var v = x*this[i++]+w[j]+c;
  1195. c = Math.floor(v/0x4000000);
  1196. w[j++] = v&0x3ffffff;
  1197. }
  1198. return c;
  1199. }
  1200. // am2 avoids a big mult-and-extract completely.
  1201. // Max digit bits should be <= 30 because we do bitwise ops
  1202. // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
  1203. function am2(i,x,w,j,c,n) {
  1204. var xl = x&0x7fff, xh = x>>15;
  1205. while(--n >= 0) {
  1206. var l = this[i]&0x7fff;
  1207. var h = this[i++]>>15;
  1208. var m = xh*l+h*xl;
  1209. l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
  1210. c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
  1211. w[j++] = l&0x3fffffff;
  1212. }
  1213. return c;
  1214. }
  1215. // Alternately, set max digit bits to 28 since some
  1216. // browsers slow down when dealing with 32-bit numbers.
  1217. function am3(i,x,w,j,c,n) {
  1218. var xl = x&0x3fff, xh = x>>14;
  1219. while(--n >= 0) {
  1220. var l = this[i]&0x3fff;
  1221. var h = this[i++]>>14;
  1222. var m = xh*l+h*xl;
  1223. l = xl*l+((m&0x3fff)<<14)+w[j]+c;
  1224. c = (l>>28)+(m>>14)+xh*h;
  1225. w[j++] = l&0xfffffff;
  1226. }
  1227. return c;
  1228. }
  1229. if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
  1230. BigInteger.prototype.am = am2;
  1231. dbits = 30;
  1232. }
  1233. else if(j_lm && (navigator.appName != "Netscape")) {
  1234. BigInteger.prototype.am = am1;
  1235. dbits = 26;
  1236. }
  1237. else { // Mozilla/Netscape seems to prefer am3
  1238. BigInteger.prototype.am = am3;
  1239. dbits = 28;
  1240. }
  1241. BigInteger.prototype.DB = dbits;
  1242. BigInteger.prototype.DM = ((1<<dbits)-1);
  1243. BigInteger.prototype.DV = (1<<dbits);
  1244. var BI_FP = 52;
  1245. BigInteger.prototype.FV = Math.pow(2,BI_FP);
  1246. BigInteger.prototype.F1 = BI_FP-dbits;
  1247. BigInteger.prototype.F2 = 2*dbits-BI_FP;
  1248. // Digit conversions
  1249. var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
  1250. var BI_RC = new Array();
  1251. var rr,vv;
  1252. rr = "0".charCodeAt(0);
  1253. for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
  1254. rr = "a".charCodeAt(0);
  1255. for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
  1256. rr = "A".charCodeAt(0);
  1257. for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
  1258. function int2char(n) { return BI_RM.charAt(n); }
  1259. function intAt(s,i) {
  1260. var c = BI_RC[s.charCodeAt(i)];
  1261. return (c==null)?-1:c;
  1262. }
  1263. // (protected) copy this to r
  1264. function bnpCopyTo(r) {
  1265. for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
  1266. r.t = this.t;
  1267. r.s = this.s;
  1268. }
  1269. // (protected) set from integer value x, -DV <= x < DV
  1270. function bnpFromInt(x) {
  1271. this.t = 1;
  1272. this.s = (x<0)?-1:0;
  1273. if(x > 0) this[0] = x;
  1274. else if(x < -1) this[0] = x+DV;
  1275. else this.t = 0;
  1276. }
  1277. // return bigint initialized to value
  1278. function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
  1279. // (protected) set from string and radix
  1280. function bnpFromString(s,b) {
  1281. var k;
  1282. if(b == 16) k = 4;
  1283. else if(b == 8) k = 3;
  1284. else if(b == 256) k = 8; // byte array
  1285. else if(b == 2) k = 1;
  1286. else if(b == 32) k = 5;
  1287. else if(b == 4) k = 2;
  1288. else { this.fromRadix(s,b); return; }
  1289. this.t = 0;
  1290. this.s = 0;
  1291. var i = s.length, mi = false, sh = 0;
  1292. while(--i >= 0) {
  1293. var x = (k==8)?s[i]&0xff:intAt(s,i);
  1294. if(x < 0) {
  1295. if(s.charAt(i) == "-") mi = true;
  1296. continue;
  1297. }
  1298. mi = false;
  1299. if(sh == 0)
  1300. this[this.t++] = x;
  1301. else if(sh+k > this.DB) {
  1302. this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
  1303. this[this.t++] = (x>>(this.DB-sh));
  1304. }
  1305. else
  1306. this[this.t-1] |= x<<sh;
  1307. sh += k;
  1308. if(sh >= this.DB) sh -= this.DB;
  1309. }
  1310. if(k == 8 && (s[0]&0x80) != 0) {
  1311. this.s = -1;
  1312. if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
  1313. }
  1314. this.clamp();
  1315. if(mi) BigInteger.ZERO.subTo(this,this);
  1316. }
  1317. // (protected) clamp off excess high words
  1318. function bnpClamp() {
  1319. var c = this.s&this.DM;
  1320. while(this.t > 0 && this[this.t-1] == c) --this.t;
  1321. }
  1322. // (public) return string representation in given radix
  1323. function bnToString(b) {
  1324. if(this.s < 0) return "-"+this.negate().toString(b);
  1325. var k;
  1326. if(b == 16) k = 4;
  1327. else if(b == 8) k = 3;
  1328. else if(b == 2) k = 1;
  1329. else if(b == 32) k = 5;
  1330. else if(b == 4) k = 2;
  1331. else return this.toRadix(b);
  1332. var km = (1<<k)-1, d, m = false, r = "", i = this.t;
  1333. var p = this.DB-(i*this.DB)%k;
  1334. if(i-- > 0) {
  1335. if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
  1336. while(i >= 0) {
  1337. if(p < k) {
  1338. d = (this[i]&((1<<p)-1))<<(k-p);
  1339. d |= this[--i]>>(p+=this.DB-k);
  1340. }
  1341. else {
  1342. d = (this[i]>>(p-=k))&km;
  1343. if(p <= 0) { p += this.DB; --i; }
  1344. }
  1345. if(d > 0) m = true;
  1346. if(m) r += int2char(d);
  1347. }
  1348. }
  1349. return m?r:"0";
  1350. }
  1351. // (public) -this
  1352. function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
  1353. // (public) |this|
  1354. function bnAbs() { return (this.s<0)?this.negate():this; }
  1355. // (public) return + if this > a, - if this < a, 0 if equal
  1356. function bnCompareTo(a) {
  1357. var r = this.s-a.s;
  1358. if(r != 0) return r;
  1359. var i = this.t;
  1360. r = i-a.t;
  1361. if(r != 0) return r;
  1362. while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
  1363. return 0;
  1364. }
  1365. // returns bit length of the integer x
  1366. function nbits(x) {
  1367. var r = 1, t;
  1368. if((t=x>>>16) != 0) { x = t; r += 16; }
  1369. if((t=x>>8) != 0) { x = t; r += 8; }
  1370. if((t=x>>4) != 0) { x = t; r += 4; }
  1371. if((t=x>>2) != 0) { x = t; r += 2; }
  1372. if((t=x>>1) != 0) { x = t; r += 1; }
  1373. return r;
  1374. }
  1375. // (public) return the number of bits in "this"
  1376. function bnBitLength() {
  1377. if(this.t <= 0) return 0;
  1378. return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
  1379. }
  1380. // (protected) r = this << n*DB
  1381. function bnpDLShiftTo(n,r) {
  1382. var i;
  1383. for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
  1384. for(i = n-1; i >= 0; --i) r[i] = 0;
  1385. r.t = this.t+n;
  1386. r.s = this.s;
  1387. }
  1388. // (protected) r = this >> n*DB
  1389. function bnpDRShiftTo(n,r) {
  1390. for(var i = n; i < this.t; ++i) r[i-n] = this[i];
  1391. r.t = Math.max(this.t-n,0);
  1392. r.s = this.s;
  1393. }
  1394. // (protected) r = this << n
  1395. function bnpLShiftTo(n,r) {
  1396. var bs = n%this.DB;
  1397. var cbs = this.DB-bs;
  1398. var bm = (1<<cbs)-1;
  1399. var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
  1400. for(i = this.t-1; i >= 0; --i) {
  1401. r[i+ds+1] = (this[i]>>cbs)|c;
  1402. c = (this[i]&bm)<<bs;
  1403. }
  1404. for(i = ds-1; i >= 0; --i) r[i] = 0;
  1405. r[ds] = c;
  1406. r.t = this.t+ds+1;
  1407. r.s = this.s;
  1408. r.clamp();
  1409. }
  1410. // (protected) r = this >> n
  1411. function bnpRShiftTo(n,r) {
  1412. r.s = this.s;
  1413. var ds = Math.floor(n/this.DB);
  1414. if(ds >= this.t) { r.t = 0; return; }
  1415. var bs = n%this.DB;
  1416. var cbs = this.DB-bs;
  1417. var bm = (1<<bs)-1;
  1418. r[0] = this[ds]>>bs;
  1419. for(var i = ds+1; i < this.t; ++i) {
  1420. r[i-ds-1] |= (this[i]&bm)<<cbs;
  1421. r[i-ds] = this[i]>>bs;
  1422. }
  1423. if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
  1424. r.t = this.t-ds;
  1425. r.clamp();
  1426. }
  1427. // (protected) r = this - a
  1428. function bnpSubTo(a,r) {
  1429. var i = 0, c = 0, m = Math.min(a.t,this.t);
  1430. while(i < m) {
  1431. c += this[i]-a[i];
  1432. r[i++] = c&this.DM;
  1433. c >>= this.DB;
  1434. }
  1435. if(a.t < this.t) {
  1436. c -= a.s;
  1437. while(i < this.t) {
  1438. c += this[i];
  1439. r[i++] = c&this.DM;
  1440. c >>= this.DB;
  1441. }
  1442. c += this.s;
  1443. }
  1444. else {
  1445. c += this.s;
  1446. while(i < a.t) {
  1447. c -= a[i];
  1448. r[i++] = c&this.DM;
  1449. c >>= this.DB;
  1450. }
  1451. c -= a.s;
  1452. }
  1453. r.s = (c<0)?-1:0;
  1454. if(c < -1) r[i++] = this.DV+c;
  1455. else if(c > 0) r[i++] = c;
  1456. r.t = i;
  1457. r.clamp();
  1458. }
  1459. // (protected) r = this * a, r != this,a (HAC 14.12)
  1460. // "this" should be the larger one if appropriate.
  1461. function bnpMultiplyTo(a,r) {
  1462. var x = this.abs(), y = a.abs();
  1463. var i = x.t;
  1464. r.t = i+y.t;
  1465. while(--i >= 0) r[i] = 0;
  1466. for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
  1467. r.s = 0;
  1468. r.clamp();
  1469. if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
  1470. }
  1471. // (protected) r = this^2, r != this (HAC 14.16)
  1472. function bnpSquareTo(r) {
  1473. var x = this.abs();
  1474. var i = r.t = 2*x.t;
  1475. while(--i >= 0) r[i] = 0;
  1476. for(i = 0; i < x.t-1; ++i) {
  1477. var c = x.am(i,x[i],r,2*i,0,1);
  1478. if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
  1479. r[i+x.t] -= x.DV;
  1480. r[i+x.t+1] = 1;
  1481. }
  1482. }
  1483. if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
  1484. r.s = 0;
  1485. r.clamp();
  1486. }
  1487. // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
  1488. // r != q, this != m. q or r may be null.
  1489. function bnpDivRemTo(m,q,r) {
  1490. var pm = m.abs();
  1491. if(pm.t <= 0) return;
  1492. var pt = this.abs();
  1493. if(pt.t < pm.t) {
  1494. if(q != null) q.fromInt(0);
  1495. if(r != null) this.copyTo(r);
  1496. return;
  1497. }
  1498. if(r == null) r = nbi();
  1499. var y = nbi(), ts = this.s, ms = m.s;
  1500. var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
  1501. if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
  1502. else { pm.copyTo(y); pt.copyTo(r); }
  1503. var ys = y.t;
  1504. var y0 = y[ys-1];
  1505. if(y0 == 0) return;
  1506. var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
  1507. var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
  1508. var i = r.t, j = i-ys, t = (q==null)?nbi():q;
  1509. y.dlShiftTo(j,t);
  1510. if(r.compareTo(t) >= 0) {
  1511. r[r.t++] = 1;
  1512. r.subTo(t,r);
  1513. }
  1514. BigInteger.ONE.dlShiftTo(ys,t);
  1515. t.subTo(y,y); // "negative" y so we can replace sub with am later
  1516. while(y.t < ys) y[y.t++] = 0;
  1517. while(--j >= 0) {
  1518. // Estimate quotient digit
  1519. var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
  1520. if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
  1521. y.dlShiftTo(j,t);
  1522. r.subTo(t,r);
  1523. while(r[i] < --qd) r.subTo(t,r);
  1524. }
  1525. }
  1526. if(q != null) {
  1527. r.drShiftTo(ys,q);
  1528. if(ts != ms) BigInteger.ZERO.subTo(q,q);
  1529. }
  1530. r.t = ys;
  1531. r.clamp();
  1532. if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
  1533. if(ts < 0) BigInteger.ZERO.subTo(r,r);
  1534. }
  1535. // (public) this mod a
  1536. function bnMod(a) {
  1537. var r = nbi();
  1538. this.abs().divRemTo(a,null,r);
  1539. if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
  1540. return r;
  1541. }
  1542. // Modular reduction using "classic" algorithm
  1543. function Classic(m) { this.m = m; }
  1544. function cConvert(x) {
  1545. if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
  1546. else return x;
  1547. }
  1548. function cRevert(x) { return x; }
  1549. function cReduce(x) { x.divRemTo(this.m,null,x); }
  1550. function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
  1551. function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
  1552. Classic.prototype.convert = cConvert;
  1553. Classic.prototype.revert = cRevert;
  1554. Classic.prototype.reduce = cReduce;
  1555. Classic.prototype.mulTo = cMulTo;
  1556. Classic.prototype.sqrTo = cSqrTo;
  1557. // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
  1558. // justification:
  1559. // xy == 1 (mod m)
  1560. // xy = 1+km
  1561. // xy(2-xy) = (1+km)(1-km)
  1562. // x[y(2-xy)] = 1-k^2m^2
  1563. // x[y(2-xy)] == 1 (mod m^2)
  1564. // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
  1565. // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
  1566. // JS multiply "overflows" differently from C/C++, so care is needed here.
  1567. function bnpInvDigit() {
  1568. if(this.t < 1) return 0;
  1569. var x = this[0];
  1570. if((x&1) == 0) return 0;
  1571. var y = x&3; // y == 1/x mod 2^2
  1572. y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
  1573. y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
  1574. y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
  1575. // last step - calculate inverse mod DV directly;
  1576. // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
  1577. y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
  1578. // we really want the negative inverse, and -DV < y < DV
  1579. return (y>0)?this.DV-y:-y;
  1580. }
  1581. // Montgomery reduction
  1582. function Montgomery(m) {
  1583. this.m = m;
  1584. this.mp = m.invDigit();
  1585. this.mpl = this.mp&0x7fff;
  1586. this.mph = this.mp>>15;
  1587. this.um = (1<<(m.DB-15))-1;
  1588. this.mt2 = 2*m.t;
  1589. }
  1590. // xR mod m
  1591. function montConvert(x) {
  1592. var r = nbi();
  1593. x.abs().dlShiftTo(this.m.t,r);
  1594. r.divRemTo(this.m,null,r);
  1595. if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
  1596. return r;
  1597. }
  1598. // x/R mod m
  1599. function montRevert(x) {
  1600. var r = nbi();
  1601. x.copyTo(r);
  1602. this.reduce(r);
  1603. return r;
  1604. }
  1605. // x = x/R mod m (HAC 14.32)
  1606. function montReduce(x) {
  1607. while(x.t <= this.mt2) // pad x so am has enough room later
  1608. x[x.t++] = 0;
  1609. for(var i = 0; i < this.m.t; ++i) {
  1610. // faster way of calculating u0 = x[i]*mp mod DV
  1611. var j = x[i]&0x7fff;
  1612. var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
  1613. // use am to combine the multiply-shift-add into one call
  1614. j = i+this.m.t;
  1615. x[j] += this.m.am(0,u0,x,i,0,this.m.t);
  1616. // propagate carry
  1617. while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
  1618. }
  1619. x.clamp();
  1620. x.drShiftTo(this.m.t,x);
  1621. if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
  1622. }
  1623. // r = "x^2/R mod m"; x != r
  1624. function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
  1625. // r = "xy/R mod m"; x,y != r
  1626. function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
  1627. Montgomery.prototype.convert = montConvert;
  1628. Montgomery.prototype.revert = montRevert;
  1629. Montgomery.prototype.reduce = montReduce;
  1630. Montgomery.prototype.mulTo = montMulTo;
  1631. Montgomery.prototype.sqrTo = montSqrTo;
  1632. // (protected) true iff this is even
  1633. function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
  1634. // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
  1635. function bnpExp(e,z) {
  1636. if(e > 0xffffffff || e < 1) return BigInteger.ONE;
  1637. var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
  1638. g.copyTo(r);
  1639. while(--i >= 0) {
  1640. z.sqrTo(r,r2);
  1641. if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
  1642. else { var t = r; r = r2; r2 = t; }
  1643. }
  1644. return z.revert(r);
  1645. }
  1646. // (public) this^e % m, 0 <= e < 2^32
  1647. function bnModPowInt(e,m) {
  1648. var z;
  1649. if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
  1650. return this.exp(e,z);
  1651. }
  1652. // protected
  1653. BigInteger.prototype.copyTo = bnpCopyTo;
  1654. BigInteger.prototype.fromInt = bnpFromInt;
  1655. BigInteger.prototype.fromString = bnpFromString;
  1656. BigInteger.prototype.clamp = bnpClamp;
  1657. BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
  1658. BigInteger.prototype.drShiftTo = bnpDRShiftTo;
  1659. BigInteger.prototype.lShiftTo = bnpLShiftTo;
  1660. BigInteger.prototype.rShiftTo = bnpRShiftTo;
  1661. BigInteger.prototype.subTo = bnpSubTo;
  1662. BigInteger.prototype.multiplyTo = bnpMultiplyTo;
  1663. BigInteger.prototype.squareTo = bnpSquareTo;
  1664. BigInteger.prototype.divRemTo = bnpDivRemTo;
  1665. BigInteger.prototype.invDigit = bnpInvDigit;
  1666. BigInteger.prototype.isEven = bnpIsEven;
  1667. BigInteger.prototype.exp = bnpExp;
  1668. // public
  1669. BigInteger.prototype.toString = bnToString;
  1670. BigInteger.prototype.negate = bnNegate;
  1671. BigInteger.prototype.abs = bnAbs;
  1672. BigInteger.prototype.compareTo = bnCompareTo;
  1673. BigInteger.prototype.bitLength = bnBitLength;
  1674. BigInteger.prototype.mod = bnMod;
  1675. BigInteger.prototype.modPowInt = bnModPowInt;
  1676. // "constants"
  1677. BigInteger.ZERO = nbv(0);
  1678. BigInteger.ONE = nbv(1);
  1679. //====================================================rng.js===================================================================//
  1680. // Random number generator - requires a PRNG backend, e.g. prng4.js
  1681. // For best results, put code like
  1682. // <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
  1683. // in your main HTML document.
  1684. var rng_state;
  1685. var rng_pool;
  1686. var rng_pptr;
  1687. // Mix in a 32-bit integer into the pool
  1688. function rng_seed_int(x) {
  1689. rng_pool[rng_pptr++] ^= x & 255;
  1690. rng_pool[rng_pptr++] ^= (x >> 8) & 255;
  1691. rng_pool[rng_pptr++] ^= (x >> 16) & 255;
  1692. rng_pool[rng_pptr++] ^= (x >> 24) & 255;
  1693. if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
  1694. }
  1695. // Mix in the current time (w/milliseconds) into the pool
  1696. function rng_seed_time() {
  1697. rng_seed_int(new Date().getTime());
  1698. }
  1699. // Initialize the pool with junk if needed.
  1700. if(rng_pool == null) {
  1701. rng_pool = new Array();
  1702. rng_pptr = 0;
  1703. var t;
  1704. if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto && window.crypto.random) {
  1705. // Extract entropy (256 bits) from NS4 RNG if available
  1706. var z = window.crypto.random(32);
  1707. for(t = 0; t < z.length; ++t)
  1708. rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
  1709. }
  1710. while(rng_pptr < rng_psize) { // extract some randomness from Math.random()
  1711. t = Math.floor(65536 * Math.random());
  1712. rng_pool[rng_pptr++] = t >>> 8;
  1713. rng_pool[rng_pptr++] = t & 255;
  1714. }
  1715. rng_pptr = 0;
  1716. rng_seed_time();
  1717. //rng_seed_int(window.screenX);
  1718. //rng_seed_int(window.screenY);
  1719. }
  1720. function rng_get_byte() {
  1721. if(rng_state == null) {
  1722. rng_seed_time();
  1723. rng_state = prng_newstate();
  1724. rng_state.init(rng_pool);
  1725. for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
  1726. rng_pool[rng_pptr] = 0;
  1727. rng_pptr = 0;
  1728. //rng_pool = null;
  1729. }
  1730. // TODO: allow reseeding after first request
  1731. return rng_state.next();
  1732. }
  1733. function rng_get_bytes(ba) {
  1734. var i;
  1735. for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
  1736. }
  1737. function SecureRandom() {}
  1738. SecureRandom.prototype.nextBytes = rng_get_bytes;
  1739. //===============================================prng4==========================================================================//
  1740. // prng4.js - uses Arcfour as a PRNG
  1741. function Arcfour() {
  1742. this.i = 0;
  1743. this.j = 0;
  1744. this.S = new Array();
  1745. }
  1746. // Initialize arcfour context from key, an array of ints, each from [0..255]
  1747. function ARC4init(key) {
  1748. var i, j, t;
  1749. for(i = 0; i < 256; ++i)
  1750. this.S[i] = i;
  1751. j = 0;
  1752. for(i = 0; i < 256; ++i) {
  1753. j = (j + this.S[i] + key[i % key.length]) & 255;
  1754. t = this.S[i];
  1755. this.S[i] = this.S[j];
  1756. this.S[j] = t;
  1757. }
  1758. this.i = 0;
  1759. this.j = 0;
  1760. }
  1761. function ARC4next() {
  1762. var t;
  1763. this.i = (this.i + 1) & 255;
  1764. this.j = (this.j + this.S[this.i]) & 255;
  1765. t = this.S[this.i];
  1766. this.S[this.i] = this.S[this.j];
  1767. this.S[this.j] = t;
  1768. return this.S[(t + this.S[this.i]) & 255];
  1769. }
  1770. Arcfour.prototype.init = ARC4init;
  1771. Arcfour.prototype.next = ARC4next;
  1772. // Plug in your RNG constructor here
  1773. function prng_newstate() {
  1774. return new Arcfour();
  1775. }
  1776. // Pool size must be a multiple of 4 and greater than 32.
  1777. // An array of bytes the size of the pool will be passed to init()
  1778. var rng_psize = 256;
  1779. //rsa加密
  1780. function rsa_encrypt(rawValue,key,mod){
  1781. //公钥
  1782. key
  1783. = "e9a815ab9d6e86abbf33a4ac64e9196d5be44a09bd0ed6ae052914e1a865ac8331fed863de8ea697e9a7f63329e5e23cda09c72570f46775b7e39ea9670086f847d3c9c51963b131409b1e04265d9747419c635404ca651bbcbc87f99b8008f7f5824653e3658be4ba73e4480156b390bb73bc1f8b33578e7a4e12440e9396f2552c1aff1c92e797ebacdc37c109ab7bce2367a19c56a033ee04534723cc2558cb27368f5b9d32c04d12dbd86bbd68b1d99b7c349a8453ea75d1b2e94491ab30acf6c46a36a75b721b312bedf4e7aad21e54e9bcbcf8144c79b6e3c05eb4a1547750d224c0085d80e6da3907c3d945051c13c7c1dcefd6520ee8379c4f5231ed";
  1784. mod="10001";
  1785. var _RSA = new RSAKey();//生成rsa加密对象
  1786. _RSA.setPublic(key, mod);//设置公钥和mod,PublicKey是1(2)中打印的hex值
  1787. return _RSA.encrypt(rawValue);
  1788. };
  1789. return {
  1790. rsa_encrypt:rsa_encrypt
  1791. }
  1792. }();
  1793. (function(global) {
  1794. /*
  1795. 此加密算法是一个16次的迭代过程,并且是反馈的,每一个加密单元是8字节,输出也是8字节,密钥是16字节
  1796. 我们以prePlain表示前一个明文块,plain表示当前明文块,crypt表示当前明文块加密得到的密文块,preCrypt表示前一个密文块 f表示加密算法,d表示解密算法
  1797. 那么从plain得到crypt的过程是: crypt = f(plain ^ preCrypt) ^ prePlain
  1798. 所以,从crypt得到plain的过程自然是 plain = d(crypt ^ prePlain) ^ preCrypt
  1799. 此外,算法有它的填充机制,其会在明文前和明文后分别填充一定的字节数,以保证明文长度是8字节的倍数 填充的字节数与原始明文长度有关,填充的方法是:
  1800. ------- 消息填充算法 -----------
  1801. a = (明文长度 + 10) mod 8
  1802. if(a 不等于 0) a = 8 - a;
  1803. b = 随机数 & 0xF8 | a; 这个的作用是把a的值保存了下来, a的值小于8
  1804. plain[0] = b; 然后把b做为明文的第0个字节,这样第0个字节就保存了a的信息,这个信息在解密时就要用来找到真正明文的起始位置
  1805. plain[1..a+2] = 随机数 & 0xFF; 这里用随机数填充明文的第1到第a+2个字节
  1806. plain[a+3..a+3+明文长度-1] = 明文; 从a+3字节开始才是真正的明文
  1807. plain[a+3+明文长度, 最后] = 0; 在最后,填充0,填充到总长度为8的整数为止。到此为止,结束了,这就是最后得到的要加密的明文内容
  1808. ------- 消息填充算法 ------------
  1809. @author 马若劼
  1810. @author notXX
  1811. @author 唐浩宸
  1812. */
  1813. var __key = '',
  1814. __pos = 0,
  1815. __plain = [],
  1816. __prePlain = [],
  1817. __cryptPos = 0, // 当前密文块位置
  1818. __preCryptPos = 0, // 上一个密文块位置
  1819. __out = [], // 保存加密/解密的输出
  1820. __cipher = [], // 输出的密文
  1821. /*用于加密时,表示当前是否是第一个8字节块,因为加密算法是反馈的,
  1822. 但是最开始的8个字节没有反馈可用,所有需要标明这种情况*/
  1823. __header = true;
  1824. function __rand() {
  1825. return Math.round(Math.random()*0xffffffff);
  1826. }
  1827. /**
  1828. * 将数据转化为无符号整形
  1829. */
  1830. function __getUInt(data, offset, len) {
  1831. if (!len || len > 4)
  1832. len = 4;
  1833. var ret = 0;
  1834. for (var i=offset; i<offset+len; i++) {
  1835. ret <<= 8;
  1836. ret |= data[i];
  1837. }
  1838. return (ret & 0xffffffff) >>> 0; // 无符号化
  1839. }
  1840. /**
  1841. 把整形数据填充到数组里,要注意端序
  1842. */
  1843. function __intToBytes(data, offset, value) {
  1844. data[offset+3] = (value >> 0) & 0xff;
  1845. data[offset+2] = (value >> 8) & 0xff;
  1846. data[offset+1] = (value >> 16) & 0xff;
  1847. data[offset+0] = (value >> 24) & 0xff;
  1848. }
  1849. function __bytesInStr(data) {
  1850. if (!data) return "";
  1851. var outInHex = "";
  1852. for (var i=0; i<data.length; i++) {
  1853. var hex = Number(data[i]).toString(16);
  1854. if (hex.length == 1)
  1855. hex = "0" + hex;
  1856. outInHex += hex;
  1857. }
  1858. return outInHex;
  1859. }
  1860. function __bytesToStr(data) {
  1861. var str = "";
  1862. for (var i=0; i<data.length; i+=2) // 输入的16进制字符串
  1863. str += String.fromCharCode(parseInt(data.substr(i, 2), 16));
  1864. return str;
  1865. }
  1866. function __strToBytes(str, unicode) {
  1867. if (!str) return "";
  1868. if (unicode) str = utf16ToUtf8(str);
  1869. var data = [];
  1870. for (var i=0; i<str.length; i++)
  1871. data[i] = str.charCodeAt(i);
  1872. return __bytesInStr(data);
  1873. }
  1874. //UTF-16转UTF-8
  1875. function utf16ToUtf8(s){
  1876. var i, code, ret = [], len = s.length;
  1877. for(i = 0; i < len; i++){
  1878. code = s.charCodeAt(i);
  1879. if(code > 0x0 && code <= 0x7f){
  1880. //单字节
  1881. //UTF-16 0000 - 007F
  1882. //UTF-8 0xxxxxxx
  1883. ret.push(s.charAt(i));
  1884. }else if(code >= 0x80 && code <= 0x7ff){
  1885. //双字节
  1886. //UTF-16 0080 - 07FF
  1887. //UTF-8 110xxxxx 10xxxxxx
  1888. ret.push(
  1889. //110xxxxx
  1890. String.fromCharCode(0xc0 | ((code >> 6) & 0x1f)),
  1891. //10xxxxxx
  1892. String.fromCharCode(0x80 | (code & 0x3f))
  1893. );
  1894. }else if(code >= 0x800 && code <= 0xffff){
  1895. //三字节
  1896. //UTF-16 0800 - FFFF
  1897. //UTF-8 1110xxxx 10xxxxxx 10xxxxxx
  1898. ret.push(
  1899. //1110xxxx
  1900. String.fromCharCode(0xe0 | ((code >> 12) & 0xf)),
  1901. //10xxxxxx
  1902. String.fromCharCode(0x80 | ((code >> 6) & 0x3f)),
  1903. //10xxxxxx
  1904. String.fromCharCode(0x80 | (code & 0x3f))
  1905. );
  1906. }
  1907. }
  1908. return ret.join('');
  1909. }
  1910. function __encrypt(data) {
  1911. __plain = new Array(8);
  1912. __prePlain = new Array(8);
  1913. __cryptPos = __preCryptPos = 0;
  1914. __header = true;
  1915. __pos = 0;
  1916. var len = data.length;
  1917. var padding = 0;
  1918. __pos = (len + 0x0A) % 8;
  1919. if (__pos != 0)
  1920. __pos = 8 - __pos;
  1921. __out = new Array(len + __pos + 10);
  1922. __plain[0] = ((__rand() & 0xF8) | __pos ) & 0xFF;
  1923. for (var i=1; i<=__pos; i++)
  1924. __plain[i] = __rand() & 0xFF;
  1925. __pos++;
  1926. for (var i=0; i<8; i++)
  1927. __prePlain[i] = 0;
  1928. padding = 1;
  1929. while (padding <= 2) {
  1930. if (__pos < 8) {
  1931. __plain[__pos++] = __rand() & 0xFF;
  1932. padding++;
  1933. }
  1934. if (__pos == 8)
  1935. __encrypt8bytes();
  1936. }
  1937. var i = 0;
  1938. while (len > 0) {
  1939. if (__pos < 8) {
  1940. __plain[__pos++] = data[i++];
  1941. len--;
  1942. }
  1943. if (__pos == 8)
  1944. __encrypt8bytes();
  1945. }
  1946. padding = 1;
  1947. while (padding <= 7) {
  1948. if (__pos < 8) {
  1949. __plain[__pos++] = 0;
  1950. padding++;
  1951. }
  1952. if (__pos == 8)
  1953. __encrypt8bytes();
  1954. }
  1955. return __out;
  1956. }
  1957. function __decrypt(data) {
  1958. var count = 0;
  1959. var m = new Array(8);
  1960. var len = data.length;
  1961. __cipher = data;
  1962. if (len % 8 != 0 || len < 16)
  1963. return null;
  1964. /* 第一个8字节,加密的时候因为prePlain是全0,所以可以直接解密,得到消息的头部,
  1965. 关键是可以得到真正明文开始的位置
  1966. */
  1967. __prePlain = __decipher(data);
  1968. __pos = __prePlain[0] & 0x7;
  1969. count = len - __pos - 10; // 真正的明文长度
  1970. if (count < 0)
  1971. return null;
  1972. // 临时的preCrypt, 与加密时对应,全0的prePlain 对应 全0的preCrypt
  1973. for (var i=0; i<m.length; i++)
  1974. m[i] = 0;
  1975. __out = new Array(count);
  1976. __preCryptPos = 0;
  1977. __cryptPos = 8; // 头部已经解密过,所以是8
  1978. __pos++; // 与解密过程对应,+1
  1979. /* 开始跳过头部,如果在这个过程中满了8字节,则解密下一块
  1980. 因为是解密下一块,所以我们有一个语句 m = data,下一块当然有preCrypt了,我们不再用m了
  1981. 但是如果不满8,这说明了什么?说明了头8个字节的密文是包含了明文信息的,当然还是要用m把明文弄出来
  1982. 所以,很显然,满了8的话,说明了头8个字节的密文除了一个长度信息有用之外,其他都是无用的填充*/
  1983. var padding = 1;
  1984. while (padding <= 2) {
  1985. if (__pos < 8) {
  1986. __pos++;
  1987. padding++;
  1988. }
  1989. if (__pos == 8) {
  1990. m = data;
  1991. if (!__decrypt8Bytes())
  1992. return null;
  1993. }
  1994. }
  1995. /* 这里是解密的重要阶段,这个时候头部的填充都已经跳过了,开始解密
  1996. 注意如果上面一个while没有满8,这里第一个if里面用的就是原始的m,否则这个m就是data了*/
  1997. var i=0;
  1998. while (count != 0) {
  1999. if (__pos < 8) {
  2000. __out[i] = (m[__preCryptPos + __pos] ^ __prePlain[__pos]) & 0xff;
  2001. i++;
  2002. count--;
  2003. __pos++;
  2004. }
  2005. if (__pos == 8) {
  2006. m = data;
  2007. __preCryptPos = __cryptPos - 8;
  2008. if (!__decrypt8Bytes())
  2009. return null;
  2010. }
  2011. }
  2012. /*
  2013. 明文已经解密完毕了,到这里剩下的只有尾部的填充,应该全是0,如果解密后非0,即出错了,返回null
  2014. */
  2015. for (padding=1; padding<8; padding++) {
  2016. if (__pos < 8) {
  2017. if ((m[__preCryptPos + __pos] ^ __prePlain[__pos]) != 0)
  2018. return null;
  2019. __pos++;
  2020. }
  2021. if (__pos == 8) {
  2022. m = data;
  2023. __preCryptPos = __cryptPos;
  2024. if (!__decrypt8Bytes())
  2025. return null;
  2026. }
  2027. }
  2028. return __out;
  2029. }
  2030. function __encrypt8bytes() {
  2031. for (var i=0; i<8; i++) {
  2032. if (__header)
  2033. __plain[i] ^= __prePlain[i];
  2034. else
  2035. __plain[i] ^= __out[__preCryptPos + i];
  2036. }
  2037. var crypted = __encipher(__plain);
  2038. for (var i=0; i<8; i++) {
  2039. __out[__cryptPos+i] = crypted[i] ^ __prePlain[i];
  2040. __prePlain[i] = __plain[i];
  2041. }
  2042. __preCryptPos = __cryptPos;
  2043. __cryptPos += 8;
  2044. __pos = 0;
  2045. __header = false;
  2046. }
  2047. function __encipher(data) {
  2048. var loop = 16;
  2049. var y = __getUInt(data, 0, 4);
  2050. var z = __getUInt(data, 4, 4);
  2051. var a = __getUInt(__key, 0, 4);
  2052. var b = __getUInt(__key, 4, 4);
  2053. var c = __getUInt(__key, 8, 4);
  2054. var d = __getUInt(__key, 12, 4);
  2055. var sum = 0;
  2056. var delta = 0x9E3779B9 >>> 0;
  2057. while (loop-- > 0) {
  2058. sum += delta;
  2059. sum = (sum & 0xFFFFFFFF) >>> 0;
  2060. y += ((z << 4) + a) ^ (z + sum) ^ ((z >>> 5) + b);
  2061. y = (y & 0xFFFFFFFF) >>> 0;
  2062. z += ((y << 4) + c) ^ (y + sum) ^ ((y >>> 5) + d);
  2063. z = (z & 0xFFFFFFFF) >>> 0;
  2064. }
  2065. var bytes = new Array(8);
  2066. __intToBytes(bytes, 0, y);
  2067. __intToBytes(bytes, 4, z);
  2068. return bytes;
  2069. }
  2070. function __decipher(data) {
  2071. var loop = 16;
  2072. var y = __getUInt(data, 0, 4);
  2073. var z = __getUInt(data, 4, 4);
  2074. var a = __getUInt(__key, 0, 4);
  2075. var b = __getUInt(__key, 4, 4);
  2076. var c = __getUInt(__key, 8, 4);
  2077. var d = __getUInt(__key, 12, 4);
  2078. var sum = 0xE3779B90 >>> 0;
  2079. var delta = 0x9E3779B9 >>> 0;
  2080. while (loop-- > 0) {
  2081. z -= ((y << 4) + c) ^ (y + sum) ^ ((y >>> 5) + d);
  2082. z = (z & 0xFFFFFFFF) >>> 0;
  2083. y -= ((z << 4) + a) ^ (z + sum) ^ ((z >>> 5) + b);
  2084. y = (y & 0xFFFFFFFF) >>> 0;
  2085. sum -= delta;
  2086. sum = (sum & 0xFFFFFFFF) >>> 0;
  2087. }
  2088. var bytes = new Array(8);
  2089. __intToBytes(bytes, 0, y);
  2090. __intToBytes(bytes, 4, z);
  2091. return bytes;
  2092. }
  2093. function __decrypt8Bytes() {
  2094. var len = __cipher.length;
  2095. for (var i=0; i<8; i++) {
  2096. __prePlain[i] ^= __cipher[__cryptPos + i];
  2097. }
  2098. __prePlain = __decipher(__prePlain);
  2099. __cryptPos += 8;
  2100. __pos = 0;
  2101. return true;
  2102. }
  2103. /**
  2104. * 把输入字符串转换为javascript array
  2105. */
  2106. function __dataFromStr(str, isASCII) {
  2107. var data = [];
  2108. if (isASCII) {
  2109. for (var i=0; i<str.length; i++)
  2110. data[i] = str.charCodeAt(i) & 0xff;
  2111. } else {
  2112. var k = 0;
  2113. for (var i=0; i<str.length; i+=2) // 输入的16进制字符串
  2114. data[k++] = parseInt(str.substr(i, 2), 16);
  2115. }
  2116. return data;
  2117. }
  2118. global.TEA = {
  2119. encrypt: function(str, isASCII) {
  2120. var data = __dataFromStr(str, isASCII);
  2121. var encrypted = __encrypt(data);
  2122. return __bytesInStr(encrypted);
  2123. },
  2124. enAsBase64: function(str, isASCII) { // output base64 encoded
  2125. var data = __dataFromStr(str, isASCII);
  2126. var encrypted = __encrypt(data);
  2127. var bytes = "";
  2128. for (var i=0; i<encrypted.length; i++)
  2129. bytes += String.fromCharCode(encrypted[i]);
  2130. return btoa(bytes);
  2131. },
  2132. decrypt: function(str) {
  2133. var data = __dataFromStr(str, false);
  2134. var decrypted = __decrypt(data);
  2135. return __bytesInStr(decrypted);
  2136. },
  2137. initkey: function(key, isASCII) {
  2138. __key = __dataFromStr(key, isASCII);
  2139. },
  2140. bytesToStr: __bytesToStr,
  2141. strToBytes: __strToBytes,
  2142. bytesInStr: __bytesInStr,
  2143. dataFromStr: __dataFromStr
  2144. };
  2145. /**
  2146. * base64 兼容window.btoa window.atob
  2147. * if (!window.btoa) window.btoa = base64.encode
  2148. * if (!window.atob) window.atob = base64.decode
  2149. */
  2150. var base64 = {};
  2151. base64.PADCHAR = '=';
  2152. base64.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  2153. /*
  2154. base64.getbyte64 = function(s,i) {
  2155. // This is oddly fast, except on Chrome/V8.
  2156. // Minimal or no improvement in performance by using a
  2157. // object with properties mapping chars to value (eg. 'A': 0)
  2158. var idx = base64.ALPHA.indexOf(s.charAt(i));
  2159. if (idx == -1) {
  2160. throw "Cannot decode base64";
  2161. }
  2162. return idx;
  2163. }
  2164. base64.decode = function(s) {
  2165. // convert to string
  2166. s = "" + s;
  2167. var getbyte64 = base64.getbyte64;
  2168. var pads, i, b10;
  2169. var imax = s.length
  2170. if (imax == 0) {
  2171. return s;
  2172. }
  2173. if (imax % 4 != 0) {
  2174. throw "Cannot decode base64";
  2175. }
  2176. pads = 0
  2177. if (s.charAt(imax -1) == base64.PADCHAR) {
  2178. pads = 1;
  2179. if (s.charAt(imax -2) == base64.PADCHAR) {
  2180. pads = 2;
  2181. }
  2182. // either way, we want to ignore this last block
  2183. imax -= 4;
  2184. }
  2185. var x = [];
  2186. for (i = 0; i < imax; i += 4) {
  2187. b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) |
  2188. (getbyte64(s,i+2) << 6) | getbyte64(s,i+3);
  2189. x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff));
  2190. }
  2191. switch (pads) {
  2192. case 1:
  2193. b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6)
  2194. x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff));
  2195. break;
  2196. case 2:
  2197. b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12);
  2198. x.push(String.fromCharCode(b10 >> 16));
  2199. break;
  2200. }
  2201. return x.join('');
  2202. }
  2203. */
  2204. base64.getbyte = function(s,i) {
  2205. var x = s.charCodeAt(i);
  2206. if (x > 255) {
  2207. throw "INVALID_CHARACTER_ERR: DOM Exception 5";
  2208. }
  2209. return x;
  2210. }
  2211. base64.encode = function(s) {
  2212. if (arguments.length != 1) {
  2213. throw "SyntaxError: Not enough arguments";
  2214. }
  2215. var padchar = base64.PADCHAR;
  2216. var alpha = base64.ALPHA;
  2217. var getbyte = base64.getbyte;
  2218. var i, b10;
  2219. var x = [];
  2220. // convert to string
  2221. s = "" + s;
  2222. var imax = s.length - s.length % 3;
  2223. if (s.length == 0) {
  2224. return s;
  2225. }
  2226. for (i = 0; i < imax; i += 3) {
  2227. b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8) | getbyte(s,i+2);
  2228. x.push(alpha.charAt(b10 >> 18));
  2229. x.push(alpha.charAt((b10 >> 12) & 0x3F));
  2230. x.push(alpha.charAt((b10 >> 6) & 0x3f));
  2231. x.push(alpha.charAt(b10 & 0x3f));
  2232. }
  2233. switch (s.length - imax) {
  2234. case 1:
  2235. b10 = getbyte(s,i) << 16;
  2236. x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
  2237. padchar + padchar);
  2238. break;
  2239. case 2:
  2240. b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8);
  2241. x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
  2242. alpha.charAt((b10 >> 6) & 0x3f) + padchar);
  2243. break;
  2244. }
  2245. return x.join('');
  2246. }
  2247. if (!window.btoa) window.btoa = base64.encode;
  2248. //if (!window.atob) window.atob = base64.decode;
  2249. })(window);
  2250. $ = window.$ || {};
  2251. $pt = window.$pt || {}; // login_div 被嵌在其它页面中,有可能$被覆盖
  2252. $.Encryption = $pt.Encryption=function(){
  2253. /********************************************
  2254. *
  2255. * 加密及算法相关,算法这个地方,很多函数可能没用,看微博的测试结果再处理。
  2256. *
  2257. *******************************************/
  2258. var hexcase = 1;
  2259. var b64pad = "";
  2260. var chrsz = 8;
  2261. var mode = 32;
  2262. function md5(s){
  2263. return hex_md5(s);
  2264. }
  2265. function hex_md5(s){
  2266. return binl2hex(core_md5(str2binl(s), s.length * chrsz));
  2267. }
  2268. function str_md5(s){
  2269. return binl2str(core_md5(str2binl(s), s.length * chrsz));
  2270. }
  2271. function hex_hmac_md5(key, data){
  2272. return binl2hex(core_hmac_md5(key, data));
  2273. }
  2274. function b64_hmac_md5(key, data){
  2275. return binl2b64(core_hmac_md5(key, data));
  2276. }
  2277. function str_hmac_md5(key, data){
  2278. return binl2str(core_hmac_md5(key, data));
  2279. }
  2280. //function md5_vm_test()//此方法只是测试是否运行正常
  2281. //{
  2282. // return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
  2283. //}
  2284. function core_md5(x, len){
  2285. x[len >> 5] |= 0x80 << ((len) % 32);
  2286. x[(((len + 64) >>> 9) << 4) + 14] = len;
  2287. var a = 1732584193;
  2288. var b = - 271733879;
  2289. var c = - 1732584194;
  2290. var d = 271733878;
  2291. for (var i = 0; i < x.length; i += 16) {
  2292. var olda = a;
  2293. var oldb = b;
  2294. var oldc = c;
  2295. var oldd = d;
  2296. a = md5_ff(a, b, c, d, x[i + 0], 7, - 680876936);
  2297. d = md5_ff(d, a, b, c, x[i + 1], 12, - 389564586);
  2298. c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
  2299. b = md5_ff(b, c, d, a, x[i + 3], 22, - 1044525330);
  2300. a = md5_ff(a, b, c, d, x[i + 4], 7, - 176418897);
  2301. d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
  2302. c = md5_ff(c, d, a, b, x[i + 6], 17, - 1473231341);
  2303. b = md5_ff(b, c, d, a, x[i + 7], 22, - 45705983);
  2304. a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
  2305. d = md5_ff(d, a, b, c, x[i + 9], 12, - 1958414417);
  2306. c = md5_ff(c, d, a, b, x[i + 10], 17, - 42063);
  2307. b = md5_ff(b, c, d, a, x[i + 11], 22, - 1990404162);
  2308. a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
  2309. d = md5_ff(d, a, b, c, x[i + 13], 12, - 40341101);
  2310. c = md5_ff(c, d, a, b, x[i + 14], 17, - 1502002290);
  2311. b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
  2312. a = md5_gg(a, b, c, d, x[i + 1], 5, - 165796510);
  2313. d = md5_gg(d, a, b, c, x[i + 6], 9, - 1069501632);
  2314. c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
  2315. b = md5_gg(b, c, d, a, x[i + 0], 20, - 373897302);
  2316. a = md5_gg(a, b, c, d, x[i + 5], 5, - 701558691);
  2317. d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
  2318. c = md5_gg(c, d, a, b, x[i + 15], 14, - 660478335);
  2319. b = md5_gg(b, c, d, a, x[i + 4], 20, - 405537848);
  2320. a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
  2321. d = md5_gg(d, a, b, c, x[i + 14], 9, - 1019803690);
  2322. c = md5_gg(c, d, a, b, x[i + 3], 14, - 187363961);
  2323. b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
  2324. a = md5_gg(a, b, c, d, x[i + 13], 5, - 1444681467);
  2325. d = md5_gg(d, a, b, c, x[i + 2], 9, - 51403784);
  2326. c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
  2327. b = md5_gg(b, c, d, a, x[i + 12], 20, - 1926607734);
  2328. a = md5_hh(a, b, c, d, x[i + 5], 4, - 378558);
  2329. d = md5_hh(d, a, b, c, x[i + 8], 11, - 2022574463);
  2330. c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
  2331. b = md5_hh(b, c, d, a, x[i + 14], 23, - 35309556);
  2332. a = md5_hh(a, b, c, d, x[i + 1], 4, - 1530992060);
  2333. d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
  2334. c = md5_hh(c, d, a, b, x[i + 7], 16, - 155497632);
  2335. b = md5_hh(b, c, d, a, x[i + 10], 23, - 1094730640);
  2336. a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
  2337. d = md5_hh(d, a, b, c, x[i + 0], 11, - 358537222);
  2338. c = md5_hh(c, d, a, b, x[i + 3], 16, - 722521979);
  2339. b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
  2340. a = md5_hh(a, b, c, d, x[i + 9], 4, - 640364487);
  2341. d = md5_hh(d, a, b, c, x[i + 12], 11, - 421815835);
  2342. c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
  2343. b = md5_hh(b, c, d, a, x[i + 2], 23, - 995338651);
  2344. a = md5_ii(a, b, c, d, x[i + 0], 6, - 198630844);
  2345. d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
  2346. c = md5_ii(c, d, a, b, x[i + 14], 15, - 1416354905);
  2347. b = md5_ii(b, c, d, a, x[i + 5], 21, - 57434055);
  2348. a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
  2349. d = md5_ii(d, a, b, c, x[i + 3], 10, - 1894986606);
  2350. c = md5_ii(c, d, a, b, x[i + 10], 15, - 1051523);
  2351. b = md5_ii(b, c, d, a, x[i + 1], 21, - 2054922799);
  2352. a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
  2353. d = md5_ii(d, a, b, c, x[i + 15], 10, - 30611744);
  2354. c = md5_ii(c, d, a, b, x[i + 6], 15, - 1560198380);
  2355. b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
  2356. a = md5_ii(a, b, c, d, x[i + 4], 6, - 145523070);
  2357. d = md5_ii(d, a, b, c, x[i + 11], 10, - 1120210379);
  2358. c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
  2359. b = md5_ii(b, c, d, a, x[i + 9], 21, - 343485551);
  2360. a = safe_add(a, olda);
  2361. b = safe_add(b, oldb);
  2362. c = safe_add(c, oldc);
  2363. d = safe_add(d, oldd);
  2364. }
  2365. if (mode == 16) {
  2366. return Array(b, c);
  2367. }else{
  2368. return Array(a, b, c, d);
  2369. }
  2370. }
  2371. function md5_cmn(q, a, b, x, s, t){
  2372. return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
  2373. }
  2374. function md5_ff(a, b, c, d, x, s, t){
  2375. return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
  2376. }
  2377. function md5_gg(a, b, c, d, x, s, t){
  2378. return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
  2379. }
  2380. function md5_hh(a, b, c, d, x, s, t){
  2381. return md5_cmn(b ^ c ^ d, a, b, x, s, t);
  2382. }
  2383. function md5_ii(a, b, c, d, x, s, t){
  2384. return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
  2385. }
  2386. function core_hmac_md5(key, data){
  2387. var bkey = str2binl(key);
  2388. if (bkey.length > 16)
  2389. bkey = core_md5(bkey, key.length * chrsz);
  2390. var ipad = Array(16), opad = Array(16);
  2391. for (var i = 0; i < 16; i++){
  2392. ipad[i] = bkey[i] ^ 0x36363636;
  2393. opad[i] = bkey[i] ^ 0x5C5C5C5C;
  2394. }
  2395. var hash = core_md5(ipad.concat(str2binl(data)), 512+data.length * chrsz);
  2396. return core_md5(opad.concat(hash), 512+128);
  2397. }
  2398. function safe_add(x, y){
  2399. var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  2400. var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  2401. return (msw << 16) | (lsw & 0xFFFF);
  2402. }
  2403. function bit_rol(num, cnt){
  2404. return (num << cnt) | (num >>> (32-cnt));
  2405. }
  2406. function str2binl(str){
  2407. var bin = Array();
  2408. var mask = (1 << chrsz) - 1;
  2409. for (var i = 0; i < str.length * chrsz; i += chrsz)
  2410. bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (i % 32);
  2411. return bin;
  2412. }
  2413. function binl2str(bin){
  2414. var str = "";
  2415. var mask = (1 << chrsz) - 1;
  2416. for (var i = 0; i < bin.length * 32; i += chrsz)
  2417. str += String.fromCharCode((bin[i >> 5] >>> (i % 32)) & mask);
  2418. return str;
  2419. }
  2420. function binl2hex(binarray){
  2421. var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  2422. var str = "";
  2423. for (var i = 0; i < binarray.length * 4; i++){
  2424. str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8+4)) & 0xF) +
  2425. hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF);
  2426. }
  2427. return str;
  2428. }
  2429. function binl2b64(binarray){
  2430. var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  2431. var str = "";
  2432. for (var i = 0; i < binarray.length * 4; i += 3){
  2433. var triplet = (((binarray[i >> 2] >> 8 * (i % 4)) & 0xFF) << 16) | ((
  2434. (binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 0xFF) << 8) | ((binarray[i
  2435. + 2 >> 2] >> 8 * ((i + 2) % 4)) & 0xFF);
  2436. for (var j = 0; j < 4; j++){
  2437. if (i * 8+j * 6 > binarray.length * 32)
  2438. str += b64pad;
  2439. else
  2440. str += tab.charAt((triplet >> 6 * (3-j)) & 0x3F);
  2441. }
  2442. }
  2443. return str;
  2444. }
  2445. function hexchar2bin(str){
  2446. var arr = [];
  2447. for(var i=0;i<str.length;i=i+2){
  2448. arr.push(String.fromCharCode(parseInt(str.substr(i,2),16)));
  2449. }
  2450. return arr.join('')
  2451. }
  2452. function __monitor(mid, probability) {
  2453. if (Math.random() > (probability || 1)) return;
  2454. try {
  2455. var url = location.protocol + '//ui.ptlogin2.qq.com/cgi-bin/report?id=' + mid;
  2456. var s = document.createElement("img");
  2457. s.src = url;
  2458. } catch (e) {}
  2459. }
  2460. /**
  2461. * encrypt user password with salt
  2462. * @param {String} password 原始密码
  2463. * @param {String} salt check 返回的序列
  2464. * @param {String} vcode 验证码
  2465. * @param {Boolean} isMd5 传入的密码是否MD5
  2466. * @return {String} PtA1 返回的加密字符串
  2467. */
  2468. function getEncryption(password, salt, vcode, isMd5) {
  2469. vcode = vcode || "";
  2470. password = password || "";
  2471. var md5Pwd = isMd5 ? password : md5(password),
  2472. h1 = hexchar2bin(md5Pwd),
  2473. s2 = md5(h1 + salt),
  2474. hexVcode = TEA.strToBytes(vcode.toUpperCase(), true),
  2475. vcodeLen = Number(hexVcode.length/2).toString(16);
  2476. while (vcodeLen.length < 4)
  2477. vcodeLen = "0" + vcodeLen;
  2478. TEA.initkey(s2);
  2479. var rawContent = TEA.encrypt(md5Pwd + TEA.strToBytes(salt) + vcodeLen + hexVcode);
  2480. TEA.initkey(""); // reset key
  2481. var rawLength = Number(rawContent.length / 2).toString(16);
  2482. while (rawLength.length < 4)
  2483. rawLength = '0' + rawLength;
  2484. var result = $pt.RSA.rsa_encrypt(hexchar2bin(rawLength + rawContent));
  2485. setTimeout(function() { // IE6 下报权限错误!
  2486. __monitor(488358, 1);
  2487. }, 0);
  2488. return btoa(hexchar2bin(result)).replace(/[\/\+=]/g, function(a) {return {'/':'-', '+':'*', '=':'_'}[a];});
  2489. }
  2490. function getRSAEncryption(password,vcode, isMd5){
  2491. var str1 = isMd5 ? password : md5(password);
  2492. var str2 = str1+vcode.toUpperCase();
  2493. var str3=$.RSA.rsa_encrypt(str2);
  2494. return str3;
  2495. }
  2496. return {
  2497. getEncryption:getEncryption,
  2498. getRSAEncryption:getRSAEncryption,
  2499. md5: md5
  2500. };
  2501. }();
  2502. try {
  2503. /**
  2504. * MTT QQ浏览器API
  2505. * @type {{version, isAndroid, isIPhone, canQlogin, QLogin4PT, canOneKey, refreshToken}}
  2506. */
  2507. // console.log(window)
  2508. window.MTT = (function() {
  2509. var version = 0,
  2510. platform = "";
  2511. try {
  2512. if (typeof window.browser != 'undefined')
  2513. version = browser.env && browser.env.version;
  2514. else
  2515. window.browser = { env: {}, app: {}, login: {} };
  2516. platform = browser.env && browser.env.platForm;
  2517. } catch (e) {
  2518. $.report.nlog("browser_env:" + "ver(" + window.ptui_pt_version + ")" + e.message, "647126");
  2519. }
  2520. var isAndroid = (platform == "ADR");
  2521. var isIPhone = (platform == "I");
  2522. var isIPad = (platform == "IP");
  2523. function canQlogin() {
  2524. try {
  2525. if (!version) return false;
  2526. var ua = navigator.userAgent;
  2527. var isWPMTT = /msie/i.test(ua) && ("notify" in window.external);
  2528. if (isWPMTT)
  2529. return true;
  2530. var isIphoneQQBrowser = isIPhone && version >= 42;
  2531. var isIpadQQBrowser = isIPad && version >= 32;
  2532. var isAndoidQQBrowser = isAndroid && version >= 42;
  2533. return isIphoneQQBrowser || isIpadQQBrowser || isAndoidQQBrowser;
  2534. } catch (e) {
  2535. return false;
  2536. }
  2537. }
  2538. function QLogin4PT(callbackFunc) {
  2539. var canQlogin = ($.cookie.get("pt_qlogincode") != 5) && MTT.canQlogin();
  2540. if ("function" != typeof(callbackFunc)) {
  2541. return;
  2542. }
  2543. if (canQlogin) {
  2544. if (/msie/i.test(window.navigator.userAgent)) {
  2545. window.external.notify("#@getUserInfoWT@#pt.qqBrowserCallback");
  2546. } else {
  2547. if (isAndroid)
  2548. if (browser.login.getLoginInfo) browser.login.getLoginInfo(callbackFunc, callbackFunc);
  2549. else callbackFunc("");
  2550. else if (isIPhone || isIPad)
  2551. if (browser.login.getUinAndSidInfo) browser.login.getUinAndSidInfo(callbackFunc, callbackFunc);
  2552. else callbackFunc("");
  2553. }
  2554. } else {
  2555. callbackFunc("");
  2556. if ($.cookie.get("pt_qlogincode") == 5) {
  2557. $.report.nlog("快速登录异常:pt_qlogincode=5", "276650");
  2558. }
  2559. }
  2560. }
  2561. function canOneKey(success, fail) {
  2562. if (!version) { // 非QQ浏览器直接返回false
  2563. fail && fail();
  2564. return false;
  2565. }
  2566. if (isAndroid) {
  2567. if (!browser.app.getApkInfo) return fail && fail();
  2568. browser.app.getApkInfo(function(info) {
  2569. try {
  2570. info = JSON.parse(JSON.parse(info));
  2571. if (version >= 51 && info && info.versionname >= "4.7")
  2572. success && success();
  2573. else
  2574. fail && fail();
  2575. } catch (e) {
  2576. fail && fail();
  2577. }
  2578. }, "com.tencent.mobileqq");
  2579. } else if (isIPhone || isIPad) {
  2580. window.x5 && x5.exec(function(app) {
  2581. if (app && app.isSupportApp)
  2582. success && success();
  2583. else
  2584. fail && fail();
  2585. }, fail, "app", "getMobileAppSupport", [{
  2586. "scheme": "wtloginmqq2://"
  2587. }]);
  2588. }
  2589. return false;
  2590. }
  2591. function refreshToken(uin, callback) { // 刷新QQ浏览器的stweb票据
  2592. if (isAndroid && browser.login.refreshToken) {
  2593. browser.login.refreshToken({ "uin": uin }, callback);
  2594. } else if (isIPad || isIPhone) {
  2595. window.x5 && x5.exec(callback, callback, "login", "refreshToken", [{ "uin": uin }]);
  2596. }
  2597. }
  2598. return {
  2599. version: version,
  2600. isAndroid: isAndroid,
  2601. isIPhone: isIPhone,
  2602. canQlogin: canQlogin,
  2603. QLogin4PT: QLogin4PT,
  2604. canOneKey: canOneKey,
  2605. refreshToken: refreshToken
  2606. };
  2607. }());
  2608. } catch (e) {
  2609. // console.log(e)
  2610. $.report.nlog("QB Exception:" + "ver(" + window.ptui_pt_version + ")" + e.message, "647127");
  2611. window.MTT = {};
  2612. }
  2613. /////////////////////////////////////////////////////登录逻辑
  2614. var pt = {
  2615. pageState: 1,
  2616. login_href: window.g_href,
  2617. domain: window.ptui_domain,
  2618. isHttps: $.check.isHttps(),
  2619. errTipClock: 0, //错误提示定时器
  2620. lang: window.STR_LANG,
  2621. submit_o: {}, //登录提交参数对象
  2622. auto_login: false, //下次自动登录
  2623. switch_position_x: 0, //滑动开关位置(应该是手指的位置)
  2624. touchstartTime: 0, //按住开始的时间,用于计算长按
  2625. longTouchTime: 500, //长按时间
  2626. default_face_url: "", //默认头像地址
  2627. is_qlogin: false, //是否快速登录
  2628. lang_num: window.ptui_lang, //语言
  2629. action: [0, 0], //动作
  2630. vcode: "", //验证码
  2631. verifysession: "", //验证码cookie
  2632. deviceType: 2, //0 pc ;1 android;2 iphone;3 wp;4 symbian;5 blackberry;其它认为是pc
  2633. login_uin: "",
  2634. login_pwd: "", //3-md5
  2635. needAt: "", //特殊帐号前加@符号
  2636. //////////////////////////////// url中自定义参数
  2637. appid: "", //appid 必须的
  2638. s_url: "", //登录成功跳转的url
  2639. low_login_enable: window.ptui_low_login, //弱登录
  2640. style: 9,
  2641. /////////////////////////////////////
  2642. t_type: 0,
  2643. /////////////
  2644. isSubmiting: false, //判断是否正在提交
  2645. key_interval: 0,
  2646. keyindex: 19, //qq浏览器快速登录
  2647. qqBrowserInfo: null, //qq浏览器快速登录信息,object
  2648. openCookieInfo: null, //互联cookie登录信息
  2649. authInfo: null, //授权信息,object
  2650. authUin: '', //授权信息
  2651. authNick: '', //授权昵称
  2652. authLoginUrl: '', //授权登录url
  2653. qlogin_list_data: [], //快速登录数据(所有的出现头像的)
  2654. checkUrl: '',
  2655. loginUrl: '',
  2656. cookieInfo: null, //互联cookie登录的信息
  2657. cookieLogin: false, //是否使用cooki中skey登录
  2658. //快速登录的头像列表
  2659. regTmp: '<span id="#uin#" pwd="#pwd#" type="#type#" class="header" onclick="pt.clickHeader(event);">\
  2660. <div id="del_touch_#uin#" class="del_touch_icon" >\
  2661. <span id="del_#uin#" class="del_icon" ></span>\
  2662. </div>\
  2663. <img id="img_#uin#" src="#src#" onerror="pt.face_error();" /> \
  2664. <div id="img_out_#uin#" class="img_out"></div>\
  2665. <label id="nick_#uin#" class="nick">#nick# </label>\
  2666. </span>',
  2667. //互联快速登录头像
  2668. hulianRegTmp: '<div class="useravatar">\
  2669. <img id="img_#uin#" src="#src#" onerror="pt.face_error();" alt="#nick#" />\
  2670. </div>\
  2671. <div class="userinfo">\
  2672. <div class="usernick" id="hl_usernick">#nick#</div>\
  2673. <div class="userqq">#uin#</div>\
  2674. </div>\
  2675. <button id="userSwitch" class="switch" tabindex="5" href="javascript:void(0)";>切换帐号</button>',
  2676. new_vcode: false,
  2677. clickEvent: "touchstart",
  2678. checkErr: {
  2679. "2052": "网络繁忙,请稍后重试。",
  2680. "1028": "網絡繁忙,請稍後重試。",
  2681. "1033": "The network is busy, please try again later."
  2682. },
  2683. /**
  2684. * 是否互联登录框
  2685. */
  2686. isHulian: window.ptui_appid == 716027609,
  2687. isOffice: window.ptui_style == 39,
  2688. isWtlogin: window.ptui_style == 42,
  2689. isInIframe: window.ptui_style == 38 || window.self !== window.top, //遇到了非38的iframe内嵌,这里判断一下更准确
  2690. is3gNews: window.ptui_style == 37, // 37 手腾网,最简单的版本
  2691. isMail: window.ptui_appid == 522005705,
  2692. lockedAccount: window.ptui_lockuin == 1 ? window.ptui_defuin : "", // 锁定账号,比如说财付通支付场景
  2693. ua: window.navigator.userAgent.toLowerCase(),
  2694. isWX: window.navigator.userAgent.match(/micromessenger\/(\d\.\d\.\d)/i),
  2695. isMQQ: window.navigator.userAgent.match(/qq\/(\d\.\d\.\d)/i),
  2696. isAndroid: /android/i.test(window.navigator.userAgent),
  2697. isIos: (/iPad|iPhone|iPod/.test(window.navigator.platform) ||
  2698. (window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1)) &&
  2699. !window.MSStream,
  2700. isIPhone: /iphone/i.test(window.navigator.userAgent),
  2701. uInput: $("u"),
  2702. pInput: $("p"),
  2703. btnGo: $("go"),
  2704. btnGo2: $("go2"),
  2705. btnOnekey: $("onekey"),
  2706. browser : (function(){
  2707. var browser = {
  2708. //这里要注意一件时间,由于历史逻辑的存在,当在企业微信打开时,isWX=true,isWorkWX=true ,暂时保留这样,后续迭代时再处理
  2709. isWX: false,
  2710. isWorkWX : false,
  2711. ua : '',
  2712. replaceLocation : function(url, context){
  2713. const win = context || window
  2714. win.location.replace(url)
  2715. },
  2716. setLocation : function(url, context){
  2717. const win = context || window
  2718. win.location.assign(url)
  2719. },
  2720. isOnline : function(){
  2721. return !!window.navigator.onLine
  2722. },
  2723. init : function(){
  2724. browser.ua = window.navigator.userAgent.toLowerCase() || '';
  2725. browser.isWX = !!browser.ua.match(/micromessenger\/(\d\.\d\.\d)/i)
  2726. browser.isWorkWX = !!browser.ua.match(/wxwork\/\d\.\d\.\d/i)
  2727. }
  2728. }
  2729. //默认进行一次初始化
  2730. browser.init();
  2731. return browser
  2732. })(),
  2733. /**
  2734. * [redirect 统一跳转]
  2735. * @param {[type]} target [description]
  2736. * @param {[type]} url [description]
  2737. * @return {[type]} [description]
  2738. */
  2739. redirect: function(target, url) {
  2740. switch (target + '') {
  2741. case '0':
  2742. if (pt.isInIframe || $.bom.query("pt_replace") == "1")
  2743. this.browser.replaceLocation(url); // 作为iframe. 不想留下历史记录
  2744. else
  2745. this.browser.setLocation(url); //这里换成assign,方便sinon mock
  2746. break;
  2747. default:
  2748. if ($.bom.query("pt_replace") == "1")
  2749. this.browser.replaceLocation(url,window.top);
  2750. else
  2751. this.browser.setLocation(url, window.top);
  2752. // window.location.assign(url); //这里换成assign,方便sinon mock
  2753. break;
  2754. }
  2755. },
  2756. init: function() {
  2757. if (pt.hasInit) {
  2758. return;
  2759. } else {
  2760. pt.hasInit = true;
  2761. }
  2762. pt.default_face_url = "//imgcache.qq.com/ptlogin/v4/style/0/images/1.gif"; //QQ企鹅头像地址
  2763. pt.initSURL();
  2764. pt.setClickEvent();
  2765. if (pt.isOffice) {
  2766. pt.open.loadAppInfo();
  2767. }
  2768. //发起各种异步请求
  2769. if (!window.hlhdFlag) {
  2770. pt.qqBrowserQlogin();
  2771. }
  2772. pt.auth();
  2773. //绑定相关事件
  2774. pt.bindEvent();
  2775. pt.bindInput();
  2776. //隐藏地址栏
  2777. pt.hideURLBar();
  2778. //先屏蔽,等验证码准备完成了再打开
  2779. pt.setVcodeFlag();
  2780. //拉取头像
  2781. pt.setUrl();
  2782. pt.showAutoLogin();
  2783. $.winName.set("login_href", encodeURIComponent(pt.login_href));
  2784. pt.checkIframe();
  2785. pt.checkPostMessage();
  2786. if (window.ptui_style == 42) {
  2787. pt.uInput && pt.uInput.focus()
  2788. }
  2789. window.setTimeout(function(e) {
  2790. if (window.ptui_appid != "549000929") { //qzone的不上报
  2791. pt.webLoginReport();
  2792. }
  2793. /*
  2794. ID: 408084 名称:互联手机版不支持cookie
  2795. ID: 408085 名称:互联手机版不支持cookie bug
  2796. ID: 410030 名称:login_mobile.js check 总量(10%)
  2797. ID: 410031 名称:login_mobile.js check后台不下发cookie
  2798. */
  2799. $.report.monitor(412020, 0.05);
  2800. if (!navigator.cookieEnabled) {
  2801. $.report.monitor(410030);
  2802. if ($.cookie.get('ptcz'))
  2803. $.report.monitor(410031);
  2804. }
  2805. }, 2000);
  2806. if (pt.lockedAccount && window.ptui_tab) {
  2807. //锁定帐号的时候不展示二维码入口
  2808. pt.switchpwd();
  2809. var qlogin_entry = $('qlogin_entry');
  2810. qlogin_entry && $.css.hide(qlogin_entry);
  2811. }
  2812. //Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16C101 QQ/7.9.9.445 V1_IPH_SQ_8.0.8_1_APP_A Pixel/1080 Core/WKWebView Device/Apple(iPhone 7Plus) NetType/4G QBWebViewType/1 WKType/1
  2813. var capthchaJsUrl = (pt.isHttps ? 'https://ssl.captcha.qq.com/' : 'http://captcha.qq.com/') +
  2814. 'template/TCapIframeApi.js?aid=' + window.ptui_appid + '&rand=' + Math.random() + '&clientype=1&lang=' +
  2815. pt.lang_num + '&apptype=2'
  2816. if(navigator.userAgent.indexOf('Core/WKWebView')>=-1){
  2817. //wk webview里边, 如果有任何js资源 一直没有回包, 会阻塞页面渲染, 所以放到onload之后再去
  2818. window.addEventListener('load', function(){
  2819. $.http.loadScript(capthchaJsUrl,
  2820. function() {});
  2821. })
  2822. }else{
  2823. $.http.loadScript(capthchaJsUrl,
  2824. function() {});
  2825. }
  2826. },
  2827. VCCallback: function(data) {
  2828. switch (+data.ret) {
  2829. case 0:
  2830. pt.submitNewVcode(data);
  2831. break;
  2832. case 1:
  2833. pt.go_back();
  2834. break;
  2835. }
  2836. },
  2837. setUrl: function() {
  2838. var proto = pt.isHttps ? "https://ssl." : "http://";
  2839. var protoCheck = pt.isHttps ? "https://ssl." : "http://check.";
  2840. pt.checkUrl = protoCheck + "ptlogin2." + pt.domain + "/check?";
  2841. pt.loginUrl = proto + "ptlogin2." + pt.domain + "/";
  2842. },
  2843. /**
  2844. * [ptui_speedReport 测速上报]
  2845. * @param {Object} params [键值对象]
  2846. * @return {[type]} [description]
  2847. */
  2848. ptui_speedReport: function(params) {
  2849. var url = 'http://isdspeed.qq.com/cgi-bin/r.cgi?flag1=7808&flag2=8';
  2850. var flag3 = 1;
  2851. if (pt.isHttps) {
  2852. url = 'https://huatuospeed.weiyun.com/cgi-bin/r.cgi?flag1=7808&flag2=8';
  2853. flag3 = 2;
  2854. } else {
  2855. //url = 'http://isdspeed.qq.com/cgi-bin/r.cgi?flag1=7808&flag2=8';
  2856. if ($.detectBrowser()[0] == "MQQBrowser") {
  2857. var net = navigator.connection;
  2858. if (net && net.type) {
  2859. var type = net.type;
  2860. if (type == 1) { //ethernet
  2861. flag3 = 3;
  2862. } else if (type == 2) { //wifi
  2863. flag3 = 4;
  2864. } else if (type == 3) { //2g
  2865. flag3 = 5;
  2866. } else if (type == 4) { //3g
  2867. flag3 = 6;
  2868. } else if (type == 5) { //4g
  2869. flag3 = 7;
  2870. } else { //none
  2871. flag3 = 8;
  2872. }
  2873. } else {
  2874. flag3 = 8;
  2875. }
  2876. } else {
  2877. flag3 = 1;
  2878. }
  2879. }
  2880. url += '&flag3=' + flag3;
  2881. for (var o in params) {
  2882. //除去十分不靠谱的时间(超过15秒)
  2883. if (params[o] > 15000 || params[o] < 0) {
  2884. continue;
  2885. }
  2886. url += "&" + o + "=" + (params[o] || 1); //最小赋值为1,否则会被丢弃
  2887. }
  2888. var img = new Image();
  2889. img.src = url;
  2890. },
  2891. /**
  2892. * [webLoginReport 测速上报逻辑]
  2893. * @return {[type]} [description]
  2894. */
  2895. webLoginReport: function() {
  2896. try {
  2897. //抽样20%,QQ浏览器全部上报
  2898. if (Math.random() > 0.2 && $.detectBrowser()[0] != "MQQBrowser") {
  2899. return;
  2900. }
  2901. var points = ["navigationStart", "unloadEventStart", "unloadEventEnd", "redirectStart", "redirectEnd", "fetchStart", "domainLookupStart", "domainLookupEnd", "connectStart", "connectEnd", "requestStart", "responseStart", "responseEnd", "domLoading", "domInteractive", "domContentLoadedEventStart", "domContentLoadedEventEnd", "domComplete", "loadEventStart", "loadEventEnd"];
  2902. var params = {};
  2903. var h5_time = window.performance ? window.performance.timing : null;
  2904. if (h5_time) {
  2905. var baseTime = h5_time[points[0]];
  2906. var i = 1;
  2907. for (var len = points.length; i < len; i++) {
  2908. if (h5_time[points[i]]) {
  2909. params[i] = h5_time[points[i]] - baseTime;
  2910. }
  2911. }
  2912. if (loadJs && loadJs.onloadTime)
  2913. params[i++] = loadJs.onloadTime - baseTime;
  2914. var isReasonable = h5_time['connectEnd'] >= h5_time['connectStart'] && h5_time["responseEnd"] >= h5_time["responseStart"] && h5_time['domComplete'] >= h5_time['domInteractive'] && h5_time['domInteractive'] >= h5_time['domLoading'] && h5_time['loadEventStart'] >= h5_time['domComplete'] && h5_time['loadEventEnd'] >= h5_time['loadEventStart'];
  2915. if (isReasonable) {
  2916. pt.ptui_speedReport(params);
  2917. }
  2918. }
  2919. } catch (e) {}
  2920. },
  2921. setClickEvent: function() {
  2922. var noIosOrAndroid = !/iphone|ipad|android/.test(window.navigator.userAgent.toLowerCase());
  2923. if(noIosOrAndroid){
  2924. pt.clickEvent = "click";
  2925. }else{
  2926. pt.clickEvent = "touchstart";
  2927. }
  2928. },
  2929. //存储上次登录的号码(only one),登录成功且没有选择自动登录的
  2930. saveLastUin: function(uin) {
  2931. $.localStorage.set("last_uin", uin);
  2932. },
  2933. //获取上次登录的号码
  2934. getLastUin: function() {
  2935. return $.localStorage.get("last_uin");
  2936. },
  2937. //将一个对象转换成url后面的参数 a=b&
  2938. object2param: function(obj) {
  2939. var arr = [];
  2940. for (var n in obj) {
  2941. arr.push(n + "=" + obj[n] + "&");
  2942. }
  2943. return arr.join("");
  2944. },
  2945. //ps:以下部分都是海外登录的逻辑,由于不清楚情况,先不要动
  2946. //进入海外手机登录页面
  2947. is_oversea: false,
  2948. enterOverseaLogin: function() {
  2949. try {
  2950. pt.alert.hide();
  2951. } catch (e) {}
  2952. var e = $('oversea');
  2953. e && $.css.show(e);
  2954. pt.is_oversea = true;
  2955. $('state').value = _areaList[0].n;
  2956. $('country-code').innerHTML = '+' + _areaList[0].c;
  2957. if (window.openSDK && window.openSDK.clearAllEdit) {
  2958. $('password').value = '';
  2959. window.openSDK.clearAllEdit();
  2960. }
  2961. },
  2962. exitOverseaLogin: function() {
  2963. var e = $('oversea');
  2964. e && $.css.hide(e);
  2965. pt.is_oversea = false;
  2966. if (window.openSDK && window.openSDK.clearAllEdit) {
  2967. pt.pInput.value = '';
  2968. window.openSDK.clearAllEdit();
  2969. }
  2970. },
  2971. //进入国家选择页
  2972. enterOverseaCountry: function() {
  2973. pt.initOverseaCountry();
  2974. var e = $('country');
  2975. e && $.css.show(e);
  2976. var state = $('state');
  2977. state && state.blur();
  2978. },
  2979. setOverseaCountry: function(code) {
  2980. for (var i in _areaList) {
  2981. if (code == _areaList[i].n) {
  2982. $('state').value = _areaList[i].n;
  2983. $('country-code').innerHTML = '+' + _areaList[i].c;
  2984. pt.exitOverseaCountry();
  2985. return;
  2986. }
  2987. }
  2988. },
  2989. initOverseaCountry: function() {
  2990. var search = $('country-search'),
  2991. list = $('country-list'),
  2992. html = '';
  2993. search.value = '';
  2994. if (_areaList) {
  2995. for (var i in _areaList) {
  2996. html += '<li onclick="pt.setOverseaCountry(\'' + _areaList[i].n + '\')">' + _areaList[i].n + '</li>'
  2997. }
  2998. }
  2999. list.innerHTML = html;
  3000. },
  3001. updateOverseaCountry: function() {
  3002. var search = $('country-search'),
  3003. list = $('country-list'),
  3004. html = '';
  3005. if (_areaList) {
  3006. var key = new RegExp(search.value.split('').join('.{0,}'), "i");
  3007. for (var i in _areaList) {
  3008. if (key.test(_areaList[i].c) || key.test(_areaList[i].n) || key.test(_areaList[i].p))
  3009. html += '<li onclick="pt.setOverseaCountry(\'' + _areaList[i].n + '\')">' + _areaList[i].n + '</li>'
  3010. }
  3011. }
  3012. list.innerHTML = html;
  3013. },
  3014. countrySearchFocus: function() {
  3015. var placeholder = $('country-search-placeholder');
  3016. placeholder && $.css.hide(placeholder);
  3017. },
  3018. countrySearchBlur: function() {
  3019. var placeholder = $('country-search-placeholder');
  3020. var input = $('country-search');
  3021. input && placeholder && input.value.length === 0 && $.css.show(placeholder);
  3022. },
  3023. exitOverseaCountry: function() {
  3024. var e = $('country');
  3025. e && $.css.hide(e);
  3026. },
  3027. //ps:以上部分都是海外登录的逻辑,由于不清楚情况,先不要动
  3028. //显示错误
  3029. showErr: function(message, callback) {
  3030. clearTimeout(pt.errTipClock);
  3031. var timeout = 3000;
  3032. if ((typeof callback).toLocaleLowerCase() == "number") {
  3033. timeout = parseInt(callback, 10);
  3034. callback = null;
  3035. }
  3036. $("error_message").innerHTML = message;
  3037. $.css.show("error_tips");
  3038. if (pt.isHulian) {
  3039. if (window.navigator.userAgent.match(/iphone/i)) {
  3040. pt.btnGo.focus(); // fix ios webview 键盘无法输入问题
  3041. }
  3042. pt.errTipClock = window.setTimeout(function() {
  3043. pt.hideErr(callback);
  3044. }, timeout);
  3045. } else {
  3046. callback && callback();
  3047. pt.errTipClock = window.setTimeout(function() {
  3048. pt.hideErr();
  3049. }, timeout);
  3050. }
  3051. },
  3052. /**
  3053. * [hideErr 隐藏错误]
  3054. * @return {[type]} [description]
  3055. */
  3056. hideErr: function(callback) {
  3057. $.css.hide("error_tips");
  3058. callback && callback();
  3059. },
  3060. /**
  3061. * [checkiframe description]
  3062. * @return {[type]} [description]
  3063. */
  3064. checkIframe: function() {
  3065. try {
  3066. if (top != self && !pt.isHulian) {
  3067. $.report.nlog("iphone登录框被iframe;" + "referer=" + document.referrer, "347748");
  3068. }
  3069. } catch (e) {
  3070. }
  3071. },
  3072. checkPostMessage: function() {
  3073. if (typeof window.postMessage == "undefined") {
  3074. $.report.nlog("iphone登录框不支持postMessage;", "350525");
  3075. }
  3076. if (typeof window.JSON == "undefined") {
  3077. $.report.nlog("iphone登录框不支持JSON;", "362678");
  3078. }
  3079. },
  3080. /**
  3081. * [setVcodeFlsg 初始化使用验证码的方式]
  3082. */
  3083. setVcodeFlag: function() {
  3084. if (typeof window.postMessage == "undefined" || typeof window.JSON == "undefined") {
  3085. pt.new_vcode = false;
  3086. } else {
  3087. pt.new_vcode = true;
  3088. }
  3089. },
  3090. /**
  3091. * [getAuthUrl 构造授权url]
  3092. * @return {String} [description]
  3093. */
  3094. getAuthUrl: function() {
  3095. var authUrl = (pt.isHttps ? "https://ssl." : "http://") + "ptlogin2." + pt.domain + "/pt4_auth?daid=" + window.ptui_daid + "&appid=" + window.ptui_appid + "&auth_token=" + $.str.time33($.cookie.get("supertoken"));
  3096. if (/^https/.test(pt.s_url)) { //成功地址为https的
  3097. authUrl += "&pt4_shttps=1";
  3098. }
  3099. if (window.ptui_pt_qzone_sig == "1") {
  3100. authUrl += "&pt_qzone_sig=1";
  3101. }
  3102. return authUrl;
  3103. },
  3104. /**
  3105. * [auth 授权]
  3106. * @return {[type]} [description]
  3107. */
  3108. auth: function() {
  3109. //获取参数列表
  3110. pt.getParam();
  3111. pt.initSURL();
  3112. var authUrl = pt.getAuthUrl();
  3113. var superuin = $.cookie.get("superuin"); //没有skey就没有superkey,这个时候可以不用去后台请求了
  3114. // APP下发superkey的时候,一般并不下发supertoken, 所以只能这里自己下发,这主要还依赖于后台对supertoken并不要求与superkey对应
  3115. var fake_supertoken = $.str.hash33(superuin);
  3116. if (!parseInt($.cookie.get("supertoken")) && fake_supertoken)
  3117. $.cookie.set("supertoken", $.str.hash33(superuin), "ptlogin2." + pt.domain);
  3118. if (window.ptui_daid && window.ptui_noAuth != "1" && superuin != "" && !pt.isWtlogin) {
  3119. $.http.loadScript(authUrl);
  3120. }
  3121. },
  3122. showAuth: function(url) {
  3123. var params = url.substr(url.indexOf("?") + 1);
  3124. var m = params.match(RegExp("(^|&)uin=([^&]*)(&|$)"));
  3125. pt.authUin = !m ? "" : decodeURIComponent(m[2]);
  3126. pt.authLoginUrl = url;
  3127. pt.authNick = $.str.utf8ToUincode($.cookie.get("ptnick_" + pt.authUin)) || pt.authUin;
  3128. if (pt.authUin) {
  3129. pt.authInfo = {
  3130. "uin": $.str.encodeHtml(pt.authUin),
  3131. "nick": $.str.encodeHtml(pt.authNick),
  3132. "authUrl": pt.authUrl,
  3133. "type": 3
  3134. };
  3135. }
  3136. },
  3137. // 互联使用superkey登录,包括已登录互联或者已登录其它业务两种情况
  3138. setCookieLogin: function() {
  3139. //非手Q内需要superkey登录 优先使用superkey
  3140. var superkey = $.cookie.get("supertoken");
  3141. var uin = $.cookie.get("superuin");
  3142. if (uin) uin = parseInt(uin.substring(1), 10);
  3143. else uin = null;
  3144. var nick = $.str.utf8ToUincode($.cookie.get("ptnick_" + uin)) || uin;
  3145. var hasCookie = window.ptui_daid && superkey;
  3146. if ((hasCookie && uin)) {
  3147. pt.cookieInfo = {
  3148. "uin": $.str.encodeHtml(uin),
  3149. "nick": $.str.encodeHtml(nick),
  3150. "superkey": superkey,
  3151. "type": 4
  3152. };
  3153. return true;
  3154. }
  3155. //没有superkey的时候 手Q内直接可以用clientkey登录
  3156. uin = $.cookie.uin();
  3157. nick = $.str.utf8ToUincode($.cookie.get("ptnick_" + uin)) || uin;
  3158. if (uin && pt.mqqCanQLogin()) {
  3159. pt.cookieInfo = {
  3160. "uin": $.str.encodeHtml(uin),
  3161. "nick": $.str.encodeHtml(nick),
  3162. "type": 4
  3163. };
  3164. return true;
  3165. }
  3166. return false;
  3167. },
  3168. qqBrowserQlogin: function() {
  3169. try {
  3170. //iframe的话无法获取到qq浏览器的信息, android 还是可以的
  3171. if (self === top || MTT.isAndroid) {
  3172. MTT.QLogin4PT(pt.qqBrowserCallback);
  3173. }
  3174. } catch (e) {
  3175. $.report.nlog("快速登录异常,qqBrowserQlogin," + e.message, "276650");
  3176. }
  3177. },
  3178. qqBrowserCallback: function(info) {
  3179. try {
  3180. if (info && typeof info === "string")
  3181. info = JSON.parse(info);
  3182. if (info && ($.check.isQQ(info.uin) && info.loginkey.length != 0 && info.loginkey.length > 10)) {
  3183. pt.qqBrowserInfo = {};
  3184. pt.qqBrowserInfo.uin = $.str.encodeHtml(info.uin);
  3185. pt.qqBrowserInfo.nick = $.str.encodeHtml(info.nickname);
  3186. pt.qqBrowserInfo.loginkey = info.loginkey;
  3187. pt.qqBrowserInfo.type = 2;
  3188. pt.refreshQloginUI();
  3189. } else {
  3190. if (info && info.uin.length == 0) {
  3191. $.report.nlog("快速登录异常:数据返回异常,没有uin", "276650");
  3192. } else if (info && info.loginkey.length == 0) {
  3193. $.report.nlog("快速登录异常:数据返回异常,没有loginkey", "276650");
  3194. } else if (info) {
  3195. $.report.nlog("快速登录异常:数据返回异常:" + info.loginkey.length, "276650");
  3196. }
  3197. }
  3198. } catch (e) {
  3199. $.report.nlog("快速登录异常: qqBrowserCallback " + e.message, "276650");
  3200. }
  3201. },
  3202. initSURL: function() {
  3203. pt.s_url = $.bom.query("s_url");
  3204. if (pt.isMail && pt.low_login_enable == 1)
  3205. pt.s_url = pt.addParamToUrl(pt.s_url, "ss", 1);
  3206. },
  3207. /**
  3208. * [addParamToUrl 在一个url后面增加参数]
  3209. * @param {String} url [description]
  3210. * @param {String} name [description]
  3211. * @param {String|Number} value [description]
  3212. */
  3213. addParamToUrl: function(url, name, value) {
  3214. var u1 = url.split('#');
  3215. var sep = u1[0].indexOf('?') > 0 ? '&' : '?';
  3216. if (u1[0].substr(u1[0].length - 1, 1) == '?') {
  3217. sep = ''; // 没有更多参数,也就不用加个&了
  3218. }
  3219. if (u1[1]) {
  3220. u1[1] = '#' + u1[1];
  3221. } else {
  3222. u1[1] = '';
  3223. }
  3224. return u1[0] + sep + name + '=' + value + u1[1];
  3225. },
  3226. //获取url参数
  3227. getParam: function() {
  3228. pt.appid = window.ptui_appid;
  3229. if (pt.isInIframe) { //style=38支持self跳转,其他的都是top跳转
  3230. switch (window.ptui_target) {
  3231. case "_self":
  3232. case "0":
  3233. pt.target = 0;
  3234. break;
  3235. case "_top":
  3236. case "1":
  3237. pt.target = 1;
  3238. break;
  3239. default:
  3240. pt.target = 1;
  3241. break;
  3242. }
  3243. } else {
  3244. pt.target = 1;
  3245. }
  3246. //pt.low_login_enable = ($.bom.query("low_login_enable")==1 ? $.bom.query("low_login_enable") : 0) || ($.bom.query("low_login")==1 ? $.bom.query("low_login") : 0);
  3247. pt.style = window.ptui_style ? window.ptui_style : 9;
  3248. // 改造中,改造完成只需把这个注释去掉, skey 与 superkey 是兼容的
  3249. //if (pt.isHulian)
  3250. // window.ptui_daid = window.ptui_daid || 381; // 互联登录有可能被其它业务直接引用,那么这个daid就不一定会传过来,所以自己加上
  3251. if (pt.isHulian)
  3252. window.pt_skey_valid = parseInt($.bom.query("pt_skey_valid")) || 0; // 由互联跳转过来时带的标记位
  3253. },
  3254. //生成快速登录列表
  3255. build_qlogin_list: function() {
  3256. var qlogin_list_data = pt.get_qlogin_list();
  3257. pt.qlogin_list_data = qlogin_list_data;
  3258. var length = qlogin_list_data.length
  3259. if (window.ptui_style == 35 && length > 1)
  3260. length = qlogin_list_data.length = 1
  3261. if (length > 0 && !window.ptui_tab) {
  3262. pt._switch(2); //指定切到快速登录页
  3263. pt.hideOneKey();
  3264. var strMessage = "";
  3265. for (var i = 0; i < length; i++) {
  3266. if (qlogin_list_data[i].uin != "") {
  3267. strMessage += pt.regTmp.replace(/#uin#/g, qlogin_list_data[i].uin)
  3268. .replace(/#nick#/g, qlogin_list_data[i].nick)
  3269. .replace(/#pwd#/g, qlogin_list_data[i].pwd)
  3270. .replace(/#type#/g, qlogin_list_data[i].type)
  3271. .replace(/#src#/g, pt.default_face_url);
  3272. }
  3273. }
  3274. if (length > 1 && window.xMsg && window.xMsg.call)
  3275. window.xMsg.call("connect", "userSwitch", {}, function() {});
  3276. $("q_logon_list").innerHTML = strMessage;
  3277. //昵称过长的中间加...
  3278. for (var i = 0; i < length; i++) {
  3279. pt.getShortWord($("nick_" + qlogin_list_data[i].uin), qlogin_list_data[i].nick, 95);
  3280. }
  3281. pt.initFace();
  3282. $("swicth_login") && ($("swicth_login").style.display = "block");
  3283. } else {
  3284. $("web_login") && ($("web_login").style.display = "block");
  3285. $("swicth_login") && ($("swicth_login").style.display = "none");
  3286. }
  3287. },
  3288. fill_usernick: function() {
  3289. // 手Q环境下补充昵称
  3290. if (window.mqq && window.mqq.data && window.mqq.data.getUserInfo) {
  3291. window.mqq.data.getUserInfo(function(result) {
  3292. var usernick = $("hl_usernick");
  3293. if (usernick && result && result.nick)
  3294. usernick.innerHTML = $.str.encodeHtml(result.nick);
  3295. });
  3296. }
  3297. },
  3298. build_office_qlogin: function() {
  3299. $.report.monitor(2123219);
  3300. if (!pt.cookieInfo)
  3301. pt.setCookieLogin();
  3302. if (!pt.cookieInfo)
  3303. return $.report.monitor(2123220);
  3304. pt.cookieLogin = true;
  3305. $("hl_avatar").style.backgroundImage = "url(https://q4.qlogo.cn/g?b=qq&nk=" + pt.cookieInfo.uin + "&s=100)";
  3306. $("hl_usernick").innerHTML = pt.cookieInfo.nick || pt.cookieInfo.uin;
  3307. $("hl_qqnum").innerHTML = "(" + pt.cookieInfo.uin + ")";
  3308. pt.fill_usernick();
  3309. },
  3310. //切换登录方式
  3311. _switch: function(state) {
  3312. var switchqlist = function() {
  3313. var switcher = $("swicth_login");
  3314. $("q_login").style.display = "block";
  3315. $("web_login").style.display = "none";
  3316. if (switcher) {
  3317. switcher.innerHTML = $.str.encodeHtml('切换帐号'); //TODO 后面改多语言
  3318. switcher.classList.add('weakest')
  3319. }
  3320. pt.hideURLBar();
  3321. pt.pageState = 2;
  3322. },
  3323. switchpwd = function() {
  3324. var switcher = $("swicth_login");
  3325. pt.showOneKey.ever && pt.showOneKey();
  3326. $("q_login").style.display = "none";
  3327. $("web_login").style.display = "block";
  3328. if (switcher) {
  3329. switcher.innerHTML = $.str.encodeHtml("切换账号")
  3330. switcher.classList.remove('weakest');
  3331. }
  3332. pt.uInput.focus(); //聚焦,调出键盘
  3333. pt.pageState = 1;
  3334. window.xMsg && xMsg.call("connect", "userSwitch", {}, function() {});
  3335. }
  3336. //切换到快速登录
  3337. if (typeof state === "undefined")
  3338. if ($("q_login").style.display == "none") {
  3339. switchqlist();
  3340. }
  3341. //切换到普通登录
  3342. else {
  3343. switchpwd();
  3344. }
  3345. else
  3346. switch (+state) {
  3347. case 2:
  3348. switchqlist();
  3349. break;
  3350. case 1:
  3351. switchpwd();
  3352. break;
  3353. default:
  3354. break;
  3355. }
  3356. pt.showAutoLogin();
  3357. if (pt.isInIframe) { //手机弹出式
  3358. window.setTimeout(function() {
  3359. pt.ptui_notifySize("content");
  3360. }, 0)
  3361. }
  3362. },
  3363. checkNetwork: function() {
  3364. if (!pt.browser.isOnline())
  3365. pt.showErr(window.STR_LANG.offline);
  3366. else
  3367. return pt._timer = window.setTimeout(function() {
  3368. $.report.monitor(2114669);
  3369. pt.showErr(window.STR_LANG.offline);
  3370. try {
  3371. pt.endLoading();
  3372. } catch (e) {}
  3373. }, 10000);
  3374. },
  3375. loadingDiv: null,
  3376. isLoading: false,
  3377. startLoading: function() {
  3378. if (!pt.loadingDiv) {
  3379. pt.loadingDiv = document.createElement("div");
  3380. pt.loadingDiv.className = 'qui-loading-mask';
  3381. }
  3382. document.body.appendChild(pt.loadingDiv);
  3383. pt.isloading = true;
  3384. },
  3385. endLoading: function() {
  3386. document.body.removeChild(pt.loadingDiv);
  3387. pt.isloading = false;
  3388. },
  3389. submitEvent: function(e) {
  3390. pt.checkNetwork();
  3391. pt.startLoading();
  3392. // todo 办公开放添加上报
  3393. if (pt.isOffice && pt.cookieLogin) {
  3394. pt.cookielogin_submit(); // 已在其它业务登录,cookie中已有superkey
  3395. } else if (pt.isOffice && pt.qqBrowserInfo) { // MTT快速登录
  3396. pt.qlogin_submit();
  3397. } else {
  3398. pt.check(false);
  3399. }
  3400. pt.qrcode.used = false;
  3401. },
  3402. showOneKey: function(sure) {
  3403. var btnOnekey = $("onekey");
  3404. if (!pt.showOneKey.ever) {
  3405. $.e.add(btnOnekey, pt.clickEvent, pt.doOneKey);
  3406. $.e.add(btnOnekey, 'blur', pt.cancelAutoOneKey);
  3407. }
  3408. pt.showOneKey.ever = true;
  3409. if (sure) {
  3410. pt.btnGo.className += ' weak';
  3411. } else {
  3412. btnOnekey.className += ' weak';
  3413. }
  3414. btnOnekey && $.css.show(btnOnekey);
  3415. btnOnekey.focus();
  3416. $.report.monitor(414089);
  3417. if (pt.isInIframe) { //手机弹出式
  3418. window.setTimeout(function() {
  3419. pt.ptui_notifySize("content");
  3420. }, 0);
  3421. }
  3422. },
  3423. cancelAutoOneKey: function() {
  3424. window.clearInterval(pt.showOneKey.tid);
  3425. var btnOnekey = pt.btnOnekey;
  3426. btnOnekey && (btnOnekey.innerHTML = window.STR_LANG.onekey);
  3427. },
  3428. hideOneKey: function() {
  3429. pt.cancelAutoOneKey();
  3430. pt.showOneKey.ever = false
  3431. if (!(pt.isWtlogin || window.ptui_style == 35))
  3432. pt.btnGo.className = pt.btnGo.className.replace("weak", "");
  3433. pt.btnOnekey && $.css.hide(pt.btnOnekey);
  3434. if (pt.isInIframe) { //手机弹出式
  3435. window.setTimeout(function() {
  3436. pt.ptui_notifySize("content");
  3437. }, 0);
  3438. }
  3439. },
  3440. //绑定事件
  3441. bindEvent: function() {
  3442. var u_input = pt.uInput,
  3443. p_input = pt.pInput;
  3444. //普通登录事件
  3445. $.e.add(pt.btnGo, pt.clickEvent, pt.submitEvent);
  3446. pt.btnGo2 && $.e.add(pt.btnGo2, pt.clickEvent, function() {
  3447. var list = $('q_logon_list')
  3448. for (var i = 0; i < list.children.length; ++i) {
  3449. if (list.children[i].onclick) {
  3450. pt.clickHeader({
  3451. preventDefault: function() {},
  3452. currentTarget: list.children[i]
  3453. }, true)
  3454. return
  3455. }
  3456. }
  3457. })
  3458. p_input && $.e.add(p_input, "keydown", function(e) {
  3459. var keyCode = e.keyCode;
  3460. if (keyCode == 13) {
  3461. pt.submitEvent();
  3462. }
  3463. });
  3464. //手机的前往按钮
  3465. u_input && $.e.add(u_input, "keydown", function(e) {
  3466. var keyCode = e.keyCode;
  3467. if (keyCode == 13) {
  3468. pt.checkNetwork();
  3469. pt.startLoading();
  3470. pt.check(false);
  3471. }
  3472. });
  3473. var ua = navigator.userAgent.toLowerCase(),
  3474. noOnekey = pt.isWX || pt.isMQQ || ua.match(/meizu_m9|IEMobile/i) ||
  3475. window.ptui_appid == 46000101 // 微博
  3476. ||
  3477. $.bom.query("pt_no_onekey") == 1 //业务主动隐藏了一键登录
  3478. ||
  3479. pt.s_url.indexOf('//openmobile.qq.com/api/check') >= 0; // 互联定向分享隐藏一键登录,因为是没有安装手Q才打开ptlogin登录
  3480. var btnOnekey = pt.btnOnekey;
  3481. if (!noOnekey && btnOnekey) {
  3482. if (pt.isHulian) { // 互联 xlogin 35 需要等授权页加载完成才判断
  3483. if (ua.match(/iphone|ipad/i)) {
  3484. // fix ios webview bug: 输入框获得焦点时,滚动页面结束后再输入,将无法输入
  3485. document.addEventListener("touchmove", function() { pt.btnGo.focus() }, false);
  3486. document.addEventListener("touchstart", function(e) {
  3487. if (pt.uInput != e.target || pt.pInput != e.target) { pt.btnGo.focus(); }
  3488. }, false);
  3489. }
  3490. pt.open.waiting('authlist', function() {
  3491. MTT.canOneKey(function() {
  3492. if (pt.get_qlogin_list().length) return; // 如果已经出现头像,以头像快速登录优先
  3493. pt.showOneKey(true);
  3494. }, function() {
  3495. if (window.hlhdFlag) {
  3496. pt.showOneKey();
  3497. } else {
  3498. pt.hideOneKey();
  3499. }
  3500. });
  3501. });
  3502. } else {
  3503. if (self === top && MTT.version) { // 浏览器既然可以判断,那就精确判断
  3504. MTT.canOneKey(function() {
  3505. if (pt.get_qlogin_list().length) return; // 如果已经出现头像,以头像快速登录优先
  3506. // pt.showOneKey('justshow'); alice修改
  3507. pt.showOneKey();
  3508. }, function() {
  3509. // pt.hideOneKey();
  3510. pt.showOneKey();
  3511. });
  3512. } else { // 否则默认显示一键登录, PC 上不显示了
  3513. var ua = navigator.userAgent;
  3514. var desktop = ua.indexOf("Windows NT") > -1 || ua.indexOf("Macintosh") > -1;
  3515. desktop || pt.isWtlogin || pt.showOneKey();
  3516. }
  3517. }
  3518. } else {
  3519. pt.hideOneKey();
  3520. }
  3521. $('show_pwd') && $.e.add($('show_pwd'), 'change', function(e) {
  3522. var pwd = pt.pInput;
  3523. if (this.checked) {
  3524. pwd.setAttribute('type', 'text');
  3525. } else {
  3526. pwd.setAttribute('type', 'password');
  3527. }
  3528. });
  3529. $('forgetpwd') && $.e.add($('forgetpwd'), pt.clickEvent, function(e) {
  3530. var uin = pt.uInput && pt.uInput.value;
  3531. var url = "https://ssl.ptlogin2.qq.com/ptui_forgetpwd_mobile?ptlang=" + pt.lang_num;
  3532. if (pt.lang_num != "1033")
  3533. url += "&account=" + uin;
  3534. window.open(url);
  3535. });
  3536. $.e.add(window, "orientationchange", function(e) {
  3537. //页面回复原形
  3538. pt.hideURLBar(e);
  3539. });
  3540. if (pt.isMail) {
  3541. var rem = $("remember");
  3542. if (!rem) return;
  3543. $.e.add(rem, "change", function() {
  3544. if (rem.checked)
  3545. pt.s_url = pt.addParamToUrl(pt.s_url, "ss", 1);
  3546. else
  3547. pt.s_url = pt.s_url.replace(/&?ss=1/, "");
  3548. pt.low_login_enable = rem.checked ? 1 : 0;
  3549. });
  3550. }
  3551. if ($('download-link') && $('download-area')) {
  3552. $.e.add($('download-area'), 'click', function(e) {
  3553. if (e.target !== $('download-link'))
  3554. $('download-link').click();
  3555. return false;
  3556. });
  3557. var rule_cn = [
  3558. [/android/i, "market://details?id=com.tencent.mobileqq"],
  3559. [/ipad|iphone/i, "itms-apps://itunes.apple.com/us/app/qq/id444934666?mt=8"]
  3560. ];
  3561. var rule_i18n = [
  3562. [/android/i, "market://details?id=com.tencent.mobileqqi"],
  3563. [/ipad|iphone/i, "itms-apps://itunes.apple.com/us/app/qq-international/id710380093?mt=8"]
  3564. ];
  3565. switch (parseInt(ptui_lang)) {
  3566. case 1033:
  3567. case 1028:
  3568. for (var i in rule_cn) {
  3569. if (rule_i18n[i][0].test(navigator.userAgent)) {
  3570. $('download-link').href = (rule_i18n[i][1]);
  3571. break;
  3572. }
  3573. }
  3574. if ($('download-link').href.length == 0) {
  3575. $('download-link').href = ("http://www.imqq.com/?lang=" + ptui_lang);
  3576. }
  3577. break;
  3578. default:
  3579. for (var i in rule_cn) {
  3580. if (rule_cn[i][0].test(navigator.userAgent)) {
  3581. $('download-link').href = (rule_cn[i][1]);
  3582. break;
  3583. }
  3584. }
  3585. if ($('download-link').href.length == 0) {
  3586. $('download-link').href = ("https://im.qq.com");
  3587. }
  3588. break;
  3589. }
  3590. var ua = navigator.userAgent;
  3591. if (/ipad/i.test(ua)) {
  3592. $('download-link-pad').href = "itms-apps://itunes.apple.com/cn/app/qq-hd-2011/id453718989?mt=8";
  3593. } else if (/android/i.test(ua) && !/mobile/i.test(ua)) {
  3594. $('download-link-pad').href = "market://details?id=com.tencent.minihd.qq";
  3595. } else {
  3596. $('download-link-pad').href = $('download-link').href;
  3597. }
  3598. }
  3599. if ($('qrlogin_switch')) {
  3600. $.e.add($('qrlogin_switch'), 'click', function() {
  3601. pt.switchpwd();
  3602. return false;
  3603. });
  3604. }
  3605. $('qr_invalid') && $.e.add($('qr_invalid'), 'click', function() {
  3606. pt.qrcode.get(0);
  3607. $.css.hide($('qr_invalid'));
  3608. });
  3609. //优化移动端聚焦体验
  3610. document.body.addEventListener('focus', function(e) {
  3611. if (e.target.scrollIntoViewIfNeeded)
  3612. e.target.scrollIntoViewIfNeeded();
  3613. else if (e.target.scrollIntoView)
  3614. e.target.scrollIntoView();
  3615. }, true);
  3616. if ($('switcher_qlogin')) {
  3617. $.e.add($('switcher_qlogin'), 'click', function() {
  3618. pt.switchqr();
  3619. return false;
  3620. })
  3621. }
  3622. setTimeout(function() {
  3623. if (window.ptui_tab) {
  3624. //邮箱appid暂时不跳转到qr框
  3625. if (window.ptui_appid != 756044602) {
  3626. //初始化二维码
  3627. pt.qrcode.get(0);
  3628. } else {
  3629. pt.switchpwd();
  3630. }
  3631. }
  3632. }, 0)
  3633. },
  3634. //输入框事件绑定
  3635. bindInput: function() {
  3636. if (pt.isOffice) return; // 办公互联没有输入框
  3637. //帐号框初始化值
  3638. var last_uin = window.ptui_defuin || pt.lockedAccount || pt.getLastUin();
  3639. //现在有主页面的输入框和 手机号页面的输入框
  3640. var uInput = pt.uInput,
  3641. pInput = pt.pInput,
  3642. uDel = $("del_touch") || $("del_u"),
  3643. pDel = $("del_touch_p") || $("del_p"),
  3644. //手机页面元素
  3645. phoneInput = $('phone'),
  3646. passwordInput = $('password'),
  3647. phoneDel = $('del_phone'),
  3648. passwordDel = $('del_password');
  3649. var showDelWrapper = function(elem, isShow, outer, resize) {
  3650. return function(e) {
  3651. isShow ? elem && $.css.show(elem) : elem && $.css.hide(elem);
  3652. if (resize) {
  3653. outer && (outer.style.paddingRight = (isShow ? "20px" : ""));
  3654. }
  3655. }
  3656. };
  3657. var showUDel = showDelWrapper(uDel, true, uDel.parentNode, ptui_style == 42),
  3658. hideUDel = showDelWrapper(uDel, false, uDel.parentNode, ptui_style == 42),
  3659. showPDel = showDelWrapper(pDel, true, pDel.parentNode, ptui_style == 42),
  3660. hidePDel = showDelWrapper(pDel, false, pDel.parentNode, ptui_style == 42),
  3661. showPhoneDel = showDelWrapper(phoneDel, true, phoneDel.parentNode, true),
  3662. hidePhoneDel = showDelWrapper(phoneDel, false, phoneDel.parentNode, true),
  3663. showPasswordDel = showDelWrapper(passwordDel, true, passwordDel.parentNode, true),
  3664. hidePasswordDel = showDelWrapper(passwordDel, false, passwordDel.parentNode, true);
  3665. if (last_uin) {
  3666. if (last_uin == "0") uInput.value = "";
  3667. else uInput.value = uInput.value || last_uin;
  3668. }
  3669. if (pt.lockedAccount) {
  3670. uInput.readOnly = true;
  3671. pInput.focus();
  3672. //锁定帐号的时候不再显示删除uin的按钮
  3673. hideUDel();
  3674. showUDel = function() {};
  3675. }
  3676. var inputWrapper = function(showFunction, hideFunction, password) {
  3677. return function(event) {
  3678. if (pt.lockedAccount && !password) return;
  3679. var element = event.target;
  3680. if (event.target.value != "")
  3681. showFunction()
  3682. else
  3683. hideFunction();
  3684. if (password) {
  3685. var caretPos = 0;
  3686. if (element.selectionStart || element.selectionStart == '0') {
  3687. caretPos = Math.max(element.selectionStart, element.selectionEnd);
  3688. }
  3689. if (window.openSDK && window.openSDK.curPosFromJS) {
  3690. window.openSDK.curPosFromJS(caretPos);
  3691. }
  3692. }
  3693. }
  3694. }
  3695. var focusWrapper = function(showFunction, password) {
  3696. return function(event) {
  3697. if (event.target.value != "")
  3698. showFunction();
  3699. if (password) {
  3700. if (window.openSDK && window.openSDK.isPasswordEdit) {
  3701. window.openSDK.isPasswordEdit(1);
  3702. }
  3703. }
  3704. }
  3705. };
  3706. var blurWrapper = function(hideFunction, password, checkUin) {
  3707. return function(event) {
  3708. if (event.target.value == "")
  3709. hideFunction();
  3710. if (password) {
  3711. if (window.openSDK && window.openSDK.isPasswordEdit) {
  3712. window.openSDK.isPasswordEdit(0);
  3713. }
  3714. } else {
  3715. if (/^\+/.test(event.target.value)) { // 海外手机+号修正
  3716. event.target.value = event.target.value.replace(/^\+/, '');
  3717. if (!/^00/.test(event.target.value))
  3718. event.target.value = '00' + event.target.value;
  3719. }
  3720. if (event.target.value == "") {
  3721. hideFunction();
  3722. } else if (checkUin) {
  3723. pt.checkQQUin(event.target.value); //TODO 手机号
  3724. }
  3725. }
  3726. }
  3727. }
  3728. $.e.add(pInput, "focus", focusWrapper(showPDel, true));
  3729. $.e.add(pInput, "blur", blurWrapper(hidePDel, true));
  3730. $.e.add(pInput, "input", function(e) {
  3731. window.setTimeout(function() {
  3732. inputWrapper(showPDel, hidePDel, true)(e)
  3733. }, 0);
  3734. });
  3735. $.e.add(uInput, "focus", focusWrapper(showUDel));
  3736. $.e.add(uInput, "blur", blurWrapper(hideUDel, false, true));
  3737. $.e.add(uInput, "input", inputWrapper(showUDel, hideUDel));
  3738. $.e.add(passwordInput, "focus", focusWrapper(showPasswordDel, true));
  3739. $.e.add(passwordInput, "blur", blurWrapper(hidePasswordDel, true));
  3740. $.e.add(passwordInput, "input", function(e) {
  3741. window.setTimeout(function() {
  3742. inputWrapper(showPasswordDel, hidePasswordDel, true)(e)
  3743. }, 0);
  3744. });
  3745. $.e.add(phoneInput, "focus", focusWrapper(showPhoneDel));
  3746. $.e.add(phoneInput, "blur", blurWrapper(hidePhoneDel, false, false));
  3747. $.e.add(phoneInput, "input", inputWrapper(showPhoneDel, hidePhoneDel));
  3748. var delWrapper = function(input, hideFunction, password) {
  3749. return function(e) {
  3750. e && e.preventDefault();
  3751. input.value = "";
  3752. if (password) {
  3753. if (window.openSDK && window.openSDK.clearAllEdit) {
  3754. window.openSDK.clearAllEdit();
  3755. }
  3756. }
  3757. input.focus();
  3758. hideFunction();
  3759. }
  3760. }
  3761. uDel && $.e.add(uDel, "click", delWrapper(uInput, hideUDel));
  3762. pDel && $.e.add(pDel, "click", delWrapper(pInput, hidePDel, true));
  3763. phoneDel && $.e.add(phoneDel, "click", delWrapper(phoneInput, hidePhoneDel));
  3764. passwordDel && $.e.add(passwordDel, "click", delWrapper(passwordInput, hidePasswordDel));
  3765. },
  3766. //绑定验证码区域事件
  3767. bindVcodeEvent: function() {
  3768. $("input_tips") && $.e.add($("input_tips"), "click", function(e) {
  3769. $("vcode_input").focus();
  3770. $.css.hide("input_tips");
  3771. e.stopPropagation();
  3772. });
  3773. $("vcode_input") && $.e.add($("vcode_input"), "focus", function(e) {
  3774. $.css.hide("input_tips");
  3775. e.stopPropagation();
  3776. });
  3777. $("vcode_input") && $.e.add($("vcode_input"), "blur", function(e) {
  3778. if (this.value == "") {
  3779. $.css.show("input_tips");
  3780. }
  3781. });
  3782. $("vcode_img") && $.e.add($("vcode_img"), "click", function(e) {
  3783. $("vcode_input").focus();
  3784. $.css.hide("input_tips");
  3785. pt.changeCodeImg();
  3786. e.stopPropagation();
  3787. });
  3788. $("submit") && $.e.add($("submit"), "click", function(e) {
  3789. pt.submitVcode();
  3790. });
  3791. },
  3792. //隐藏地址栏
  3793. hideURLBar: function() {
  3794. window.setTimeout(function() {
  3795. window.scrollTo(0, 1);
  3796. }, 0);
  3797. },
  3798. // 根据当前页面状态摆放记住登录按钮的位置
  3799. showAutoLogin: function() { // todo 设置pagestate 常量
  3800. if (!pt.isMail) return;
  3801. var autoLogin = $("auto_login");
  3802. if (!autoLogin) return;
  3803. var btnGo = pt.btnGo;
  3804. if (pt.pageState == 1) {
  3805. $("web_login").insertBefore(autoLogin, btnGo);
  3806. } else {
  3807. var qlogin = $("q_login");
  3808. qlogin.insertBefore(autoLogin, qlogin.lastChild);
  3809. }
  3810. $.css.show(autoLogin);
  3811. },
  3812. doOneKey: function(e) {
  3813. // 防止短时间内重复点击
  3814. if (pt.doOneKey.ing) return;
  3815. pt.doOneKey.ing = true;
  3816. setTimeout(function() { pt.doOneKey.ing = false; }, 5000);
  3817. var ua = navigator.userAgent.toLowerCase();
  3818. var p = pt.loginUrl + 'jump?u1=' + encodeURIComponent(pt.s_url) + "&pt_report=1";
  3819. if(window.pt_ptdrvs){
  3820. p += "&ptdrvs=" + window.pt_ptdrvs;
  3821. }
  3822. if (window.ptui_pt_ttype == "1") {
  3823. p += "&pt_ttype=1";
  3824. }
  3825. if (window.ptui_daid) {
  3826. p += ("&daid=" + ptui_daid);
  3827. }
  3828. if (pt.low_login_enable) {
  3829. p += "&low_login_enable=1&low_login_hour=" + window.ptui_low_login_hour;
  3830. }
  3831. p += "&style=" + window.ptui_style;
  3832. var browser = $.detectBrowser()[0];
  3833. if (browser) {
  3834. p += "&pt_ua=" + $.Encryption.md5(ua);
  3835. p += "&pt_browser=" + browser;
  3836. }
  3837. var appname = $.bom.query("pt_appname");
  3838. if (appname) // 在手Q上展示应用名称
  3839. p += "&pt_appname=" + appname;
  3840. var pkg = $.bom.query("pt_package");
  3841. if (/android/i.test(navigator.userAgent)) {
  3842. if (pkg) // 在手Q上展示应用图标,复用申请快速登录所有图标
  3843. p += "&pt_package=" + pkg;
  3844. } else {
  3845. var bundleID = $.bom.query("pt_bundleid") || pkg; // 有可能ios和android包名相同,所以可以省略pt_bundleid
  3846. if (bundleID)
  3847. p += "&pt_bundleid=" + bundleID;
  3848. }
  3849. $.report.monitor(414090);
  3850. qqMusicReport('83886593', 33616325); //QQ音乐一键登录上报
  3851. if (pt.isHulian) {
  3852. pt.open.waiting('authdata', function() {
  3853. if (window.ptui_pt_3rd_aid) { // for 互联
  3854. p += "&pt_3rd_aid=" + window.ptui_pt_3rd_aid;
  3855. }
  3856. if (pt.submit_o.openlogin_data) {
  3857. p += "&pt_openlogin_data=" + pt.submit_o.openlogin_data;
  3858. }
  3859. OneKey('wtloginmqq://ptlogin/qlogin?p=' + encodeURIComponent(p));
  3860. });
  3861. } else {
  3862. OneKey('wtloginmqq://ptlogin/qlogin?p=' + encodeURIComponent(p));
  3863. }
  3864. },
  3865. /**
  3866. * [addToSet 数组模拟集合的添加]
  3867. * @param {[type]} list [description]
  3868. * @param {[type]} o [description]
  3869. */
  3870. addToSet: function(list, o) {
  3871. if (!o) {
  3872. } else {
  3873. var id = o["uin"];
  3874. var needAdd = true;
  3875. for (var i = 0, length = list.length; i < length; i++) {
  3876. if (list[i]["uin"] == id) {
  3877. needAdd = false;
  3878. }
  3879. }
  3880. if (needAdd) {
  3881. list.push(o);
  3882. }
  3883. }
  3884. },
  3885. //获取快速登录帐号信息
  3886. get_qlogin_list: function() {
  3887. var qlogin_list = [];
  3888. //互联cookie登录
  3889. if (pt.isHulian) {
  3890. if (pt.cookieInfo) {
  3891. pt.addToSet(qlogin_list, pt.cookieInfo);
  3892. }
  3893. } else {
  3894. if (pt.authInfo) {
  3895. pt.addToSet(qlogin_list, pt.authInfo);
  3896. }
  3897. }
  3898. if (pt.qqBrowserInfo) {
  3899. pt.addToSet(qlogin_list, pt.qqBrowserInfo);
  3900. }
  3901. return qlogin_list;
  3902. },
  3903. /**
  3904. * [qlogin_submit 快速登录提交]
  3905. *
  3906. */
  3907. qlogin_submit: function(cgi) {
  3908. $.report.monitor(259519); //手Q快速登录统计
  3909. var s_url = encodeURIComponent(pt.s_url);
  3910. var pt_url;
  3911. if (cgi == pt.qrcode.CGI) {
  3912. pt_url = pt.loginUrl + cgi + "?u1=" + s_url;
  3913. pt_url += "&from_ui=1&type=1&ptlang=" + pt.lang_num;
  3914. pt_url += "&ptqrtoken=" + $.str.hash33($.cookie.get("qrsig"));
  3915. } else if (cgi == "mqq") {
  3916. pt_url = (pt.isHttps ? "https://ssl." : "http://") + "ptlogin2.qq.com/jump?clientuin=$UIN&clientkey=$KEY&keyindex=$KEYINDEX&u1=" + encodeURIComponent(pt.s_url);
  3917. } else {
  3918. var uin = pt.qqBrowserInfo.uin;
  3919. var clientkey = pt.qqBrowserInfo.loginkey;
  3920. pt_url = pt.loginUrl + "jump?keyindex=" + pt.keyindex + "&clientuin=" + uin + "&clientkey=" + clientkey + "&u1=" + s_url;
  3921. }
  3922. if (window.ptui_daid)
  3923. pt_url += "&daid=" + window.ptui_daid;
  3924. if (window.ptui_appid)
  3925. pt_url += "&aid=" + window.ptui_appid;
  3926. if (window.ptui_pt_qzone_sig == "1") {
  3927. pt_url += "&pt_qzone_sig=1";
  3928. }
  3929. if (window.ptui_pt_ttype == "1") {
  3930. pt_url += "&pt_ttype=1";
  3931. }
  3932. if (window.ptui_pt_light == "1") {
  3933. pt_url += "&pt_light=1";
  3934. }
  3935. if (pt.low_login_enable) {
  3936. pt_url += "&low_login_enable=1&low_login_hour=" + window.ptui_low_login_hour;
  3937. }
  3938. if (window.ptui_pt_3rd_aid) { // for 互联
  3939. pt_url += "&pt_3rd_aid=" + window.ptui_pt_3rd_aid;
  3940. }
  3941. if (pt.submit_o.openlogin_data) {
  3942. pt_url += "&pt_openlogin_data=" + pt.submit_o.openlogin_data;
  3943. }
  3944. if (window.ptui_kf_csimc != "0" && window.ptui_kf_csimc) {
  3945. pt_url += "&csimc=" + ptui_kf_csimc;
  3946. pt_url += "&csnum=" + ptui_kf_csnum;
  3947. pt_url += "&authid=" + ptui_kf_authid;
  3948. }
  3949. pt_url += "&device=" + pt.deviceType;
  3950. if (cgi != "mqq") pt_url += "&ptopt=1";
  3951. pt_url += "&pt_uistyle=" + window.ptui_style;
  3952. if (cgi) return pt_url;
  3953. $.http.loadScript(pt_url);
  3954. },
  3955. /**
  3956. * [cookielogin_submit 快速登录提交]
  3957. * @return {[type]} [description]
  3958. */
  3959. cookielogin_submit: function() {
  3960. var superkey = pt.cookieInfo.superkey;
  3961. if (superkey) {
  3962. var superkey_token = superkey && $.str.hash33(superkey);
  3963. pt.submit_o.auth_token = superkey_token;
  3964. pt.submit('open');
  3965. } else {
  3966. if (pt.mqqCanQLogin()) {
  3967. pt.redirect(pt.target, pt.qlogin_submit("mqq"));
  3968. }
  3969. }
  3970. },
  3971. /**
  3972. * [cancel_cookielogin 取消cookie快速登录]
  3973. */
  3974. cancel_cookielogin: function(clear) {
  3975. try {
  3976. $.css.show($("form_outter_wrap"));
  3977. $.css.hide($("q_logon_list"));
  3978. } catch (e) {}
  3979. pt.cookieLogin = false;
  3980. delete pt.submit_o['skey_token'];
  3981. pt.cookieInfo = null;
  3982. //清除帐号输入框
  3983. if (clear)
  3984. pt.uInput.value = "";
  3985. },
  3986. authlogin_submit: function() {
  3987. var authUrl = pt.authLoginUrl;
  3988. authUrl += "&regmaster=" + window.ptui_regmaster + "&aid=" + window.ptui_appid + "&s_url=" + encodeURIComponent(pt.s_url);
  3989. if (pt.low_login_enable) {
  3990. authUrl += "&low_login_enable=1&low_login_hour=" + window.ptui_low_login_hour;
  3991. }
  3992. //pt_ttype 是否下发vkey,现在已不使用
  3993. if (window.ptui_pt_ttype == "1") {
  3994. authUrl += "&pt_ttype=1";
  3995. }
  3996. //pt_light 是否下发superkey和skey
  3997. if (window.ptui_pt_light == "1") {
  3998. authUrl += "&pt_light=1";
  3999. }
  4000. authUrl += "&device=" + pt.deviceType;
  4001. //top.location.href = authUrl
  4002. pt.redirect(pt.target, authUrl);
  4003. },
  4004. /**
  4005. * jsonp的方式提交登录表单
  4006. * @prama vcode 是否需要验证码
  4007. */
  4008. submit: function(vcode) {
  4009. var u_input = pt.uInput,
  4010. p_input = pt.is_oversea ? $('password') : pt.pInput;
  4011. //get 参数
  4012. var uin = ""; //uin
  4013. var pwd = ""; //原始密码
  4014. //这个来自check的cgi的返回,由于chrome的samesite策略,导致cookie中的ptdrvs可能种不上,这里在jsonp返回中获取并设置到全局变量上
  4015. if(window.pt_ptdrvs){
  4016. pt.submit_o['ptdrvs'] = window.pt_ptdrvs || ''; //参数也传ptdrvs,兜底
  4017. }
  4018. //如果是快速登录,帐号和密码
  4019. if (pt.is_qlogin) {
  4020. uin = pt.login_uin; //uin
  4021. } else {
  4022. uin = pt.needAt ? pt.needAt : u_input && u_input.value; //uin
  4023. pt.login_uin = uin;
  4024. //QQ音乐帐号密码登录上报
  4025. qqMusicReport("33616396", 33616396);
  4026. }
  4027. //////构造submit对象
  4028. if (vcode) {
  4029. //免验证码的时候不带这个参数
  4030. pt.submit_o["pt_vcode_v1"] = 0;
  4031. pt.submit_o["pt_verifysession_v1"] = pt.verifysession;
  4032. }
  4033. pt.submit_o.verifycode = pt.vcode.toUpperCase(); //验证码 必须
  4034. pt.submit_o.u = uin;
  4035. var isMd5 = false;
  4036. if (window.openSDK && openSDK.md5Pwd && openSDK.result == 0) {
  4037. pwd = openSDK.md5Pwd;
  4038. isMd5 = true;
  4039. } else {
  4040. pwd = p_input && p_input.value; //原始密码
  4041. isMd5 = false;
  4042. }
  4043. if (vcode != 'open')
  4044. pt.submit_o.p = $.Encryption.getEncryption(pwd, pt.salt, pt.submit_o.verifycode, isMd5); //要提交给后台的密码形式
  4045. else
  4046. delete pt.submit_o.p;
  4047. pt.submit_o.pt_randsalt = pt.isRandSalt || 0;
  4048. pt.submit_o.ptlang = pt.lang_num; //版本语种 必须
  4049. pt.submit_o.low_login_enable = (pt.low_login_enable == 1) ? 1 : 0; //是否自动登录
  4050. if (pt.submit_o.low_login_enable) {
  4051. pt.submit_o.low_login_hour = window.ptui_low_login_hour; //弱登录默认一个月
  4052. }
  4053. pt.submit_o.u1 = encodeURIComponent(pt.s_url); //成功url 必须
  4054. pt.submit_o.from_ui = 1;
  4055. pt.submit_o.fp = "loginerroralert";
  4056. pt.submit_o.device = pt.deviceType; //设备类型
  4057. pt.submit_o.aid = pt.appid; //接入业务的appid 必须
  4058. if (window.ptui_daid) {
  4059. pt.submit_o.daid = window.ptui_daid; //接入业务的appid 必须
  4060. }
  4061. if (window.ptui_pt_qzone_sig == "1") {
  4062. pt.submit_o.pt_qzone_sig = 1;
  4063. }
  4064. if (window.ptui_pt_ttype == "1") {
  4065. pt.submit_o.pt_ttype = "1";
  4066. }
  4067. if (window.ptui_pt_light == "1") {
  4068. pt.submit_o.pt_light = "1";
  4069. }
  4070. if (window.ptui_pt_3rd_aid) {
  4071. pt.submit_o.pt_3rd_aid = window.ptui_pt_3rd_aid;
  4072. }
  4073. pt.submit_o.ptredirect = pt.target;
  4074. pt.submit_o.h = 1;
  4075. pt.submit_o.g = 1; //加盐了
  4076. pt.submit_o.pt_uistyle = window.ptui_style;
  4077. if (window.ptui_kf_csimc != "0" && window.ptui_kf_csimc) {
  4078. pt.submit_o.csimc = ptui_kf_csimc;
  4079. pt.submit_o.csnum = ptui_kf_csnum;
  4080. pt.submit_o.authid = ptui_kf_authid;
  4081. }
  4082. pt.submit_o.regmaster = window.ptui_regmaster;
  4083. var param = pt.object2param(pt.submit_o);
  4084. //如果验证码为空(需要验证码),跳到验证码页面
  4085. if (!vcode) {
  4086. pt.showVcode();
  4087. pt.isSubmiting = false; //提交结束
  4088. } else {
  4089. console.log('login--',vcode)
  4090. pt.checkNetwork();
  4091. pt.startLoading();
  4092. var cgi = pt.isHulian ? 'pt_open_login' : 'login';
  4093. var url = pt.loginUrl + cgi + "?" + param;
  4094. //这里延迟100ms发出请求,因为有人说这样能解决他们的bug,只能试试了
  4095. setTimeout(function(){
  4096. if(cgi === 'login'){
  4097. // 如果是login,先存起来备用
  4098. pt.smsLoginUrl = url
  4099. }
  4100. $.http.loadScript(url); //回调 ptuiCB方法
  4101. },100)
  4102. }
  4103. return false;
  4104. },
  4105. smsSubmit: function(){
  4106. // pt.submit('sms')
  4107. var url = pt.smsLoginUrl
  4108. pt.isloading = true
  4109. if(url){
  4110. if($.cookie.get("pt_sms")){
  4111. url += '&pt_sms_code='+ $.cookie.get("pt_sms")
  4112. }
  4113. $.http.loadScript(url);
  4114. }
  4115. },
  4116. /**
  4117. * 用户点击确定,jsonp回调方法
  4118. *
  4119. * @param ret 登录状态主信息 0 成功
  4120. * @param extret 登录状态附加信息
  4121. * @param url 登录成功的跳转地址
  4122. * @param redirect 跳转方式 0:self 1:top 2:parent 手机端没用
  4123. * @param Mmsg 登录信息
  4124. * @param nick 登录成功的号码的昵称
  4125. */
  4126. cb: function(ret, extret, url, redirect, Mmsg, nick) {
  4127. pt.isSubmiting = false; //提交结束
  4128. if (pt.qrcode.used && [0, 65, 66, 67].indexOf(+ret) == -1) { // 上报二维码异常
  4129. $.report.monitor('2586869');
  4130. }
  4131. switch (+ret) {
  4132. case 0:
  4133. clearInterval(pt.qrcode.clock);
  4134. //如果自动登录,则保存到本地存储,
  4135. var loginUin = pt.uInput && pt.uInput.value; //输入的帐号
  4136. pt.saveLastUin(loginUin || "");
  4137. //密保模版
  4138. if (url.indexOf("/cgi-bin/mibao_vry") > -1) {
  4139. url += "&style=" + pt.style;
  4140. }
  4141. if (pt.isOffice && window.mqq && mqq.invoke) // 通知手Q
  4142. mqq.invoke("QQOfficeOpen", "checkApp", { appId: window.ptui_pt_3rd_aid });
  4143. if (pt.qrcode.used) {
  4144. pt.qrcode.done = true;
  4145. $.report.monitor('2136878');
  4146. }
  4147. pt.redirect(redirect, url);
  4148. return;
  4149. case 4: //验证码错误
  4150. pt.changeCodeImg();
  4151. break;
  4152. case 65: // 二维码已失效
  4153. clearInterval(pt.qrcode.clock);
  4154. $.report.monitor('2586868');
  4155. if (window.ptui_tab) {
  4156. $.css.show($('qr_invalid'));
  4157. if ($.bom.query("autorefresh") == "1") {
  4158. $('qr_invalid').click();
  4159. return;
  4160. }
  4161. } else
  4162. pt.showErr("一键登录超时,请重试。", 1000 * 1000);
  4163. return;
  4164. case 66:
  4165. case 67:
  4166. return;
  4167. case 10010:
  4168. // sms 验证码错误
  4169. pt.smsIframe.postMessage({msg:'smsError'})
  4170. break
  4171. case 10009:
  4172. $.cookie.set('pt_sms_phone',Mmsg,window.location.host, '/', 1000*60)
  4173. var ptdrvs = $.cookie.get('ptdrvs')
  4174. pt.smsPtdrvs = ptdrvs
  4175. var appid = $.url.getParam('appid')
  4176. var uin = $.cookie.get('pt_loginuin') || pt.uInput.value
  4177. var Iframe = $.iframe()
  4178. Iframe.init({
  4179. name:'verify',
  4180. id:'verify',
  4181. url: "https://ui.ptlogin2.qq.com/web/verify/iframe?uin=" + uin + "&appid=" + appid,
  4182. iframeStyle:'width: 100vw;height: 100vh;margin: 0px auto;position: absolute;top: 0;border: none;z-index:10',
  4183. smsSubmitEvent: pt.smsSubmit
  4184. })
  4185. pt.smsIframe = Iframe
  4186. break
  4187. default:
  4188. clearInterval(pt.qrcode.clock);
  4189. //其他错误返回我们的页面
  4190. pt.go_back();
  4191. }
  4192. //锁定帐号的时候不展示手机号入口
  4193. if (ret == 3 && !pt.is_oversea && [9, 35, 42].indexOf(parseInt(window.ptui_style)) !== -1 && !pt.lockedAccount){
  4194. pt.alert.show(Mmsg + '<br>' + STR_LANG.password_error_tips); //密码错误需要弹窗
  4195. }else if(ret == 10010 || ret == 10009){
  4196. ;
  4197. } else{
  4198. pt.showErr(Mmsg);
  4199. }
  4200. },
  4201. /**
  4202. * jsonp回调方法,判断是否需要验证码
  4203. *
  4204. * @param ret 0:不需要验证码 1:需要验证码
  4205. * @param code 需要验证码时,为加密串,拉取验证码需要带上
  4206. * 不需要用户填验证码时,需要自动带上的验证
  4207. */
  4208. cb_checkVC: function(ret, code, salt, verifysession, isRandSalt) { //code 原来获取验证码的时候需要带上,参数名为vc_type
  4209. //ret 0:正常不需要验证码;1:安全中心需要验证码;2:uin不存在;3:check内部错误
  4210. switch (ret + '') {
  4211. case '0':
  4212. pt.vcode = code || "abcd";
  4213. pt.verifysession = verifysession;
  4214. break;
  4215. case '1':
  4216. pt.vcode = '';
  4217. pt.cap_cd = code;
  4218. break;
  4219. case '2':
  4220. case '3':
  4221. break;
  4222. default:
  4223. break;
  4224. }
  4225. if (ret == 2) {
  4226. pt.showErr(pt.lang.err_uin);
  4227. return;
  4228. }
  4229. if (ret == 3) {
  4230. pt.showErr(pt.checkErr[ptui_lang]);
  4231. return;
  4232. }
  4233. pt.salt = salt;
  4234. pt.isRandSalt = isRandSalt;
  4235. //提交的时候根据验证码判断是否需要提交到后台
  4236. pt.submit(pt.vcode)
  4237. },
  4238. /**
  4239. * 到后台查询是否需要加载验证码,并在回调函数中确定是否提交
  4240. * @param 是否快速登录
  4241. */
  4242. check: function(is_qlogin) {
  4243. //避免多次提交
  4244. if (pt.isSubmiting) {
  4245. return;
  4246. }
  4247. pt.is_qlogin = is_qlogin;
  4248. //先前台验证 普通登录
  4249. if (!pt.is_qlogin) {
  4250. if (!pt.checkValidate()) {
  4251. clearTimeout(pt._timer);
  4252. pt.endLoading();
  4253. return;
  4254. }
  4255. }
  4256. var uin = "";
  4257. //如果是快速登录,帐号和密码
  4258. if (is_qlogin) {
  4259. uin = pt.login_uin; //uin
  4260. } else {
  4261. uin = pt.needAt ? pt.needAt : pt.uInput.value; //uin
  4262. }
  4263. var url = pt.checkUrl + "pt_tea=2&uin=" + uin + "&appid=" + pt.appid + "&ptlang=" + pt.lang_num + "&regmaster=" + window.ptui_regmaster + "&pt_uistyle=" + pt.style + "&r=" + Math.random();
  4264. if (window.TDC && TDC.getInfo && TDC.getInfo().tokenid)
  4265. url += "&pt_jstoken=" + TDC.getInfo().tokenid;
  4266. $.http.loadScript(url); // 回调cb_checkVC
  4267. return;
  4268. },
  4269. //检查uin和密码合法性
  4270. checkValidate: function() {
  4271. var f_u = pt.is_oversea ? $('phone') : pt.uInput; //帐号输入框
  4272. var f_p = pt.is_oversea ? $('password') : pt.pInput; //密码输入框
  4273. var u = f_u.value;
  4274. if (pt.is_oversea) {
  4275. u = '00' + $('country-code').innerHTML.replace(/[^0-9]/, '') + u;
  4276. u = u.replace('0086', ''); //国内手机号不需要加国家码
  4277. }
  4278. if (f_u.value == "") {
  4279. pt.showErr(pt.lang.no_uin, function() {
  4280. f_u.focus();
  4281. }); //"你还没有输入帐号!"
  4282. return false;
  4283. }
  4284. if (!pt.checkQQUin(u)) {
  4285. pt.showErr(pt.lang.err_uin, function() {
  4286. f_u.focus();
  4287. }); //"请输入正确的帐号!"
  4288. return false;
  4289. }
  4290. f_u.value = $.str.trim(f_u.value);
  4291. if (f_p.value == "") {
  4292. pt.showErr(pt.lang.no_password, function() {
  4293. f_p.focus();
  4294. }); //"你还没有输入密码!"
  4295. return false;
  4296. }
  4297. return true;
  4298. },
  4299. /**
  4300. * 检查QQ用户帐号是否合法(号码和email和中文)
  4301. */
  4302. checkQQUin: function(qquin) {
  4303. if (qquin.length == 0)
  4304. return false;
  4305. qquin = $.str.trim(qquin);
  4306. pt.needAt = "";
  4307. var tmp = $.check;
  4308. if ($.check.is_weibo_appid(pt.appid)) {
  4309. if (tmp.isQQ(qquin) || tmp.isMail(qquin)) {
  4310. return true;
  4311. } else if (tmp.isNick(qquin) || tmp.isName(qquin)) { //短昵称和中文帐号前加@
  4312. pt.needAt = "@" + encodeURIComponent(qquin);
  4313. return true;
  4314. } else if (tmp.isPhone(qquin)) { //手机号码前加@
  4315. pt.needAt = "@" + qquin.replace(/^(86|886)/, "");
  4316. return true;
  4317. } else if (tmp.isSeaPhone(qquin)) {
  4318. pt.needAt = "@00" + qquin.replace(/^(00)/, "");
  4319. if (/^(@0088609)/.test(pt.needAt)) {
  4320. pt.needAt = pt.needAt.replace(/^(@0088609)/, "@008869"); //碰到0088609开头的前端统一修正为008869 by harlantu
  4321. }
  4322. return true;
  4323. }
  4324. pt.needAt = "";
  4325. } else { //其他
  4326. if (tmp.isQQ(qquin) || qquin.match(/@/)) { //这里只要包含@就认为是邮箱 避免重复添加@qq.com
  4327. return true;
  4328. }
  4329. if (tmp.isPhone(qquin)) {
  4330. pt.needAt = "@" + qquin.replace(/^(86|886)/, "");
  4331. return true;
  4332. }
  4333. if (tmp.isForeignPhone(qquin)) {
  4334. pt.needAt = "@" + qquin;
  4335. }
  4336. //正常情况下不是qq号/邮箱/手机的都认为是邮箱名
  4337. pt.uInput.value = qquin + "@qq.com";
  4338. return true;
  4339. }
  4340. //国外手机
  4341. if (tmp.isForeignPhone(qquin)) {
  4342. pt.needAt = "@" + qquin;
  4343. return true;
  4344. }
  4345. if (tmp.isPaipaiDuokefu(qquin)) {
  4346. return true;
  4347. }
  4348. return false;
  4349. },
  4350. //检查验证码的合法性
  4351. checkVcode: function() {
  4352. var vcode = $("vcode_input");
  4353. if (vcode.value == "") {
  4354. pt.showErr(pt.lang.no_code); //"你还没有输入验证码!"
  4355. vcode.focus();
  4356. return false;
  4357. }
  4358. if (vcode.value.length < 4) {
  4359. pt.showErr(pt.lang.less_code); //"请输入完整的验证码!"
  4360. vcode.focus();
  4361. vcode.select();
  4362. return false;
  4363. }
  4364. if (!(/^[a-zA-Z0-9]+$/.test(vcode.value))) {
  4365. pt.showErr(pt.lang.err_code); //"请输入正确的验证码!"
  4366. vcode.focus();
  4367. vcode.select();
  4368. return false;
  4369. }
  4370. return true;
  4371. },
  4372. //点击头像
  4373. clickHeader: function(event, force) {
  4374. event.preventDefault();
  4375. if ((pt.isWtlogin || window.ptui_style == 35) && !force) return
  4376. var pNode = event.currentTarget;
  4377. var uin = pNode.getAttribute("id");
  4378. var type = pNode.getAttribute("type");
  4379. pt.login_uin = uin;
  4380. pt.login_pwd = pNode.getAttribute("pwd");
  4381. switch (type + "") {
  4382. case "1": //普通登录
  4383. pt.check(true);
  4384. break;
  4385. case "2": //qq浏览器快速登录
  4386. pt.qlogin_submit();
  4387. break;
  4388. case "3": //授权登录
  4389. pt.authlogin_submit();
  4390. break;
  4391. case "4": //互联登录头像
  4392. pt.cookielogin_submit();
  4393. break;
  4394. default:
  4395. pt.check(true);
  4396. }
  4397. },
  4398. //获取头像的回调函数,jsonp调用
  4399. //{"uin":"uin","url":"url"}
  4400. setHeader: function(json) {
  4401. //列表生成了,只需要修改头像地址即可
  4402. for (var o in json) {
  4403. if (json[o].url != "" && o != "") {
  4404. if ($("img_" + o)) {
  4405. $("img_" + o).src = json[o];
  4406. }
  4407. }
  4408. }
  4409. pt.hideURLBar();
  4410. },
  4411. //拉取头像
  4412. initFace: function() {
  4413. var qlogin_list_data = pt.qlogin_list_data;
  4414. var length = qlogin_list_data.length;
  4415. var protocol = pt.isHttps ? "https://ssl." : "http://";
  4416. for (var i = 0; i < length; i++) {
  4417. $.http.loadScript(protocol + "ptlogin2." + pt.domain + "/getface?appid=" + pt.appid + "&imgtype=3&encrytype=0&devtype=1&keytpye=0&uin=" + qlogin_list_data[i].uin + "&r=" + Math.random());
  4418. }
  4419. },
  4420. //拉取头像错误处理
  4421. face_error: function(img) {
  4422. if (img.src != pt.default_face_url) {
  4423. img.src = pt.default_face_url;
  4424. }
  4425. return false;
  4426. },
  4427. //获取长字符串的缩略字符,中间加...
  4428. getShortWord: function(element, str, width) {
  4429. str = str ? str : "";
  4430. var appendStr = "...";
  4431. element.innerHTML = str;
  4432. if (element.clientWidth <= width) {
  4433. } else {
  4434. var len = str.length;
  4435. var harfLen = Math.ceil(len / 2);
  4436. for (var i = 0; i < harfLen; i++) {
  4437. var left = str.substring(0, harfLen - i)
  4438. var right = str.substring(harfLen + i, len);
  4439. element.innerHTML = left + appendStr + right;
  4440. if (element.clientWidth <= width) {
  4441. element.title = str;
  4442. break;
  4443. }
  4444. var right = str.substring(harfLen + i + 1, len);
  4445. element.innerHTML = left + appendStr + right;
  4446. if (element.clientWidth <= width) {
  4447. element.title = str;
  4448. break;
  4449. }
  4450. }
  4451. }
  4452. element.style.width = width + "px";
  4453. },
  4454. /**
  4455. * 刷新验证码图片
  4456. */
  4457. changeCodeImg: function() {
  4458. if (pt.new_vcode) {} else {
  4459. var img = $("vcode_img");
  4460. var domain = pt.domain;
  4461. var verifycodeUrl = (pt.isHttps ? "https://ssl." : "http://") + "captcha." + domain + "/getimage";
  4462. //qq.com的https走安全中心的
  4463. if (pt.isHttps && domain != "qq.com" && domain != "tenpay.com") {
  4464. verifycodeUrl = "https://ssl.ptlogin2." + domain + "/ptgetimage";
  4465. }
  4466. verifycodeUrl += ("?aid=" + pt.appid + "&uin=" + pt.login_uin + "&v=" + Math.random());
  4467. img.src = verifycodeUrl;
  4468. }
  4469. },
  4470. newVCFirst: true,
  4471. //显示验证码页面
  4472. showVcode: function() {
  4473. //针对简体中文和支持postMessgae的切换到新版验证码
  4474. if (pt.new_vcode) {
  4475. $("content").style.display = "none";
  4476. $("new_vcode").style.display = "block";
  4477. if (pt.newVCFirst) {
  4478. pt.newVCFirst = false;
  4479. capInit($('new_vcode'), {
  4480. callback: pt.VCCallback,
  4481. showHeader: true,
  4482. uin: pt.login_uin,
  4483. capcd: pt.cap_cd
  4484. });
  4485. } else {
  4486. capRefresh({
  4487. uin: pt.login_uin,
  4488. capcd: pt.cap_cd
  4489. });
  4490. }
  4491. pt.ptui_notifySize();
  4492. } else {
  4493. $("login").style.display = "none";
  4494. $("vcode").style.display = "block";
  4495. //绑定验证码区域事件
  4496. pt.bindVcodeEvent();
  4497. //拉取验证码
  4498. pt.changeCodeImg();
  4499. }
  4500. pt.hideURLBar();
  4501. $("btn_app_down") && $.css.hide("btn_app_down");
  4502. },
  4503. go_back: function() {
  4504. $("content") && ($("content").style.display = "block");
  4505. $("login") && ($("login").style.display = "block");
  4506. $("vcode") && ($("vcode").style.display = "none");
  4507. $("new_vcode") && ($("new_vcode").style.display = "none");
  4508. },
  4509. //提交验证码
  4510. submitVcode: function() { // todo remove it
  4511. //避免多次提交
  4512. if (pt.isSubmiting) {
  4513. return;
  4514. }
  4515. if (!pt.checkVcode()) {
  4516. return false;
  4517. }
  4518. pt.submit_o.verifycode = $("vcode_input").value.toUpperCase(); //验证码 必须
  4519. var pwd = ""; //原始密码
  4520. var isMd5 = false;
  4521. if (window.openSDK && openSDK.md5Pwd && openSDK.result == 0) {
  4522. pwd = openSDK.md5Pwd;
  4523. isMd5 = true;
  4524. } else {
  4525. pwd = pt.pInput.value; //原始密码
  4526. isMd5 = false;
  4527. }
  4528. pt.submit_o.p = $.Encryption.getEncryption(pwd, pt.salt, pt.submit_o.verifycode, isMd5); //要提交给后台的密码形式
  4529. pt.submit_o.pt_randsalt = pt.isRandSalt || 0;
  4530. if (window.TDC && TDC.getInfo && TDC.getInfo().tokenid)
  4531. pt.submit_o.pt_jstoken = TDC.getInfo().tokenid;
  4532. var param = pt.object2param(pt.submit_o);
  4533. var cgi = pt.isHulian ? 'pt_open_login' : 'login';
  4534. var url = (pt.isHttps ? "https://ssl." : "http://") + "ptlogin2." + pt.domain + "/" + cgi + "?" + param;
  4535. $.http.loadScript(url); //回调 ptuiCB方法
  4536. },
  4537. /**
  4538. * [submitNewVcode 提交新的验证码]
  4539. * @param {[type]} data [description]
  4540. * @return {[type]} [description]
  4541. */
  4542. submitNewVcode: function(data) {
  4543. //$.cookie.set("verifysession", data.sig, pt.domain); //把cookie当成验证码图片的cookie set
  4544. pt.submit_o.verifycode = data.randstr.toUpperCase(); //验证码 必须
  4545. pt.submit_o.pt_vcode_v1 = 1;
  4546. pt.submit_o.pt_verifysession_v1 = data.ticket;
  4547. var pwd = ""; //原始密码
  4548. var isMd5 = false;
  4549. if (window.openSDK && openSDK.md5Pwd && openSDK.result == 0) {
  4550. pwd = openSDK.md5Pwd;
  4551. isMd5 = true;
  4552. } else {
  4553. pwd = pt.pInput.value; //原始密码
  4554. isMd5 = false;
  4555. }
  4556. pt.submit_o.p = $.Encryption.getEncryption(pwd, pt.salt, pt.submit_o.verifycode, isMd5); //要提交给后台的密码形式
  4557. pt.submit_o.pt_randsalt = pt.isRandSalt || 0;
  4558. if (window.ptui_kf_csimc != "0" && window.ptui_kf_csimc) {
  4559. pt.submit_o.csimc = ptui_kf_csimc;
  4560. pt.submit_o.csnum = ptui_kf_csnum;
  4561. pt.submit_o.authid = ptui_kf_authid;
  4562. }
  4563. var param = pt.object2param(pt.submit_o);
  4564. var cgi = pt.isHulian ? 'pt_open_login' : 'login';
  4565. var url = (pt.isHttps ? "https://ssl." : "http://") + "ptlogin2." + pt.domain + "/" + cgi + "?" + param;
  4566. if(cgi === 'login'){
  4567. pt.smsLoginUrl = url
  4568. }
  4569. pt.checkNetwork();
  4570. pt.startLoading();
  4571. $.http.loadScript(url); //回调 ptuiCB方法
  4572. },
  4573. /* 互联授权页面回调实现 */
  4574. open: {
  4575. timer: -1,
  4576. authListDone: false,
  4577. waiting: function(what, forFn) {
  4578. if (!forFn) return;
  4579. switch (what) {
  4580. case 'authlist':
  4581. if (pt.open.authListDone)
  4582. forFn();
  4583. else
  4584. pt.open.waiting.authlistFn = forFn;
  4585. break;
  4586. case 'authdata':
  4587. if (pt.submit_o.openlogin_data) {
  4588. forFn();
  4589. } else {
  4590. pt.open.getAuthData();
  4591. pt.open.waiting.authdataFn = forFn;
  4592. }
  4593. break;
  4594. }
  4595. },
  4596. authListReady: function(opt) {
  4597. pt.open.authListDone = true;
  4598. if (pt.open.waiting.authlistFn) {
  4599. pt.open.waiting.authlistFn();
  4600. pt.open.waiting.authlistFn = null;
  4601. }
  4602. opt = opt || {};
  4603. var superkey = window.ptui_daid && parseInt($.cookie.get("supertoken"));
  4604. if (superkey) opt.superkey = 1;
  4605. // 触发柔性逻辑
  4606. if (opt.pt_flex) window.pt_flex = 1;
  4607. if (opt.skey) opt.skey = +opt.skey;
  4608. window.pt_skey_valid = opt.skey;
  4609. if ((opt.skey == 1 || opt.superkey) || pt.qqBrowserInfo) {
  4610. pt.openCookieInfo = opt;
  4611. pt.refreshQloginUI();
  4612. pt.initFace();
  4613. }
  4614. //拉取完成之后立即拉取opendata
  4615. if (window.pt_flex)
  4616. pt.open.getData({ value: location.search.substr(1) + "&pt_flex=1" });
  4617. else
  4618. xMsg.call("connect", "getData", {}, pt.open.getData);
  4619. if (window.ptui_tab)
  4620. xMsg.call("connect", "hideList", {});
  4621. },
  4622. setFrameHeight: function(opt) {},
  4623. getData: function(data) {
  4624. clearTimeout(pt.open.timer);
  4625. pt.submit_o.openlogin_data = encodeURIComponent(data.value);
  4626. /* 就目前来说,只在一键登录处 just waiting authdata, 所以处理完及时返回,避免多余操作 */
  4627. if (pt.open.waiting.authdataFn) {
  4628. pt.open.waiting.authdataFn();
  4629. pt.open.waiting.authdataFn = null;
  4630. return;
  4631. }
  4632. },
  4633. getAuthData: function() {
  4634. if (!pt.open.authListDone){
  4635. // fix个bug:
  4636. // 看了一下逻辑,在2s内,授权列表还没加载出来,就立刻点击“一键登录”,会触发这个提示。但实际上等列表加载完,会自动执行回调,跳登录的。
  4637. // 就是过了2s后,授权列表没加载出来,也会自动触发柔性策略,自动执行回调,依然能成功登陆,所以没必要出现“授权列表加载失败”提示了
  4638. // 那就把这句话注释掉好了
  4639. // return pt.showErr("授权列表加载失败");
  4640. return;
  4641. }
  4642. pt.open.timer = setTimeout(function() {
  4643. pt.showErr("授权信息获取失败");
  4644. }, 3000);
  4645. },
  4646. fillAppInfo: function(res) { // cgi get_app_basicinfo jsonp callback
  4647. if (res && res.retcode == 0 && res.result && res.result.pc) {
  4648. var icon = res.result.pc.Logo100;
  4649. if (icon && icon.indexOf("http://") > -1)
  4650. icon = icon.replace("http://", "https://");
  4651. $("app_logo").style.backgroundImage = "url(" + icon + ")";
  4652. $("app_alias").innerHTML = res.result.pc.AppAlias;
  4653. }
  4654. },
  4655. loadAppInfo: function() {
  4656. $.http.loadScript("//openmobile.qq.com/api/get_app_info_by_id?callback=get_app_basicinfo&appid=" + window.ptui_pt_3rd_aid);
  4657. var path = window.ptui_pt_3rd_aid.toString();
  4658. while (path.length > 8) path = path.substr(path.length - 8);
  4659. while (path.length < 8) path = '0' + path;
  4660. path = path.replace(/(\w{2})/g, '$1/');
  4661. var adimgurl = '//i.gtimg.cn/open/app_icon/' + path + window.ptui_pt_3rd_aid + '_android_ad_0.jpg'
  4662. console.log(adimgurl)
  4663. var img = new Image;
  4664. img.onload = function() {
  4665. console.log(img);
  4666. var appinfo = document.getElementsByClassName('appinfo')[0]
  4667. if (!appinfo) return;
  4668. img.style.width = '100%';
  4669. img.style.borderTopLeftRadius = '0.5rem';
  4670. img.style.borderTopRightRadius = '0.5rem';
  4671. appinfo.style.padding = 0;
  4672. appinfo.style.fontSize = 0; // 避免有字体导致多出一行
  4673. appinfo.appendChild(img);
  4674. var app_logo = $('app_logo'),
  4675. app_alias = $('app_alias'),
  4676. app_comment = $('app_comment');
  4677. if (app_logo) app_logo.style.display = 'none';
  4678. if (app_alias) app_alias.style.display = 'none';
  4679. if (app_comment) app_comment.style.display = 'none';
  4680. }
  4681. img.src = adimgurl;
  4682. }
  4683. },
  4684. /**
  4685. * [crossMessage 跨域通信]
  4686. * @param {[type]} messasge [description]
  4687. * @return {[type]} [description]
  4688. */
  4689. crossMessage: function(message) {
  4690. //支持html5的消息传递
  4691. if (typeof window.postMessage != "undefined") {
  4692. var messasgeStr = $.str.json2str(message);
  4693. window.parent.postMessage(messasgeStr, "*");
  4694. }
  4695. },
  4696. ////////////////////////////以下为一些调用业务测的接口
  4697. //通知父窗口关闭
  4698. ptui_notifyClose: function(e) {
  4699. e && e.preventDefault();
  4700. var messasge = {};
  4701. messasge.action = "close";
  4702. pt.crossMessage(messasge);
  4703. },
  4704. ptui_notifySize: function(div) {
  4705. var message = {};
  4706. message.action = "resize";
  4707. if (div) {
  4708. var obj = $(div);
  4709. message.width = obj.offsetWidth || 1;
  4710. message.height = obj.offsetHeight || 1;
  4711. } else { // todo 出现拼图验证码,希望能回传全屏大小
  4712. message.width = 320;
  4713. message.height = 441;
  4714. }
  4715. pt.crossMessage(message);
  4716. },
  4717. //记录登录框访问次数,避免手Qkey过期时和业务之间死循环
  4718. accessCount: function() {
  4719. if (!$.localStorage.isSupport()) return 0;
  4720. return parseInt($.localStorage.get('accessCount'));
  4721. },
  4722. access: function() {
  4723. if (!$.localStorage.isSupport()) return;
  4724. try {
  4725. var count, lasttime, now;
  4726. now = new Date();
  4727. lasttime = new Date();
  4728. lasttime.setTime($.localStorage.get('lastAccessDate'));
  4729. if (Math.abs(now - lasttime) < 30 * 1000) {
  4730. count = parseInt($.localStorage.get('accessCount')) + 1;
  4731. } else {
  4732. count = 1;
  4733. }
  4734. $.localStorage.set('accessCount', count);
  4735. $.localStorage.set('lastAccessDate', now.getTime());
  4736. } catch (e) {
  4737. $.localStorage.set('accessCount', 1);
  4738. $.localStorage.set('lastAccessDate', new Date().getTime());
  4739. }
  4740. },
  4741. //style42用
  4742. switchpwd: function() {
  4743. $.css.show($('pwdlogin'));
  4744. pt.uInput && pt.uInput.focus();
  4745. $.css.hide($('qrlogin'));
  4746. $.css.show($('switch'));
  4747. $.css.show($('zc_feedback'));
  4748. pt.qrcode && clearInterval(pt.qrcode.clock);
  4749. },
  4750. switchqr: function() {
  4751. $.css.hide($('pwdlogin'));
  4752. $.css.show($('qrlogin'));
  4753. $.css.hide($('switch'));
  4754. $.css.hide($('zc_feedback'));
  4755. pt.qrcode.get(0);
  4756. },
  4757. //刷新qlogin页面,仅当处于快速登录页面 或切换到快速登录
  4758. refreshQloginUI: function() {
  4759. if (pt.isOffice)
  4760. pt.build_office_qlogin();
  4761. else if (!pt.isWtlogin && !pt.is3gNews)
  4762. pt.build_qlogin_list();
  4763. },
  4764. mqqCanQLogin: function() {
  4765. var ua = navigator.userAgent,
  4766. mqq = ua.match(/QQ\/(\d\.\d\.\d)/i);
  4767. if (mqq && mqq[1] >= "5.9") {
  4768. return true;
  4769. }
  4770. return false;
  4771. }
  4772. };
  4773. /**
  4774. * alert 提示能力
  4775. */
  4776. pt.alert = (function(){
  4777. let alertBackground=null;
  4778. let alertDiv = null
  4779. return {
  4780. show: function(message) {
  4781. if (!alertBackground) {
  4782. alertBackground = document.createElement("div");
  4783. alertBackground.className = 'qui-dialog-mask';
  4784. }
  4785. if (!alertDiv) {
  4786. alertDiv = document.createElement('div');
  4787. alertDiv.className = 'qui-dialog-box';
  4788. }
  4789. alertDiv.innerHTML = '<div class="qui-dialog-content">' + message + '</div><div class="qui-dialog-bottom" onclick="pt.alert.hide()">' + window.STR_LANG.close + '</div>';
  4790. document.body.appendChild(alertBackground);
  4791. document.body.appendChild(alertDiv);
  4792. },
  4793. hide: function() {
  4794. document.body.removeChild(alertBackground);
  4795. document.body.removeChild(alertDiv);
  4796. }
  4797. }
  4798. })()
  4799. pt.qrcode = {
  4800. CGI: 'ptqrlogin',
  4801. used: false,
  4802. done: false,
  4803. clock: 0,
  4804. get: function(type) {
  4805. var loginName = "ptqrshow";
  4806. var proto = pt.isHttps ? "https://ssl." : "http://";
  4807. var url = proto + "ptlogin2." + pt.domain + "/" + loginName + "?s=8&e=0&";
  4808. url += "appid=" + pt.appid + "&type=" + type + "&t=" + Math.random();
  4809. if (pt.daid) {
  4810. url += "&daid=" + pt.daid;
  4811. }
  4812. if (window.ptui_pt_3rd_aid) { // for 互联
  4813. url += "&pt_3rd_aid=" + window.ptui_pt_3rd_aid;
  4814. }
  4815. if (window.ptui_regmaster) {
  4816. url += '&regmaster=' + window.ptui_regmaster;
  4817. }
  4818. clearInterval(pt.qrcode.clock);
  4819. pt.checkNetwork();
  4820. if (type == 1) {
  4821. $.http.loadScript(url); // ptui_qrcode_CB
  4822. } else {
  4823. $.e.add($('qrimg'), 'error', function() {
  4824. $.css.show('qr_invalid');
  4825. });
  4826. $.e.add($('qrimg'), 'load', function() {
  4827. clearTimeout(pt._timer);
  4828. pt.qrcode.polling();
  4829. });
  4830. $('qrimg').src = url;
  4831. }
  4832. pt.qrcode.used = true;
  4833. pt.qrcode.done = false;
  4834. $.report.monitor('2136877');
  4835. },
  4836. polling: function(qrcode) {
  4837. clearInterval(pt.qrcode.clock);
  4838. pt.qrcode.clock = setInterval(function() {
  4839. var qrUrl = pt.qlogin_submit(pt.qrcode.CGI);
  4840. $.http.loadScript(qrUrl + "&r=" + Math.random());
  4841. }, 3000);
  4842. if (qrcode) {
  4843. var schema = pt.isIos ? "wtloginmqq3:" : "wtloginmqq:";
  4844. var dstUrl = schema + '//ptlogin/qlogin?qrcode=' + encodeURIComponent(qrcode) + '&schemacallback=' + encodeURIComponent('weixin://');
  4845. openApp(dstUrl);
  4846. }
  4847. }
  4848. };
  4849. function ptui_qrcode_CB(res) {
  4850. clearTimeout(pt._timer);
  4851. res && (res.ec == 0) && pt.qrcode.polling(res.qrcode);
  4852. }
  4853. function weixin_sig_cb() {
  4854. var callback = function() {
  4855. WeixinJSBridge.invoke('getInstallState', {
  4856. "packageName": "com.tencent.mobileqq",
  4857. "packageUrl": "mqq://"
  4858. }, function(res) {
  4859. var err_msg = res && res.err_msg;
  4860. var canOnekey;
  4861. if (err_msg && (canOnekey = err_msg.match(/:yes(?:_(\d+))?/))) {
  4862. var androidVersionCode = 336;
  4863. //pt_no_onekey用于关闭一键登录
  4864. if ((pt.isIPhone || (pt.isAndroid && canOnekey[1] >= androidVersionCode))&& $.bom.query('pt_no_onekey')!=='1')
  4865. pt.showOneKey('justshow');
  4866. }
  4867. });
  4868. };
  4869. if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") {
  4870. callback();
  4871. } else {
  4872. if (document.addEventListener) {
  4873. document.addEventListener("WeixinJSBridgeReady", callback, false);
  4874. } else if (document.attachEvent) {
  4875. document.attachEvent("WeixinJSBridgeReady", callback);
  4876. document.attachEvent("onWeixinJSBridgeReady", callback);
  4877. }
  4878. }
  4879. }
  4880. /*
  4881. * jsonp形式的调用,不可转移命名空间
  4882. * ret 0:不需要验证码 1:需要验证码
  4883. * code 需要验证码时,为加密串,拉取验证码需要带上
  4884. * 不需要用户填验证码时,需要自动带上的验证码
  4885. *
  4886. * @param {*} ptdrvs 这个用于在iframe内无法下发cookie的时候作为兜底逻辑
  4887. */
  4888. function ptui_checkVC(ret, code, salt, verifysession, isRandSalt,ptdrvs) {
  4889. if (!pt.isloading) return; //check已经超时就不要处理了
  4890. clearTimeout(pt._timer);
  4891. pt.endLoading();
  4892. window.pt_ptdrvs = ptdrvs || ''; //前面加个pt的前缀防止冲突 pt_ptdrvs
  4893. if (window.openSDK && openSDK.getMD5FromNative) {
  4894. openSDK.getMD5FromNative(function() {
  4895. pt.cb_checkVC(ret, code, salt, verifysession, isRandSalt);
  4896. })
  4897. } else {
  4898. pt.cb_checkVC(ret, code, salt, verifysession, isRandSalt);
  4899. }
  4900. }
  4901. /**
  4902. * 刷新验证码,页面中有用到,暂不更改命名空间
  4903. */
  4904. function ptui_changeImg() {
  4905. }
  4906. /**
  4907. * 登录提交后,回调函数,暂不更改命名空间
  4908. */
  4909. function ptuiCB(ret, extret, url, redirect, Mmsg, nick) {
  4910. if (ret == 10005) {
  4911. Mmsg = '为了帐号安全,请使用一键登录。';
  4912. if ($("onekey")) {
  4913. pt.showOneKey();
  4914. }
  4915. }
  4916. if (ret != 0 && !pt.is_qlogin) { //QQ音乐帐号密码登录错误统计
  4917. qqMusicReport("33616396", 33616397);
  4918. }
  4919. if (!pt.isloading && !pt.qrcode.used) return; //已经超时就不要处理了
  4920. clearTimeout(pt._timer);
  4921. try {
  4922. pt.endLoading();
  4923. } catch (e) {}
  4924. pt.cb(ret, extret, url, redirect, Mmsg, nick);
  4925. }
  4926. /**
  4927. * 上报拉取验证码所需时间
  4928. * 页面中用到,暂不更改命名空间
  4929. */
  4930. function imgLoadReport() {
  4931. }
  4932. /**
  4933. * 检验登录表单所有数据的合法性
  4934. * 此方法在点击登录的时候调用,页面中调用,暂不更改命名空间
  4935. */
  4936. function ptui_checkValidate() {
  4937. return pt.checkValidate();
  4938. }
  4939. /**
  4940. * [ptui_auth_CB 授权回调函数]
  4941. * @param {[type]} ret,url [description]
  4942. * @return {[type]} [description]
  4943. */
  4944. function ptui_auth_CB(ret, url) {
  4945. switch (parseInt(ret)) {
  4946. //显示授权页面
  4947. case 0:
  4948. if (pt.isHulian)
  4949. pt.setCookieLogin();
  4950. else
  4951. pt.showAuth(url);
  4952. break;
  4953. //没有授权页面显示
  4954. case 1:
  4955. if (pt.isHulian) {
  4956. // pt.cancel_cookielogin();
  4957. break;
  4958. }
  4959. if (pt.mqqCanQLogin() && pt.accessCount() < 5) { //没有陷入死循环
  4960. var url = (pt.isHttps ? "https://ssl." : "http://") + "ptlogin2.qq.com/jump?clientuin=$UIN&clientkey=$KEY&keyindex=$KEYINDEX&u1=" + encodeURIComponent(pt.s_url);
  4961. pt.redirect(pt.target, url);
  4962. break;
  4963. }
  4964. break;
  4965. //不显示授权页面直接跳转
  4966. case 2:
  4967. if (pt.isHulian) {
  4968. pt.setCookieLogin();
  4969. break;
  4970. }
  4971. var authUrl = url + "&regmaster=" + window.ptui_regmaster + "&aid=" + window.ptui_appid + "&s_url=" + encodeURIComponent(pt.s_url);
  4972. if (pt.low_login_enable == 1) {
  4973. authUrl += "&low_login_enable=1&low_login_hour=" + window.ptui_low_login_hour;
  4974. }
  4975. if (window.ptui_pt_ttype == "1") {
  4976. authUrl += "&pt_ttype=1";
  4977. }
  4978. if (window.ptui_pt_light == "1") {
  4979. authUrl += "&pt_light=1";
  4980. }
  4981. pt.redirect(pt.target, authUrl);
  4982. break;
  4983. default:
  4984. }
  4985. pt.refreshQloginUI();
  4986. }
  4987. /**
  4988. * [ptuiCB description]
  4989. * @param {String} ret [错误码]
  4990. * @param {String} url [跳转url]
  4991. * @param {String} msg [登录信息]
  4992. */
  4993. function ptui_qlogin_CB(ret, url, msg) {
  4994. switch (ret + '') {
  4995. case '0':
  4996. //top.location.href = url;
  4997. pt.redirect(pt.target, url);
  4998. break;
  4999. case '5':
  5000. if (MTT.refreshToken) {
  5001. var clock = setTimeout(function() {
  5002. pt.showErr(msg);
  5003. }, 3000);
  5004. MTT.refreshToken(pt.qqBrowserInfo.uin, function(data) {
  5005. MTT.refreshToken = null;
  5006. if (!data.stweb) return;
  5007. $.report.monitor("624562");
  5008. clearTimeout(clock);
  5009. pt.qqBrowserInfo.loginkey = data.stweb;
  5010. pt.qlogin_submit();
  5011. });
  5012. $.report.monitor("624561");
  5013. } else {
  5014. pt.showErr(msg);
  5015. }
  5016. break;
  5017. default:
  5018. $.report.nlog("qq浏览器快速登录失败," + ret, "443881", pt.qqBrowserInfo.uin);
  5019. pt.showErr(msg);
  5020. }
  5021. }
  5022. function canOpenqqUaCheck() {
  5023. var iosbrowser = [
  5024. 'uc',
  5025. 'baidu',
  5026. 'weibo'
  5027. ]; //ios不能打开手Q的浏览器
  5028. var androidbrowser = [ //安卓不能打开QQ的名单
  5029. // 'uc',
  5030. // 'qq',
  5031. // '2345',
  5032. // 'sogou',
  5033. // 'chrome',
  5034. // 'liebao',
  5035. 'weibo'
  5036. ]; //手Q目前兼容了的浏览器,360算在chrome里,即android下可以打开手Q的浏览器,baidu安卓打不开
  5037. var browserType = null;
  5038. var ua = navigator.userAgent.toLowerCase();
  5039. if (ua.indexOf('ucbrowser') > -1) {
  5040. browserType = 'uc';
  5041. } else if (ua.indexOf('baidubrowser') > -1) {
  5042. browserType = 'baidu';
  5043. } else if (ua.indexOf('mqqbrowser') > -1 || ua.indexOf('tencenttraveler') > -1) {
  5044. browserType = 'qq';
  5045. } else if (ua.indexOf('liebao') > -1) {
  5046. browserType = 'liebao';
  5047. } else if (ua.indexOf('2345browser') > -1) {
  5048. browserType = '2345';
  5049. } else if (ua.indexOf('sogoumobilebrowser') > -1) {
  5050. browserType = 'sogou';
  5051. } else if (ua.indexOf('weibo')> -1){//微博暂时屏蔽
  5052. browserType = 'weibo';
  5053. //这里注意,一定要最后判断chrome,因为其他app的ua里边也可能有chrome
  5054. } else if (ua.indexOf('chrome') > -1) { //360,chrome都可以打开
  5055. browserType = 'chrome';
  5056. } else {
  5057. browserType = 'other';
  5058. }
  5059. console.log(browserType);
  5060. if (pt.isAndroid) {
  5061. if (androidbrowser.indexOf(browserType) > -1) {
  5062. return false;
  5063. } else {
  5064. return true;
  5065. }
  5066. } else if (pt.isIos) {
  5067. if (iosbrowser.indexOf(browserType) > -1) {
  5068. return false;
  5069. } else {
  5070. return true;
  5071. }
  5072. }
  5073. return false;
  5074. }
  5075. OneKey.ERRMSG = {
  5076. "2052": "使用一键登录,<a href='http://im.qq.com/mobileqq/touch/53/index.html' target='_blank'>请安装最新版本的QQ手机版</a>",
  5077. "1028": "使用一鍵登錄,<a href='http://im.qq.com/mobileqq/touch/53/index.html' target='_blank'>請安裝最新版本的QQ手機版</a>",
  5078. "1033": "Have <a href='http://im.qq.com/mobileqq/touch/53/index.html' target='_blank'>the latest Mobile QQ</a>?",
  5079. "10000": "当前应用不支持QQ快速登录,建议使用其他浏览器尝试。"
  5080. };
  5081. function OneKey(dstUrl) {
  5082. OneKey.done = false;
  5083. OneKey.TIMEOUT = 3000;
  5084. if (pt.isWX) {
  5085. OneKey.TIMEOUT = 5000;
  5086. OneKey.qrcode = true;
  5087. for (var lang in OneKey.ERRMSG) {
  5088. if (OneKey.ERRMSG.hasOwnProperty(lang))
  5089. OneKey.ERRMSG[lang] = OneKey.ERRMSG[lang].replace(/<a.*>([^<]*)<\/a>/, "$1");
  5090. }
  5091. pt.qrcode.get(1);
  5092. } else {
  5093. setTimeout(function() {
  5094. openApp(dstUrl);
  5095. }, 100);
  5096. }
  5097. }
  5098. /**
  5099. * [openApp 优化拉起QQ手机版]
  5100. * @param {String} appScheme QQ手机版的scheme
  5101. * @param {Function} [timeOutCallback] 拉起超时的回调,超时不一定失败,也可能是用户主动切回来
  5102. * @param {Function} [failCallback] 拉起失败的回调
  5103. */
  5104. function openApp(appScheme, timeOutCallback, failCallback) {
  5105. if (OneKey.done) return;
  5106. if (pt.isLaunching) return;
  5107. pt.isLaunching = true;
  5108. var timeout = OneKey.TIMEOUT;
  5109. var startDate = new Date();
  5110. pt.btnOnekey.innerHTML = STR_LANG.onekeying;
  5111. setTimeout(function() {
  5112. timeOutCallback && timeOutCallback();
  5113. pt.isLaunching = false;
  5114. pt.btnOnekey.innerHTML = STR_LANG.onekey;
  5115. if (pt.qrcode.done) return;
  5116. if (new Date() - startDate <= timeout + 200) { // 200 毫秒是误差
  5117. failCallback && failCallback(); //停留在当前页面,给出错误提示
  5118. if (!canOpenqqUaCheck()) {
  5119. pt.showErr(OneKey.ERRMSG["10000"], 5000); //浏览器原因拉起手Q失败停留在当前页面,给出错误提示
  5120. } else {
  5121. pt.showErr(OneKey.ERRMSG[ptui_lang], 5000); //停留在当前页面,给出错误提示
  5122. }
  5123. $.report.nlog("callApp failed:" + navigator.userAgent, 424783);
  5124. qqMusicReport('83886593', 33616387); //QQ音乐一键登录失败量
  5125. }
  5126. }, timeout);
  5127. // 为什么折腾?因为至少android微信不延时打开的话,按钮的文案不会更新
  5128. if (pt.isWX && pt.isAndroid)
  5129. setTimeout(function() { doOpenApp(appScheme) }, 100);
  5130. else
  5131. doOpenApp(appScheme);
  5132. }
  5133. /**
  5134. *
  5135. * @param {String} appScheme 要 使用的schema
  5136. * @param {Boolean} forceLocation 这个是为了兼容老版本微信,在使用jsapi跳转失败时,用传统的方法来跳转
  5137. */
  5138. function doOpenApp(appScheme, forceLocation) {
  5139. var res = $.detectBrowser();
  5140. var browser = res[0] && res[0].toLowerCase();
  5141. var schemas = {};
  5142. //只有微信才走这个逻辑,企业微信不走这个逻辑
  5143. if (pt.browser.isWX && !pt.browser.isWorkWX && !forceLocation) {
  5144. $.invokeWXAPI('launchApplication', {
  5145. "schemeUrl": appScheme
  5146. }, function(res) {
  5147. var err_msg = res && res.err_msg;
  5148. console.log(err_msg)
  5149. if (err_msg != 'launchApplication:ok') {
  5150. console.log('try again')
  5151. //可能是老版本微信 再用老方式试一次
  5152. doOpenApp(appScheme, true);
  5153. }
  5154. })
  5155. } else if (pt.isAndroid) {
  5156. var openStyle = res[1] || "location";
  5157. if (browser) {
  5158. schemas = {
  5159. 'ucbrowser': 'ucweb://',
  5160. 'meizu': 'mzbrowser://',
  5161. 'liebaofast': 'lb://',
  5162. 'baidubrowser': 'bdbrowser://',
  5163. 'baiduboxapp': 'bdapp://',
  5164. 'qihoobrowser': 'qihoobrowser://',
  5165. 'chrome': 'googlechrome://',
  5166. 'sogoumobilebrowser': 'SogouMSE://',
  5167. '2345browser': 'browser2345://',
  5168. 'now/' : 'tnow://openpage/web?url='
  5169. };
  5170. if (schemas[browser])
  5171. appScheme += "&schemacallback=" + encodeURIComponent(schemas[browser]);
  5172. }
  5173. switch (openStyle) {
  5174. case "iframe":
  5175. if (openApp.iframe) {
  5176. openApp.iframe.src = appScheme;
  5177. } else {
  5178. openApp.iframe = document.createElement("iframe");
  5179. openApp.iframe.src = appScheme;
  5180. openApp.iframe.style.display = "none";
  5181. document.body.appendChild(openApp.iframe);
  5182. }
  5183. openApp.flag = "iframe";
  5184. break;
  5185. case "open":
  5186. var win = window.open(appScheme, "_blank");
  5187. setTimeout(function() {
  5188. win.close();
  5189. }, 0);
  5190. openApp.flag = "open";
  5191. break;
  5192. case "location":
  5193. location.href = appScheme;
  5194. openApp.flag = "location";
  5195. break;
  5196. }
  5197. } else { //IOS or others
  5198. if (browser) {
  5199. schemas = {
  5200. 'ucbrowser': 'ucbrowser://',
  5201. 'liebao': 'lb://u/100/',
  5202. 'baiduboxapp': 'baiduboxapp', //ios百度浏览器目前缺少schema,暂时不考虑
  5203. 'qihoobrowser': 'qihoobrowser://mse.360.cn/app?q=',
  5204. 'sogoumobilebrowser': 'SogouMSE://openurl?url=',
  5205. 'chrome': 'googlechrome',
  5206. '2345browser': 'browser2345://',
  5207. 'now/' : 'tnow://openpage/web?url='
  5208. };
  5209. if (schemas[browser])
  5210. appScheme += "&schemacallback=" + encodeURIComponent(schemas[browser]);
  5211. }
  5212. if (pt.isInIframe){ // ios 9无法在iframe中拉起APP
  5213. pt.browser.setLocation(appScheme, window.top);
  5214. }else{
  5215. pt.browser.setLocation(appScheme, window)
  5216. }
  5217. openApp.flag = "location";
  5218. }
  5219. }
  5220. /**
  5221. * 把跟native调用相关的逻辑放到pt.nativeApi这个命名空间下
  5222. */
  5223. pt.nativeApi = {
  5224. doOpenApp : doOpenApp
  5225. }
  5226. /**
  5227. * [ 互联opensdk密码加密]
  5228. * @return {[type]} [description]
  5229. */
  5230. var openSDK = (function() {
  5231. var md5Pwd = "";
  5232. var result = 0;
  5233. var sn = 0;
  5234. var callbackArray = [];
  5235. var curPosFromJS = function(pos, callback) {
  5236. sn = 1;
  5237. if (typeof callback == "function") {
  5238. callbackArray[sn] = callback;
  5239. }
  5240. //pt.showErr("curPosFromJS,pos="+pos);
  5241. window.location.href = "jsbridge://SecureJsInterface/curPosFromJS/" + sn + "/openSDKCallBack/" + pos;
  5242. };
  5243. var isPasswordEdit = function(flag, callback) {
  5244. sn = 2;
  5245. if (typeof callback == "function") {
  5246. callbackArray[sn] = callback;
  5247. }
  5248. //pt.showErr("isPasswordEdit,sn="+sn);
  5249. window.location.href = "jsbridge://SecureJsInterface/isPasswordEdit/" + sn + "/openSDKCallBack/" + flag;
  5250. };
  5251. var clearAllEdit = function(callback) {
  5252. sn = 3;
  5253. if (typeof callback == "function") {
  5254. callbackArray[sn] = callback;
  5255. }
  5256. //pt.showErr("clearAllEdit,sn="+sn);
  5257. window.location.href = "jsbridge://SecureJsInterface/clearAllEdit/" + sn + "/openSDKCallBack";
  5258. };
  5259. var getMD5FromNative = function(callback) {
  5260. sn = 4;
  5261. if (typeof callback == "function") {
  5262. callbackArray[sn] = callback;
  5263. }
  5264. //pt.showErr("getMD5FromNative,sn="+sn);
  5265. window.location.href = "jsbridge://SecureJsInterface/getMD5FromNative/" + sn + "/openSDKCallBack";
  5266. };
  5267. if (window.ptui_enablePwd == "1") {
  5268. return {
  5269. curPosFromJS: curPosFromJS,
  5270. isPasswordEdit: isPasswordEdit,
  5271. clearAllEdit: clearAllEdit,
  5272. getMD5FromNative: getMD5FromNative,
  5273. sn: sn,
  5274. md5Pwd: md5Pwd,
  5275. result: result,
  5276. callbackArray: callbackArray
  5277. }
  5278. }
  5279. })();
  5280. function openSDKCallBack(json) {
  5281. var result = json.result;
  5282. var md5 = json.data;
  5283. var sn = json.sn;
  5284. switch (sn) {
  5285. case 4:
  5286. openSDK.md5Pwd = md5;
  5287. openSDK.result = result;
  5288. //alert("md5="+openSDK.md5Pwd);
  5289. openSDK.callbackArray[sn].call();
  5290. break;
  5291. default:
  5292. break;
  5293. }
  5294. }
  5295. function get_app_basicinfo(res) {
  5296. pt.open.fillAppInfo(res);
  5297. }
  5298. function ptui_wtlogin_CB(uin,sig) {
  5299. clearInterval(pt.qrcode.clock);
  5300. pt.isLoading && pt.endLoading();
  5301. if(!window.wtCB){
  5302. // 兼容and6奇怪的客户端bug
  5303. // 这里安卓6下,腾讯视频的客户端有个wtCB无法注入的bug,这里暂时的兜底逻辑 by dariondiao 20190408
  5304. if(window.WTLogin && window.WTLogin.ptloginCallBack){
  5305. WTLogin.ptloginCallBack(uin,sig);
  5306. }else{
  5307. pt.showErr('请安装手机QQ后再登录');
  5308. }
  5309. console.log('wtCB不存在');
  5310. }else{
  5311. window.wtCB && window.wtCB.apply(window, arguments);
  5312. console.log('wtCB存在');
  5313. }
  5314. }
  5315. //这里的代码只有在单元测试的时候会执行
  5316. if(typeof process!=='undefined' && process.env && process.env.UNITTEST==1){
  5317. module.exports = pt
  5318. }
  5319. //启动代码都在login_mobile_init.js里边,会合并进来
  5320. //20180129 add
  5321. var hlhdFlag = false; //是否进行互联新版本登录模式灰度,条件为:1.在灰度名单中 2.在非手Q中 3.在style为35的情况下
  5322. var isMobileQQ = !!(typeof mqq != "undefined" && typeof mqq.QQVersion != "undefined" && mqq.QQVersion != 0 && !/Qzone/.test(navigator.userAgent));
  5323. if (window.ptui_style == 35 && window.hlhd_temp && !isMobileQQ) {
  5324. hlhdFlag = true;
  5325. }
  5326. //启动登录页的主逻辑
  5327. pt.access();
  5328. pt.init();
  5329. // pt.isWX = true;
  5330. // pt.showOneKey('justshow');
  5331. if (!window.hlhdFlag) {
  5332. if ($.bom.query("pt_wxtest") !== '0' && pt.isWX) weixin_sig_cb(); //使用jsbridge 不用发起请求了
  5333. } else {
  5334. pt.showOneKey();
  5335. }
  5336. try {
  5337. if (window._timePoints && window._timePoints.length > 1 && typeof(window.speedReportAR) == 'function') {
  5338. window._timePoints[2] = Date.now();
  5339. //参数填入(appId, buzId, siteId, pageId, gray),其中 appId 是固定值20122 ,剩下的来自申请的 id
  5340. //例如,校园圈主页的active点id为 21485-1-1-24,则填入
  5341. window.speedReportAR(20122, 21998, 1, 1);
  5342. }
  5343. } catch (err) {
  5344. //console.log(err);
  5345. }
  5346. //20181129 add QQ音乐加上报
  5347. var url_appid = $.bom.query("appid") || '';
  5348. var qqMusicReport = function(appid, moinitorid) {
  5349. if (url_appid == "83886593" && moinitorid) {
  5350. $.report.monitor(moinitorid);
  5351. }
  5352. }
  5353. qqMusicReport("83886593", 33616394); ///QQ音乐总量pv