pla.php 241 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181
  1. <?php
  2. //
  3. // Project: phpLiteAdmin (https://www.phpliteadmin.org/)
  4. // Version: 1.9.8.2
  5. // Summary: PHP-based admin tool to manage SQLite2 and SQLite3 databases on the web
  6. // Last updated: 2019-09-05
  7. // Developers:
  8. // Dane Iracleous (daneiracleous@gmail.com)
  9. // Ian Aldrighetti (ian.aldrighetti@gmail.com)
  10. // George Flanagin & Digital Gaslight, Inc (george@digitalgaslight.com)
  11. // Christopher Kramer (crazy4chrissi@gmail.com, http://en.christosoft.de)
  12. // Ayman Teryaki (http://havalite.com)
  13. // Dreadnaut (dreadnaut@gmail.com, http://dreadnaut.altervista.org)
  14. //
  15. //
  16. // Copyright (C) 2019, phpLiteAdmin
  17. //
  18. // This program is free software: you can redistribute it and/or modify
  19. // it under the terms of the GNU General Public License as published by
  20. // the Free Software Foundation, either version 3 of the License, or
  21. // (at your option) any later version.
  22. //
  23. // This program is distributed in the hope that it will be useful,
  24. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. // GNU General Public License for more details.
  27. //
  28. // You should have received a copy of the GNU General Public License
  29. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  30. //
  31. // ////////////////////////////////////////////////////////////////////////
  32. //
  33. // Please report any bugs you may encounter to our issue tracker here:
  34. // https://bitbucket.org/phpliteadmin/public/issues?status=new&status=open
  35. //
  36. // This is sample configuration file
  37. //
  38. // You can configure phpliteadmin in one of 2 ways:
  39. // 1. Rename phpliteadmin.config.sample.php to phpliteadmin.config.php and change parameters in there.
  40. // You can set only your custom settings in phpliteadmin.config.php. All other settings will be set to defaults.
  41. // 2. Change parameters directly in main phpliteadmin.php file
  42. //
  43. // Please see https://bitbucket.org/phpliteadmin/public/wiki/Configuration for more details
  44. //password to gain access
  45. $password = 'admin';
  46. //directory relative to this file to search for databases (if false, manually list databases in the $databases variable)
  47. $directory = '../../tmp/appdata/palicanon';
  48. //whether or not to scan the subdirectories of the above directory infinitely deep
  49. $subdirectories = false;
  50. //if the above $directory variable is set to false, you must specify the databases manually in an array as the next variable
  51. //if any of the databases do not exist as they are referenced by their path, they will be created automatically
  52. $databases = array(
  53. array(
  54. 'path'=> 'database1.sqlite',
  55. 'name'=> 'Database 1'
  56. ),
  57. array(
  58. 'path'=> 'database2.sqlite',
  59. 'name'=> 'Database 2'
  60. ),
  61. );
  62. /* ---- Interface settings ---- */
  63. // Theme! If you want to change theme, save the CSS file in same folder of phpliteadmin or in folder "themes"
  64. $theme = 'phpliteadmin.css';
  65. // the default language! If you want to change it, save the language file in same folder of phpliteadmin or in folder "languages"
  66. // More about localizations (downloads, how to translate etc.): https://bitbucket.org/phpliteadmin/public/wiki/Localization
  67. $language = 'en';
  68. // set default number of rows. You need to relog after changing the number
  69. $rowsNum = 30;
  70. // reduce string characters by a number bigger than 10
  71. $charsNum = 300;
  72. // maximum number of SQL queries to save in the history
  73. $maxSavedQueries = 10;
  74. /* ---- Custom functions ---- */
  75. //a list of custom functions that can be applied to columns in the databases
  76. //make sure to define every function below if it is not a core PHP function
  77. $custom_functions = array(
  78. 'md5', 'sha1', 'time', 'strtotime',
  79. // add the names of your custom functions to this array
  80. /* 'leet_text', */
  81. );
  82. // define your custom functions here
  83. /*
  84. function leet_text($value)
  85. {
  86. return strtr($value, 'eaAsSOl', '344zZ01');
  87. }
  88. */
  89. /* ---- Advanced options ---- */
  90. //changing the following variable allows multiple phpLiteAdmin installs to work under the same domain.
  91. $cookie_name = 'pla3412';
  92. //whether or not to put the app in debug mode where errors are outputted
  93. $debug = false;
  94. // the user is allowed to create databases with only these extensions
  95. $allowed_extensions = array('db','db3','sqlite','sqlite3');
  96. // English language-texts.
  97. // Read our wiki on how to translate: https://bitbucket.org/phpliteadmin/public/wiki/Localization
  98. $lang = array(
  99. "direction" => "LTR",
  100. "date_format" => 'g:ia \o\n F j, Y (T)', // see http://php.net/manual/en/function.date.php for what the letters stand for
  101. "ver" => "version",
  102. "for" => "for",
  103. "to" => "to",
  104. "go" => "Go",
  105. "yes" => "Yes",
  106. "no" => "No",
  107. "sql" => "SQL",
  108. "csv" => "CSV",
  109. "csv_tbl" => "Table that CSV pertains to",
  110. "srch" => "Search",
  111. "srch_again" => "Do Another Search",
  112. "login" => "Log In",
  113. "logout" => "Logout",
  114. "view" => "View", // here, the noun SQL view is meant, not the verb "to view"
  115. "confirm" => "Confirm",
  116. "cancel" => "Cancel",
  117. "save_as" => "Save As",
  118. "options" => "Options",
  119. "no_opt" => "No options",
  120. "help" => "Help",
  121. "installed" => "installed",
  122. "not_installed" => "not installed",
  123. "done" => "done",
  124. "insert" => "Insert",
  125. "export" => "Export",
  126. "import" => "Import",
  127. "rename" => "Rename",
  128. "empty" => "Empty",
  129. "drop" => "Drop",
  130. "tbl" => "Table",
  131. "chart" => "Chart",
  132. "err" => "ERROR",
  133. "act" => "Action",
  134. "rec" => "Records",
  135. "col" => "Column",
  136. "cols" => "Columns",
  137. "rows" => "row(s)",
  138. "edit" => "Edit",
  139. "del" => "Delete",
  140. "add" => "Add",
  141. "backup" => "Backup database file",
  142. "before" => "Before",
  143. "after" => "After",
  144. "passwd" => "Password",
  145. "passwd_incorrect" => "Incorrect password.",
  146. "chk_ext" => "Checking supported SQLite PHP extensions",
  147. "autoincrement" => "Autoincrement",
  148. "not_null" => "Not NULL",
  149. "attention" => "Attention",
  150. "none" => "None",
  151. "as_defined" => "As defined",
  152. "expression" => "Expression",
  153. "download" => "Download",
  154. "open_in_browser" => "Open in browser",
  155. "sqlite_ext" => "SQLite extension",
  156. "sqlite_ext_support" => "It appears that none of the supported SQLite library extensions are available in your installation of PHP. You may not use %s until you install at least one of them.",
  157. "sqlite_v" => "SQLite version",
  158. "sqlite_v_error" => "It appears that your database is of SQLite version %s but your installation of PHP does not contain the necessary extensions to handle this version. To fix the problem, either delete the database and allow %s to create it automatically or recreate it manually as SQLite version %s.",
  159. "report_issue" => "The problem cannot be diagnosed properly. Please file an issue report at",
  160. "sqlite_limit" => "Due to the limitations of SQLite, only the field name and data type can be modified.",
  161. "php_v" => "PHP version",
  162. "new_version" => "There is a new version!",
  163. "db_dump" => "database dump",
  164. "db_f" => "database file",
  165. "db_ch" => "Change Database",
  166. "db_event" => "Database Event",
  167. "db_name" => "Database name",
  168. "db_rename" => "Rename Database",
  169. "db_renamed" => "Database '%s' has been renamed to",
  170. "db_del" => "Delete Database",
  171. "db_path" => "Path to database",
  172. "db_size" => "Size of database",
  173. "db_mod" => "Database last modified",
  174. "db_create" => "Create New Database",
  175. "db_vac" => "The database, '%s', has been VACUUMed.",
  176. "db_not_writeable" => "The database, '%s', does not exist and cannot be created because the containing directory, '%s', is not writable. The application is unusable until you make it writable.",
  177. "db_setup" => "There was a problem setting up your database, %s. An attempt will be made to find out what's going on so you can fix the problem more easily",
  178. "db_exists" => "A database, other file or directory of the name '%s' already exists.",
  179. "db_blank" => "The database name cannot be blank.",
  180. "exported" => "Exported",
  181. "struct" => "Structure",
  182. "struct_for" => "structure for",
  183. "on_tbl" => "on table",
  184. "data_dump" => "Data dump for",
  185. "backup_hint" => "Hint: To backup your database, the easiest way is to %s.",
  186. "backup_hint_linktext" => "download the database-file",
  187. "total_rows" => "a total of %s rows",
  188. "total" => "Total",
  189. "not_dir" => "The directory you specified to scan for databases does not exist or is not a directory.",
  190. "bad_php_directive" => "It appears that the PHP directive, 'register_globals' is enabled. This is bad. You need to disable it before continuing.",
  191. "page_gen" => "Page generated in %s seconds.",
  192. "powered" => "Powered by",
  193. "free_software" => "This is free software.",
  194. "please_donate" => "Please donate.",
  195. "remember" => "Remember me",
  196. "no_db" => "Welcome to %s. It appears that you have selected to scan a directory for databases to manage. However, %s could not find any valid SQLite databases. You may use the form below to create your first database.",
  197. "no_db2" => "The directory you specified does not contain any existing databases to manage, and the directory is not writable. This means you can't create any new databases using %s. Either make the directory writable or manually upload databases to the directory.",
  198. "dir_not_executable" => "The directory you specified cannot be scanned for databases as %s has no execute permissions on it. On Linux, use 'chmod +x %s' to fix this.",
  199. "create" => "Create",
  200. "created" => "has been created",
  201. "create_tbl" => "Create new table",
  202. "create_tbl_db" => "Create new table on database",
  203. "create_trigger" => "Creating new trigger on table",
  204. "create_index" => "Creating new index on table",
  205. "create_index1" => "Create Index",
  206. "create_view" => "Create new view on database",
  207. "trigger" => "Trigger",
  208. "triggers" => "Triggers",
  209. "trigger_name" => "Trigger name",
  210. "trigger_act" => "Trigger Action",
  211. "trigger_step" => "Trigger Steps (semicolon terminated)",
  212. "when_exp" => "WHEN expression (type expression without 'WHEN')",
  213. "index" => "Index",
  214. "indexes" => "Indexes",
  215. "index_name" => "Index name",
  216. "name" => "Name",
  217. "unique" => "Unique",
  218. "seq_no" => "Seq. No.",
  219. "emptied" => "has been emptied",
  220. "dropped" => "has been dropped",
  221. "renamed" => "has been renamed to",
  222. "altered" => "has been altered successfully",
  223. "inserted" => "inserted",
  224. "deleted" => "deleted",
  225. "affected" => "affected",
  226. "blank_index" => "Index name must not be blank.",
  227. "one_index" => "You must specify at least one index column.",
  228. "docu" => "Documentation",
  229. "license" => "License",
  230. "proj_site" => "Project Site",
  231. "bug_report" => "This may be a bug that needs to be reported at",
  232. "return" => "Return",
  233. "browse" => "Browse",
  234. "fld" => "Field",
  235. "fld_num" => "Number of Fields",
  236. "fields" => "Fields",
  237. "type" => "Type",
  238. "operator" => "Operator",
  239. "val" => "Value",
  240. "update" => "Update",
  241. "comments" => "Comments",
  242. "specify_fields" => "You must specify the number of table fields.",
  243. "specify_tbl" => "You must specify a table name.",
  244. "specify_col" => "You must specify a column.",
  245. "tbl_exists" => "Table of the same name already exists.",
  246. "show" => "Show",
  247. "show_rows" => "Showing %s row(s). ",
  248. "showing" => "Showing",
  249. "showing_rows" => "Showing rows",
  250. "query_time" => "(Query took %s sec)",
  251. "syntax_err" => "There is a problem with the syntax of your query (Query was not executed)",
  252. "run_sql" => "Run SQL query/queries on database '%s'",
  253. "recent_queries" => "Recent Queries",
  254. "full_texts" => "Show full texts",
  255. "no_full_texts" => "Shorten long texts",
  256. "ques_empty" => "Are you sure you want to empty the table '%s'?",
  257. "ques_drop" => "Are you sure you want to drop the table '%s'?",
  258. "ques_drop_view" => "Are you sure you want to drop the view '%s'?",
  259. "ques_del_rows" => "Are you sure you want to delete row(s) %s from table '%s'?",
  260. "ques_del_db" => "Are you sure you want to delete the database '%s'?",
  261. "ques_column_delete" => "Are you sure you want to delete column(s) %s from table '%s'?",
  262. "ques_del_index" => "Are you sure you want to delete index '%s'?",
  263. "ques_del_trigger" => "Are you sure you want to delete trigger '%s'?",
  264. "ques_primarykey_add" => "Are you sure you want to add a primary key for the column(s) %s in table '%s'?",
  265. "export_struct" => "Export with structure",
  266. "export_data" => "Export with data",
  267. "add_drop" => "Add DROP TABLE",
  268. "add_transact" => "Add TRANSACTION",
  269. "fld_terminated" => "Fields terminated by",
  270. "fld_enclosed" => "Fields enclosed by",
  271. "fld_escaped" => "Fields escaped by",
  272. "fld_names" => "Field names in first row",
  273. "rep_null" => "Replace NULL by",
  274. "rem_crlf" => "Remove CRLF characters within fields",
  275. "put_fld" => "Put field names in first row",
  276. "null_represent" => "NULL represented by",
  277. "import_suc" => "Import was successful.",
  278. "import_into" => "Import into",
  279. "import_f" => "File to import",
  280. "max_file_size" => "Maximum file size",
  281. "rename_tbl" => "Rename table '%s' to",
  282. "rows_records" => "row(s) starting from record # ",
  283. "rows_aff" => "row(s) affected. ",
  284. "as_a" => "as a",
  285. "readonly_tbl" => "'%s' is a view, which means it is a SELECT statement treated as a read-only table. You may not edit or insert records.",
  286. "chk_all" => "Check All",
  287. "unchk_all" => "Uncheck All",
  288. "with_sel" => "With Selected",
  289. "no_tbl" => "No table in database.",
  290. "no_chart" => "If you can read this, it means the chart could not be generated. The data you are trying to view may not be appropriate for a chart.",
  291. "no_rows" => "There are no rows in the table for the range you selected.",
  292. "no_sel" => "You did not select anything.",
  293. "chart_type" => "Chart Type",
  294. "chart_bar" => "Bar Chart",
  295. "chart_pie" => "Pie Chart",
  296. "chart_line" => "Line Chart",
  297. "lbl" => "Labels",
  298. "empty_tbl" => "This table is empty.",
  299. "click" => "Click here",
  300. "insert_rows" => "to insert rows.",
  301. "restart_insert" => "Restart insertion with ",
  302. "ignore" => "Ignore",
  303. "func" => "Function",
  304. "new_insert" => "Insert As New Row",
  305. "save_ch" => "Save Changes",
  306. "def_val" => "Default Value",
  307. "prim_key" => "Primary Key",
  308. "tbl_end" => "field(s) at end of table",
  309. "query_used_table" => "Query used to create this table",
  310. "query_used_view" => "Query used to create this view",
  311. "create_index2" => "Create an index on",
  312. "create_trigger2" => "Create a new trigger",
  313. "new_fld" => "Adding new field(s) to table '%s'",
  314. "add_flds" => "Add Fields",
  315. "edit_col" => "Editing column '%s'",
  316. "vac" => "Vacuum",
  317. "vac_desc" => "Large databases sometimes need to be VACUUMed to reduce their footprint on the server. Click the button below to VACUUM the database '%s'.",
  318. "vac_on_empty"=>"Rebuild database file to recover unused space (Vacuum)",
  319. "event" => "Event",
  320. "each_row" => "For Each Row",
  321. "define_index" => "Define index properties",
  322. "dup_val" => "Duplicate values",
  323. "allow" => "Allowed",
  324. "not_allow" => "Not Allowed",
  325. "asc" => "Ascending",
  326. "desc" => "Descending",
  327. "warn0" => "You have been warned.",
  328. "warn_passwd" => "You are using the default password, which can be dangerous. You can change it easily at the top of %s.",
  329. "counting_skipped" => "Counting of records has been skipped for some tables because your database is comparably big and some tables don't have primary keys assigned to them so counting might be slow. Add a primary key to these tables or %sforce counting%s.",
  330. "sel_state" => "Select Statement",
  331. "delimit" => "Delimiter",
  332. "back_top" => "Back to Top",
  333. "choose_f" => "Choose File",
  334. "instead" => "Instead of",
  335. "define_in_col" => "Define index column(s)",
  336. "delete_only_managed" => "You can only delete databases managed by this tool!",
  337. "rename_only_managed" => "You can only rename databases managed by this tool!",
  338. "db_moved_outside" => "You either tried to move the database into a directory where it cannot be managed anylonger, or the check if you did this failed because of missing rights.",
  339. "extension_not_allowed" => "The extension you provided is not within the list of allowed extensions. Please use one of the following extensions",
  340. "add_allowed_extension" => "You can add extensions to this list by adding your extension to \$allowed_extensions in the configuration.",
  341. "database_not_writable" => "The database-file is not writable, so its content cannot be changed in any way.",
  342. "directory_not_writable" => "The database-file itself is writable, but to write into it, the containing directory needs to be writable as well. This is because SQLite puts temporary files in there for locking.",
  343. "tbl_inexistent" => "Table %s does not exist",
  344. "col_inexistent" => "Column %s does not exist",
  345. // errors that can happen when ALTER TABLE fails. You don't necessarily have to translate these.
  346. "alter_failed" => "Altering of Table %s failed",
  347. "alter_tbl_name_not_replacable" => "could not replace the table name with the temporary one",
  348. "alter_no_def" => "no ALTER definition",
  349. "alter_parse_failed" =>"failed to parse ALTER definition",
  350. "alter_action_not_recognized" => "ALTER action could not be recognized",
  351. "alter_no_add_col" => "no column to add detected in ALTER statement",
  352. "alter_pattern_mismatch"=>"Pattern did not match on your original CREATE TABLE statement",
  353. "alter_col_not_recognized" => "could not recognize new or old column name",
  354. "alter_unknown_operation" => "Unknown ALTER operation!",
  355. /* Help documentation */
  356. "help_doc" => "Help Documentation",
  357. "help1" => "SQLite Library Extensions",
  358. "help1_x" => "%s uses PHP library extensions that allow interaction with SQLite databases. Currently, %s supports PDO, SQLite3, and SQLiteDatabase. Both PDO and SQLite3 deal with version 3 of SQLite, while SQLiteDatabase deals with version 2. So, if your PHP installation includes more than one SQLite library extension, PDO and SQLite3 will take precedence to make use of the better technology. However, if you have existing databases that are of version 2 of SQLite, %s will be forced to use SQLiteDatabase for only those databases. Not all databases need to be of the same version. During the database creation, however, the most advanced extension will be used.",
  359. "help2" => "Creating a New Database",
  360. "help2_x" => "When you create a new database, the name you entered will be appended with the appropriate file extension (.db, .db3, .sqlite, etc.) if you do not include it yourself. The database will be created in the directory you specified as the \$directory variable.",
  361. "help3" => "Tables vs. Views",
  362. "help3_x" => "On the main database page, there is a list of tables and views. Since views are read-only, certain operations will be disabled. These disabled operations will be apparent by their omission in the location where they should appear on the row for a view. If you want to change the data for a view, you need to drop that view and create a new view with the appropriate SELECT statement that queries other existing tables. For more information, see <a href='http://en.wikipedia.org/wiki/View_(database)' target='_blank'>http://en.wikipedia.org/wiki/View_(database)</a>",
  363. "help4" => "Writing a Select Statement for a New View",
  364. "help4_x" => "When you create a new view, you must write an SQL SELECT statement that it will use as its data. A view is simply a read-only table that can be accessed and queried like a regular table, except it cannot be modified through insertion, column editing, or row editing. It is only used for conveniently fetching data.",
  365. "help5" => "Export Structure to SQL File",
  366. "help5_x" => "During the process for exporting to an SQL file, you may choose to include the queries that create the table and columns.",
  367. "help6" => "Export Data to SQL File",
  368. "help6_x" => "During the process for exporting to an SQL file, you may choose to include the queries that populate the table(s) with the current records of the table(s).",
  369. "help7" => "Add Drop Table to Exported SQL File",
  370. "help7_x" => "During the process for exporting to an SQL file, you may choose to include queries to DROP the existing tables before adding them so that problems do not occur when trying to create tables that already exist.",
  371. "help8" => "Add Transaction to Exported SQL File",
  372. "help8_x" => "During the process for exporting to an SQL file, you may choose to wrap the queries around a TRANSACTION so that if an error occurs at any time during the importation process using the exported file, the database can be reverted to its previous state, preventing partially updated data from populating the database.",
  373. "help9" => "Add Comments to Exported SQL File",
  374. "help9_x" => "During the process for exporting to an SQL file, you may choose to include comments that explain each step of the process so that a human can better understand what is happening.",
  375. "help10" => "Partial Indexes",
  376. "help10_x" => "Partial indexes are indexes over a subset of the rows of a table specified by a WHERE clause. Note this requires at least SQLite 3.8.0 and database files with partial indexes won't be readable or writable by older versions. See the <a href='https://www.sqlite.org/partialindex.html' target='_blank'>SQLite documentation.</a>",
  377. "help11" => "Maximum size of file uploads",
  378. "help11_x" => "The maximum size of file uploads is determined by three PHP settings: <em>upload_max_filesize</em>, <em>post_max_size</em> and <em>memory_limit</em>. The smallest of these three limits the maximum size for file uploads. To upload larger files, adjust these values in your <em>php.ini</em> file."
  379. );
  380. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  381. //there is no reason for the average user to edit anything below this comment
  382. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  383. //- Initialization
  384. // load optional configuration file
  385. $config_filename = './phpliteadmin.config.php';
  386. if (is_readable($config_filename))
  387. {
  388. include_once $config_filename;
  389. }
  390. //constants 1
  391. define("PROJECT", "phpLiteAdmin");
  392. define("VERSION", "1.9.8.2");
  393. define("FORCETYPE", false); //force the extension that will be used (set to false in almost all circumstances except debugging)
  394. define("SYSTEMPASSWORD", $password); // Makes things easier.
  395. define('PROJECT_URL','https://www.phpliteadmin.org/');
  396. define('DONATE_URL','https://www.phpliteadmin.org/donate/');
  397. define('VERSION_CHECK_URL','https://www.phpliteadmin.org/current_version.php');
  398. define('PROJECT_BUGTRACKER_LINK','<a href="https://bitbucket.org/phpliteadmin/public/issues?status=new&status=open" target="_blank">https://bitbucket.org/phpliteadmin/public/issues?status=new&status=open</a>');
  399. define('PROJECT_INSTALL_LINK','<a href="https://bitbucket.org/phpliteadmin/public/wiki/Installation" target="_blank">https://bitbucket.org/phpliteadmin/public/wiki/Installation</a>');
  400. // up here, we don't output anything. debug output might appear here which is catched by ob and thrown later
  401. ob_start();
  402. // Resource output (css and javascript files)
  403. // we get out of the main code as soon as possible, without inizializing the session
  404. if (isset($_GET['resource']))
  405. {
  406. Resources::output($_GET['resource']);
  407. exit();
  408. }
  409. // don't mess with this - required for the login session
  410. ini_set('session.cookie_httponly', '1');
  411. session_start();
  412. // version-number added so after updating, old session-data is not used anylonger
  413. // cookies names cannot contain symbols, except underscores
  414. define("COOKIENAME", preg_replace('/[^a-zA-Z0-9_]/', '_', $cookie_name . '_' . VERSION) );
  415. $params = new GetParameters();
  416. if($debug==true)
  417. {
  418. ini_set("display_errors", 1);
  419. error_reporting(E_STRICT | E_ALL);
  420. } else
  421. {
  422. @ini_set("display_errors", 0);
  423. }
  424. // start the timer to record page load time
  425. $pageTimer = new MicroTimer();
  426. // load language file
  427. if($language != 'en') {
  428. $temp_lang=$lang;
  429. if(is_file('languages/lang_'.$language.'.php'))
  430. include('languages/lang_'.$language.'.php');
  431. elseif(is_file('lang_'.$language.'.php'))
  432. include('lang_'.$language.'.php');
  433. $lang = array_merge($temp_lang, $lang);
  434. unset($temp_lang);
  435. }
  436. // stripslashes if MAGIC QUOTES is turned on
  437. // This is only a workaround. Please better turn off magic quotes!
  438. // This code is from http://php.net/manual/en/security.magicquotes.disabling.php
  439. if (get_magic_quotes_gpc()) {
  440. $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
  441. while (list($key, $val) = each($process)) {
  442. foreach ($val as $k => $v) {
  443. unset($process[$key][$k]);
  444. if (is_array($v)) {
  445. $process[$key][stripslashes($k)] = $v;
  446. $process[] = &$process[$key][stripslashes($k)];
  447. } else {
  448. $process[$key][stripslashes($k)] = stripslashes($v);
  449. }
  450. }
  451. }
  452. unset($process);
  453. }
  454. //data types array
  455. $sqlite_datatypes = array("INTEGER", "REAL", "TEXT", "BLOB","NUMERIC","BOOLEAN","DATETIME");
  456. //available SQLite functions array (don't add anything here or there will be problems)
  457. $sqlite_functions = array("abs", "hex", "length", "lower", "ltrim", "random", "round", "rtrim", "trim", "typeof", "upper");
  458. //- Support functions
  459. // for php < 5.6.0
  460. if(!function_exists('hash_equals'))
  461. {
  462. function hash_equals($str1, $str2)
  463. {
  464. if(strlen($str1) != strlen($str2))
  465. return false;
  466. else {
  467. $res = $str1 ^ $str2;
  468. $ret = 0;
  469. for($i = strlen($res) - 1; $i >= 0; $i--)
  470. $ret |= ord($res[$i]);
  471. return !$ret;
  472. }
  473. }
  474. }
  475. //function that allows SQL delimiter to be ignored inside comments or strings
  476. function explode_sql($delimiter, $sql)
  477. {
  478. $ign = array('"' => '"', "'" => "'", "/*" => "*/", "--" => "\n"); // Ignore sequences.
  479. $out = array();
  480. $last = 0;
  481. $slen = strlen($sql);
  482. $dlen = strlen($delimiter);
  483. $i = 0;
  484. while($i < $slen)
  485. {
  486. // Split on delimiter
  487. if($slen - $i >= $dlen && substr($sql, $i, $dlen) == $delimiter)
  488. {
  489. array_push($out, substr($sql, $last, $i - $last));
  490. $last = $i + $dlen;
  491. $i += $dlen;
  492. continue;
  493. }
  494. // Eat comments and string literals
  495. foreach($ign as $start => $end)
  496. {
  497. $ilen = strlen($start);
  498. if($slen - $i >= $ilen && substr($sql, $i, $ilen) == $start)
  499. {
  500. $i+=strlen($start);
  501. $elen = strlen($end);
  502. while($i < $slen)
  503. {
  504. if($slen - $i >= $elen && substr($sql, $i, $elen) == $end)
  505. {
  506. // SQL comment characters can be escaped by doubling the character. This recognizes and skips those.
  507. if($start == $end && $slen - $i >= $elen*2 && substr($sql, $i, $elen*2) == $end.$end)
  508. {
  509. $i += $elen * 2;
  510. continue;
  511. }
  512. else
  513. {
  514. $i += $elen;
  515. continue 3;
  516. }
  517. }
  518. $i++;
  519. }
  520. continue 2;
  521. }
  522. }
  523. $i++;
  524. }
  525. if($last < $slen)
  526. array_push($out, substr($sql, $last, $slen - $last));
  527. return $out;
  528. }
  529. //function to scan entire directory tree and subdirectories
  530. function dir_tree($dir)
  531. {
  532. $path = array();
  533. $stack = array($dir);
  534. while($stack)
  535. {
  536. $thisdir = array_pop($stack);
  537. if($dircont = scandir($thisdir))
  538. {
  539. $i=0;
  540. while(isset($dircont[$i]))
  541. {
  542. if($dircont[$i] !== '.' && $dircont[$i] !== '..')
  543. {
  544. $current_file = $thisdir.DIRECTORY_SEPARATOR.$dircont[$i];
  545. if(is_file($current_file))
  546. {
  547. $path[] = $thisdir.DIRECTORY_SEPARATOR.$dircont[$i];
  548. }
  549. elseif (is_dir($current_file))
  550. {
  551. $path[] = $thisdir.DIRECTORY_SEPARATOR.$dircont[$i];
  552. $stack[] = $current_file;
  553. }
  554. }
  555. $i++;
  556. }
  557. }
  558. }
  559. return $path;
  560. }
  561. //the function echo the help [?] links to the documentation
  562. function helpLink($name)
  563. {
  564. global $lang;
  565. return "<a href='?help=1' onclick='openHelp(\"".$name."\"); return false;' class='helpq' title='".$lang['help'].": ".$name."' target='_blank'><span>[?]</span></a>";
  566. }
  567. // function to encode value into HTML just like htmlentities, but with adjusted default settings
  568. function htmlencode($value, $flags=ENT_QUOTES, $encoding ="UTF-8")
  569. {
  570. return htmlentities($value, $flags, $encoding);
  571. }
  572. // reduce string chars
  573. function subString($str)
  574. {
  575. global $charsNum, $params;
  576. if($charsNum > 10 && (!isset($params->fulltexts) || !$params->fulltexts) && mb_strlen($str)>$charsNum)
  577. {
  578. $str = mb_substr($str, 0, $charsNum).'...';
  579. }
  580. return $str;
  581. }
  582. // marks searchwords and htmlencodes correctly
  583. function markSearchWords($input, $field, $search)
  584. {
  585. $output = htmlencode($input);
  586. if(isset($search['values'][$field]) && is_array($search['values'][$field]))
  587. {
  588. // build one regex that matches (all) search words
  589. $regex = '/';
  590. $vali=0;
  591. foreach($search['values'][$field] as $searchValue)
  592. {
  593. if($search['operators'][$field] =='LIKE' || $search['operators'][$field] == 'LIKE%')
  594. $regex .= '(?:'.($searchValue[0]=='%'?'':'^'); // does the searchvalue have to occur at the start?
  595. $regex .= preg_quote(trim($searchValue,'%'),'/'); // the search value
  596. if($search['operators'][$field] =='LIKE' || $search['operators'][$field] == 'LIKE%')
  597. $regex .= (substr($searchValue,-1)=='%'?'':'$').')'; // does the searchvalue have to occur at the end?
  598. if($vali++<count($search['values'][$field]))
  599. $regex .= '|'; // there is another search value, so we add a |
  600. }
  601. $regex .= '/u';
  602. // LIKE operator is not case sensitive, others are
  603. if($search['operators'][$field] =='LIKE' || $search['operators'][$field] == 'LIKE%')
  604. $regex.= 'i';
  605. // split the string into parts that match and should be highlighted and parts in between
  606. // $fldBetweenParts: the parts that don't match (might contain empty strings)
  607. $fldBetweenParts = preg_split($regex, $input);
  608. // $fldFoundParts[0]: the parts that match
  609. preg_match_all($regex, $input, $fldFoundParts);
  610. // stick the parts together
  611. $output = '';
  612. foreach($fldBetweenParts as $index => $betweenPart)
  613. {
  614. $output .= htmlencode($betweenPart); // part that does not match (might be empty)
  615. if(isset($fldFoundParts[0][$index]))
  616. $output .= '<u class="found">'.htmlencode($fldFoundParts[0][$index]).'</u>'; // the part that matched
  617. }
  618. }
  619. return $output;
  620. }
  621. // checks the (new) name of a database file
  622. function checkDbName($name)
  623. {
  624. global $allowed_extensions;
  625. $info = pathinfo($name);
  626. if(isset($info['extension']) && !in_array($info['extension'], $allowed_extensions))
  627. {
  628. return false;
  629. } else
  630. {
  631. return (!is_file($name) && !is_dir($name));
  632. }
  633. }
  634. // check whether a path is a db managed by this tool
  635. // requires that $databases is already filled!
  636. // returns the key of the db if managed, false otherwise.
  637. function isManagedDB($path)
  638. {
  639. global $databases;
  640. foreach($databases as $db_key => $database)
  641. {
  642. if($path === $database['path'])
  643. {
  644. // a db we manage. Thats okay.
  645. // return the key.
  646. return $db_key;
  647. }
  648. }
  649. // not a db we manage!
  650. return false;
  651. }
  652. // from a typename of a colun, get the type of the column's affinty
  653. // see https://www.sqlite.org/datatype3.html section 2.1 for rules
  654. function get_type_affinity($type)
  655. {
  656. if (preg_match("/INT/i", $type))
  657. return "INTEGER";
  658. else if (preg_match("/(?:CHAR|CLOB|TEXT)/i", $type))
  659. return "TEXT";
  660. else if (preg_match("/BLOB/i", $type) || $type=="")
  661. return "NONE";
  662. else if (preg_match("/(?:REAL|FLOA|DOUB)/i", $type))
  663. return "REAL";
  664. else
  665. return "NUMERIC";
  666. }
  667. // Returns a file size limit in bytes based on the PHP upload_max_filesize
  668. // post_max_size and memory_limit. Returns -1 in case of no limit.
  669. function fileUploadMaxSize()
  670. {
  671. $max1 = parseSize(ini_get('post_max_size'));
  672. $max2 = parseSize(ini_get('upload_max_filesize'));
  673. $max3 = parseSize(ini_get('memory_limit'));
  674. if($max1>0 && ($max1<=$max2 || $max2==0) && ($max1<=$max3 || $max3==-1))
  675. return $max1;
  676. elseif($max2>0 && ($max2<=$max1 || $max1==0) && ($max2<=$max3 || $max3==-1))
  677. return $max2;
  678. elseif($max3>-1 && ($max3<=$max1 || $max1==0) && ($max3<=$max2 || $max2==0))
  679. return $max3;
  680. else
  681. return -1; // no limit
  682. }
  683. // Parses given size string like "12M" into number of bytes
  684. // based on https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Component%21Utility%21Bytes.php/function/Bytes%3A%3AtoInt/8.2.x
  685. function parseSize($size)
  686. {
  687. // Remove the non-unit characters from the size.
  688. $unit = preg_replace('/[^bkmgtpezy]/i', '', $size);
  689. // Remove the non-numeric characters from the size.
  690. $size = preg_replace('/[^0-9\.]/', '', $size);
  691. if ($unit)
  692. {
  693. // Find the position of the unit in the ordered string which is the power
  694. // of magnitude to multiply a kilobyte by.
  695. return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
  696. }
  697. else {
  698. return round($size);
  699. }
  700. }
  701. //- Check user authentication, login and logout
  702. $auth = new Authorization(); //create authorization object
  703. // check if user has attempted to log out
  704. if (isset($_GET['logout']))
  705. $auth->revoke();
  706. // check if user has attempted to log in
  707. else if (isset($_POST['login']) && isset($_POST['password']))
  708. {
  709. $attempt = $auth->attemptGrant($_POST['password'], isset($_POST['remember']));
  710. $params->redirect( $attempt ? array():array('failed'=>'1') );
  711. }
  712. //- Actions on database files and bulk data
  713. if ($auth->isAuthorized())
  714. {
  715. //- Create a new database
  716. if(isset($_POST['new_dbname']))
  717. {
  718. if($_POST['new_dbname']=='')
  719. $params->redirect(array('table'=>null), $lang['err'].': '.$lang['db_blank']);
  720. else
  721. {
  722. $str = preg_replace('@[^\w\-.]@u','', $_POST['new_dbname']);
  723. $dbname = $str;
  724. $dbpath = $str;
  725. if(checkDbName($dbname))
  726. {
  727. $tdata = array();
  728. $tdata['name'] = $dbname;
  729. $tdata['path'] = $directory.DIRECTORY_SEPARATOR.$dbpath;
  730. if(isset($_POST['new_dbtype']))
  731. $tdata['type'] = $_POST['new_dbtype'];
  732. else
  733. $tdata['type'] = 3;
  734. $td = new Database($tdata);
  735. $td->query("VACUUM");
  736. } else
  737. {
  738. if(is_file($dbname) || is_dir($dbname))
  739. $params->redirect(array('view'=>'structure'),$lang['err'].': '.sprintf($lang['db_exists'], htmlencode($dbname)));
  740. else
  741. $params->redirect(array('view'=>'structure'),$lang['extension_not_allowed'].': '.implode(', ', array_map('htmlencode', $allowed_extensions)).'<br />'.$lang['add_allowed_extension']);
  742. }
  743. }
  744. }
  745. //- Scan a directory for databases
  746. if($directory!==false)
  747. {
  748. if($directory[strlen($directory)-1]==DIRECTORY_SEPARATOR) //if user has a trailing slash in the directory, remove it
  749. $directory = substr($directory, 0, strlen($directory)-1);
  750. if(is_dir($directory)) //make sure the directory is valid
  751. {
  752. if($subdirectories===true)
  753. $arr = dir_tree($directory);
  754. else
  755. $arr = scandir($directory);
  756. $databases = array();
  757. $j = 0;
  758. for($i=0; $i<sizeof($arr); $i++) //iterate through all the files in the databases
  759. {
  760. if($subdirectories===false)
  761. $arr[$i] = $directory.DIRECTORY_SEPARATOR.$arr[$i];
  762. if(@!is_file($arr[$i])) continue;
  763. $con = file_get_contents($arr[$i], NULL, NULL, 0, 60);
  764. if(strpos($con, "** This file contains an SQLite 2.1 database **", 0)!==false || strpos($con, "SQLite format 3", 0)!==false)
  765. {
  766. $databases[$j]['path'] = $arr[$i];
  767. if($subdirectories===false)
  768. $databases[$j]['name'] = basename($arr[$i]);
  769. else
  770. $databases[$j]['name'] = $arr[$i];
  771. $databases[$j]['writable'] = is_writable($databases[$j]['path']);
  772. $databases[$j]['writable_dir'] = is_writable(dirname($databases[$j]['path']));
  773. $databases[$j]['readable'] = is_readable($databases[$j]['path']);
  774. $j++;
  775. }
  776. }
  777. // 22 August 2011: gkf fixed bug #50.
  778. sort($databases);
  779. if(isset($tdata))
  780. {
  781. foreach($databases as $db_id => $database)
  782. {
  783. if($database['path'] === $tdata['path'])
  784. {
  785. $currentDB = $database;
  786. $params->database = $database['path'];
  787. break;
  788. }
  789. }
  790. }
  791. }
  792. else //the directory is not valid - display error and exit
  793. {
  794. echo "<div class='confirm' style='margin:20px;'>".$lang['not_dir']."</div>";
  795. exit();
  796. }
  797. }
  798. else
  799. {
  800. for($i=0; $i<sizeof($databases); $i++)
  801. {
  802. if(!file_exists($databases[$i]['path']))
  803. {
  804. // the file does not exist and will be created when clicked, if permissions allow to
  805. $databases[$i]['writable'] = is_writable(dirname($databases[$i]['path']));
  806. $databases[$i]['writable_dir'] = is_writable(dirname($databases[$i]['path']));
  807. $databases[$i]['readable'] = is_writable(dirname($databases[$i]['path']));
  808. }
  809. else
  810. {
  811. $databases[$i]['writable'] = is_writable($databases[$i]['path']);
  812. $databases[$i]['writable_dir'] = is_writable(dirname($databases[$i]['path']));
  813. $databases[$i]['readable'] = is_readable($databases[$i]['path']);
  814. }
  815. }
  816. sort($databases);
  817. }
  818. // we now have the $databases array set. Check whether selected DB is a managed Db (is in this array)
  819. if(!isset($currentDB) && (isset($_GET['database']) || isset($_POST['database']) ) )
  820. {
  821. $selected_db = ( isset($_POST['database']) ? $_POST['database'] : $_GET['database'] );
  822. $db_key = isManagedDB($selected_db);
  823. if($db_key!==false) {
  824. $currentDB = $databases[$db_key];
  825. $params->database = $databases[$db_key]['path'];
  826. }
  827. }
  828. //- Delete an existing database
  829. if(isset($_GET['database_delete']))
  830. {
  831. $dbpath = $_POST['database_delete'];
  832. // check whether $dbpath really is a db we manage
  833. $checkDB = isManagedDB($dbpath);
  834. if($checkDB !== false)
  835. {
  836. unlink($dbpath);
  837. unset($params->database);
  838. unset($currentDB);
  839. unset($databases[$checkDB]);
  840. } else die($lang['err'].': '.$lang['delete_only_managed']);
  841. }
  842. //- Rename an existing database
  843. if(isset($_GET['database_rename']))
  844. {
  845. $oldpath = $_POST['oldname'];
  846. $newpath = $_POST['newname'];
  847. $oldpath_parts = pathinfo($oldpath);
  848. $newpath_parts = pathinfo($newpath);
  849. // only rename?
  850. $newpath = $oldpath_parts['dirname'].DIRECTORY_SEPARATOR.basename($_POST['newname']);
  851. if($newpath != $_POST['newname'] && $subdirectories)
  852. {
  853. // it seems that the file should not only be renamed but additionally moved.
  854. // we need to make sure it stays within $directory...
  855. $new_realpath = realpath($newpath_parts['dirname']).DIRECTORY_SEPARATOR;
  856. $directory_realpath = realpath($directory).DIRECTORY_SEPARATOR;
  857. if(strpos($new_realpath, $directory_realpath)===0)
  858. {
  859. // its okay, the new directory is within $directory
  860. $newpath = $_POST['newname'];
  861. }
  862. else $params->redirect(array('view'=>'rename'), $lang['err'].': '.$lang['db_moved_outside']);
  863. }
  864. if(checkDbName($newpath))
  865. {
  866. $checkDB = isManagedDB($oldpath);
  867. if($checkDB !==false )
  868. {
  869. rename($oldpath, $newpath);
  870. $databases[$checkDB]['path'] = $newpath;
  871. $databases[$checkDB]['name'] = basename($newpath);
  872. $currentDB = $databases[$checkDB];
  873. $params->database = $databases[$checkDB]['path'];
  874. $params->redirect(array('view'=>'rename'), sprintf($lang['db_renamed'], htmlencode($oldpath))." '".htmlencode($newpath)."'.");
  875. }
  876. else $params->redirect(array('view'=>'rename'), $lang['err'].': '.$lang['rename_only_managed']);
  877. }
  878. else
  879. {
  880. if(is_file($newpath) || is_dir($newpath))
  881. $params->redirect(array('view'=>'rename'), $lang['err'].": " . sprintf($lang['db_exists'], htmlencode($newpath)));
  882. else
  883. $params->redirect(array('view'=>'rename'), $lang['err'].": " . $lang['extension_not_allowed'].': '.implode(', ', array_map('htmlencode', $allowed_extensions)).'<br />'.$lang['add_allowed_extension']);
  884. }
  885. }
  886. //- Export (download a dump) an existing database
  887. if(isset($_POST['export']))
  888. {
  889. ob_end_clean();
  890. $export_filename = str_replace(array("\r", "\n"), '',$_POST['filename']); // against http header injection (php < 5.1.2 only)
  891. if($_POST['export_type']=="sql")
  892. {
  893. header('Content-Type: text/sql');
  894. header('Content-Disposition: attachment; filename="'.$export_filename.'.'.$_POST['export_type'].'";');
  895. if(isset($_POST['tables']))
  896. $tables = $_POST['tables'];
  897. else
  898. {
  899. $tables = array();
  900. $tables[0] = $_POST['single_table'];
  901. }
  902. $drop = isset($_POST['drop']);
  903. $structure = isset($_POST['structure']);
  904. $data = isset($_POST['data']);
  905. $transaction = isset($_POST['transaction']);
  906. $comments = isset($_POST['comments']);
  907. $db = new Database($currentDB);
  908. echo $db->export_sql($tables, $drop, $structure, $data, $transaction, $comments);
  909. }
  910. else if($_POST['export_type']=="csv")
  911. {
  912. header("Content-type: application/csv");
  913. header('Content-Disposition: attachment; filename="'.$export_filename.'.'.$_POST['export_type'].'";');
  914. header("Pragma: no-cache");
  915. header("Expires: 0");
  916. if(isset($_POST['tables']))
  917. $tables = $_POST['tables'];
  918. else
  919. {
  920. $tables = array();
  921. $tables[0] = $_POST['single_table'];
  922. }
  923. $field_terminate = $_POST['export_csv_fieldsterminated'];
  924. $field_enclosed = $_POST['export_csv_fieldsenclosed'];
  925. $field_escaped = $_POST['export_csv_fieldsescaped'];
  926. $null = $_POST['export_csv_replacenull'];
  927. $crlf = isset($_POST['export_csv_crlf']);
  928. $fields_in_first_row = isset($_POST['export_csv_fieldnames']);
  929. $db = new Database($currentDB);
  930. echo $db->export_csv($tables, $field_terminate, $field_enclosed, $field_escaped, $null, $crlf, $fields_in_first_row);
  931. }
  932. exit();
  933. }
  934. //- Import a file into an existing database
  935. if(isset($_POST['import']))
  936. {
  937. $db = new Database($currentDB);
  938. $db->registerUserFunction($custom_functions);
  939. if($_POST['import_type']=="sql")
  940. {
  941. $data = file_get_contents($_FILES["file"]["tmp_name"]);
  942. $importSuccess = $db->import_sql($data);
  943. }
  944. else
  945. {
  946. $field_terminate = $_POST['import_csv_fieldsterminated'];
  947. $field_enclosed = $_POST['import_csv_fieldsenclosed'];
  948. $field_escaped = $_POST['import_csv_fieldsescaped'];
  949. $null = $_POST['import_csv_replacenull'];
  950. $fields_in_first_row = isset($_POST['import_csv_fieldnames']);
  951. if(isset($_POST['single_table']) && $_POST['single_table']!='')
  952. $table = $_POST['single_table'];
  953. else
  954. {
  955. $table = basename($_FILES["file"]["name"],".csv");
  956. $i="";
  957. while($db->getTypeOfTable($table.$i)!="")
  958. {
  959. if($i=="")
  960. $i=2;
  961. else
  962. $i++;
  963. }
  964. $table = $table.$i;
  965. }
  966. $importSuccess = $db->import_csv($_FILES["file"]["tmp_name"], $table, $field_terminate, $field_enclosed, $field_escaped, $null, $fields_in_first_row);
  967. }
  968. }
  969. //- Download (backup) a database file (as SQLite file, not as dump)
  970. if(isset($_GET['download']) && isManagedDB($_GET['download'])!==false)
  971. {
  972. ob_end_clean();
  973. header("Content-type: application/octet-stream");
  974. header('Content-Disposition: attachment; filename="'.basename($_GET['download']).'";');
  975. header("Pragma: no-cache");
  976. header("Expires: 0");
  977. readfile($_GET['download']);
  978. exit;
  979. }
  980. //- Select database (from session or first available)
  981. if(!isset($currentDB) && count($databases)>0)
  982. {
  983. //set the current database to the first existing one in the array (default)
  984. $currentDB = reset($databases);
  985. $params->database = $currentDB['path'];
  986. }
  987. if(isset($currentDB))
  988. {
  989. //- Open database (creates a Database object)
  990. $db = new Database($currentDB); //create the Database object
  991. $db->registerUserFunction($custom_functions);
  992. }
  993. // collect parameters early, just once
  994. $target_table = isset($_GET['table']) ? $_GET['table'] : null;
  995. // are we working on a view? let's check once here
  996. $target_table_type = !is_null($target_table) ? $db->getTypeOfTable($target_table) : null;
  997. if(is_null($target_table_type) && !is_null($target_table))
  998. $params->redirect(array('table'=>null), $lang['err'].': '.sprintf($lang['tbl_inexistent'], htmlencode($target_table)));
  999. $params->table = $target_table;
  1000. // initialize / change fulltexts and numrows parameter
  1001. if(isset($_GET['fulltexts']))
  1002. $params->fulltexts = ($_GET['fulltexts'] ? 1 : 0);
  1003. else
  1004. $params->fulltexts = 0;
  1005. if(isset($_GET['numRows']) && intval($_GET['numRows'])>0)
  1006. $params->numRows = intval($_GET['numRows']);
  1007. else
  1008. $params->numRows = $rowsNum;
  1009. //- Switch on $_GET['action'] for operations without output
  1010. if(isset($_GET['action']) && isset($_GET['confirm']))
  1011. {
  1012. switch($_GET['action'])
  1013. {
  1014. //- Table actions
  1015. //- Create table (=table_create)
  1016. case "table_create":
  1017. $num = intval($_POST['rows']);
  1018. $name = $_POST['tablename'];
  1019. $primary_keys = array();
  1020. for($i=0; $i<$num; $i++)
  1021. {
  1022. if($_POST[$i.'_field']!="" && isset($_POST[$i.'_primarykey']))
  1023. {
  1024. $primary_keys[] = $_POST[$i.'_field'];
  1025. }
  1026. }
  1027. $query = "CREATE TABLE ".$db->quote($name)." (";
  1028. for($i=0; $i<$num; $i++)
  1029. {
  1030. if($_POST[$i.'_field']!="")
  1031. {
  1032. $query .= $db->quote($_POST[$i.'_field'])." ";
  1033. $query .= $_POST[$i.'_type']." ";
  1034. if(isset($_POST[$i.'_primarykey']))
  1035. {
  1036. if(count($primary_keys)==1)
  1037. {
  1038. $query .= "PRIMARY KEY ";
  1039. if(isset($_POST[$i.'_autoincrement']) && $db->getType() != "SQLiteDatabase")
  1040. $query .= "AUTOINCREMENT ";
  1041. }
  1042. $query .= "NOT NULL ";
  1043. }
  1044. if(!isset($_POST[$i.'_primarykey']) && isset($_POST[$i.'_notnull']))
  1045. $query .= "NOT NULL ";
  1046. if($_POST[$i.'_defaultoption']!='defined' && $_POST[$i.'_defaultoption']!='none' && $_POST[$i.'_defaultoption']!='expr')
  1047. $query .= "DEFAULT ".$_POST[$i.'_defaultoption']." ";
  1048. elseif($_POST[$i.'_defaultoption']=='expr')
  1049. $query .= "DEFAULT (".$_POST[$i.'_defaultvalue'].") ";
  1050. elseif(isset($_POST[$i.'_defaultvalue']) && $_POST[$i.'_defaultoption']=='defined')
  1051. {
  1052. $typeAffinity = get_type_affinity($_POST[$i.'_type']);
  1053. if(($typeAffinity=="INTEGER" || $typeAffinity=="REAL" || $typeAffinity=="NUMERIC") && is_numeric($_POST[$i.'_defaultvalue']))
  1054. $query .= "DEFAULT ".$_POST[$i.'_defaultvalue']." ";
  1055. else
  1056. $query .= "DEFAULT ".$db->quote($_POST[$i.'_defaultvalue'])." ";
  1057. }
  1058. $query = substr($query, 0, -1);
  1059. $query .= ", ";
  1060. }
  1061. }
  1062. if (count($primary_keys)>1)
  1063. {
  1064. $compound_key = "";
  1065. foreach ($primary_keys as $primary_key)
  1066. {
  1067. $compound_key .= ($compound_key=="" ? "" : ", ") . $db->quote($primary_key);
  1068. }
  1069. $query .= "PRIMARY KEY (".$compound_key."), ";
  1070. }
  1071. $query = substr($query, 0, -2);
  1072. $query .= ")";
  1073. $result = $db->query($query);
  1074. if($result === false)
  1075. $completed = $db->getError(true);
  1076. else
  1077. $completed = $lang['tbl']." '".htmlencode($_POST['tablename'])."' ".$lang['created'].".<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1078. $params->redirect(($result===false ? array() : array('action'=>'column_view', 'table'=>$name) ), $completed);
  1079. break;
  1080. //- Empty table (=table_empty)
  1081. case "table_empty":
  1082. $query1 = "DELETE FROM ".$db->quote_id($_GET['table']).";";
  1083. $result1 = $db->query($query1);
  1084. if($result1 === false)
  1085. $completed = $db->getError(true);
  1086. if(isset($_POST['vacuum']) && $_POST['vacuum'])
  1087. {
  1088. $query2 = "VACUUM;";
  1089. $result2 = $db->query($query2);
  1090. }
  1091. else
  1092. $query2 = "";
  1093. if($result1 !== false)
  1094. $completed = $lang['tbl']." '".htmlencode($_GET['table'])."' ".$lang['emptied'].".<br/><span style='font-size:11px;'>".htmlencode($query1)."<br />".htmlencode($query2)."</span>";
  1095. $params->redirect(($result1===false ? array() : array('action'=>'row_view') ), $completed);
  1096. break;
  1097. //- Create view (=view_create)
  1098. case "view_create":
  1099. $query = "CREATE VIEW ".$db->quote($_POST['viewname'])." AS ".$_POST['select'];
  1100. $result = $db->query($query);
  1101. if($result === false)
  1102. $completed = $db->getError(true);
  1103. else
  1104. $completed = $lang['view']." '".htmlencode($_POST['viewname'])."' ".$lang['created'].".<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1105. $params->redirect(($result===false ? array() : array('action'=>'column_view', 'table'=>$_POST['viewname']) ), $completed);
  1106. break;
  1107. //- Drop table (=table_drop)
  1108. case "table_drop":
  1109. $query1 = "DROP TABLE ".$db->quote_id($_GET['table']).";";
  1110. $result1=$db->query($query1);
  1111. if($result1 === false)
  1112. $completed = $db->getError(true);
  1113. if(isset($_POST['vacuum']) && $_POST['vacuum'])
  1114. {
  1115. $query2 = "VACUUM;";
  1116. $result2 = $db->query($query2);
  1117. }
  1118. else
  1119. $query2 = "";
  1120. if($result1 !== false)
  1121. {
  1122. $target_table = null;
  1123. $completed = $lang['tbl']." '".htmlencode($_GET['table'])."' ".$lang['dropped'].".<br/><span style='font-size:11px;'>".htmlencode($query1)."<br />".htmlencode($query2)."</span>";;
  1124. }
  1125. $params->redirect(array('table'=>null), $completed);
  1126. break;
  1127. //- Drop view (=view_drop)
  1128. case "view_drop":
  1129. $query = "DROP VIEW ".$db->quote_id($_POST['viewname']);
  1130. $result=$db->query($query);
  1131. if($result === false)
  1132. $completed = $db->getError(true);
  1133. else
  1134. $completed = $lang['view']." '".htmlencode($_POST['viewname'])."' ".$lang['dropped'].".<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1135. $params->redirect(array('table'=>null), $completed);
  1136. break;
  1137. //- Rename table (=table_rename)
  1138. case "table_rename":
  1139. $query = "ALTER TABLE ".$db->quote_id($_GET['table'])." RENAME TO ".$db->quote($_POST['newname']);
  1140. $type = $db->getTypeOfTable($_GET['table']);
  1141. if($db->getVersion()==3 && $type=='table' // SQLite 3 can rename tables, not views
  1142. // In SQL(ite) table names are case-insensitve, so changing is not supported by SQLite.
  1143. // But table names are stored and displayed case sensitive, so we use the workaround for case sensitive renaming.
  1144. && !($_GET['table'] !== $_POST['newname'] && strtolower($_GET['table']) === strtolower($_POST['newname']))
  1145. )
  1146. $result = $db->query($query, true);
  1147. else
  1148. // Workaround can rename tables of sqlite2 and views of both sqlite versions. Can also do case sensitive renames.
  1149. $result = $db->query($query, false);
  1150. if($result === false)
  1151. $completed = $db->getError(true);
  1152. else
  1153. {
  1154. $completed = $lang['tbl']." '".htmlencode($_GET['table'])."' ".$lang['renamed']." '".htmlencode($_POST['newname'])."'.<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1155. $target_table = $_POST['newname'];
  1156. }
  1157. $params->redirect(array('action'=>'row_view', 'table'=>$_POST['newname']), $completed);
  1158. break;
  1159. //- Search table (=table_search)
  1160. case "table_search":
  1161. $searchValues = array();
  1162. $searchOperators = array();
  1163. $tableInfo = $db->getTableInfo($target_table);
  1164. $j = 0;
  1165. $whereExpr = array();
  1166. for($i=0; $i<sizeof($tableInfo); $i++)
  1167. {
  1168. $field = $tableInfo[$i][1];
  1169. $operator = $_POST['field_'.$i.'_operator'];
  1170. $searchOperators[$field] = $operator;
  1171. $value = $_POST['field_'.$i.'_value'];
  1172. if($value!="" || $operator=="!= ''" || $operator=="= ''" || $operator == 'IS NULL' || $operator == 'IS NOT NULL')
  1173. {
  1174. if($operator=="= ''" || $operator=="!= ''" || $operator == 'IS NULL' || $operator == 'IS NOT NULL')
  1175. $whereExpr[$j] = $db->quote_id($field)." ".$operator;
  1176. else{
  1177. if($operator == "LIKE%"){
  1178. $operator = "LIKE";
  1179. if(!preg_match('/(^%)|(%$)/', $value)) $value = '%'.$value.'%';
  1180. $searchValues[$field] = array($value);
  1181. $valueQuoted = $db->quote($value);
  1182. }
  1183. elseif($operator == 'IN' || $operator == 'NOT IN')
  1184. {
  1185. $value = trim($value, '() ');
  1186. $values = explode(',',$value);
  1187. $values = array_map('trim', $values, array_fill(0,count($values),' \'"'));
  1188. if($operator == 'IN')
  1189. $searchValues[$field] = $values;
  1190. $values = array_map(array($db, 'quote'), $values);
  1191. $valueQuoted = '(' .implode(', ', $values) . ')';
  1192. }
  1193. else
  1194. {
  1195. $searchValues[$field] = array($value);
  1196. $valueQuoted = $db->quote($value);
  1197. }
  1198. $whereExpr[$j] = $db->quote_id($field)." ".$operator." ".$valueQuoted;
  1199. }
  1200. $j++;
  1201. }
  1202. }
  1203. $searchWhere = '';
  1204. if(sizeof($whereExpr)>0)
  1205. {
  1206. $searchWhere .= " WHERE ".$whereExpr[0];
  1207. for($i=1; $i<sizeof($whereExpr); $i++)
  1208. {
  1209. $searchWhere .= " AND ".$whereExpr[$i];
  1210. }
  1211. }
  1212. $searchID = md5($searchWhere);
  1213. $_SESSION[COOKIENAME.'search'][$searchID] = array(
  1214. 'where' => $searchWhere,
  1215. 'values' => $searchValues,
  1216. 'operators' => $searchOperators
  1217. );
  1218. $params->redirect(array('action'=>'table_search','search'=>$searchID));
  1219. break;
  1220. //- Row actions
  1221. //- Create row (=row_create)
  1222. case "row_create":
  1223. $completed = "";
  1224. $num = $_POST['newRows'];
  1225. $z = 0;
  1226. $error = false;
  1227. $tableInfo = $db->getTableInfo($target_table);
  1228. for($i=0; $i<$num; $i++)
  1229. {
  1230. if(!isset($_POST[$i.":ignore"]))
  1231. {
  1232. $query_cols = "";
  1233. $query_vals = "";
  1234. $all_default = true;
  1235. for($j=0; $j<sizeof($tableInfo); $j++)
  1236. {
  1237. $null = isset($_POST[$j."_null"][$i]);
  1238. $type = strtoupper($tableInfo[$j]['type']);
  1239. $typeAffinity = get_type_affinity($type);
  1240. if(!$null && isset($_POST[$i.":".$j]))
  1241. $value = $_POST[$i.":".$j];
  1242. else
  1243. $value = "";
  1244. if(preg_match('/^BLOB/', $type))
  1245. {
  1246. if($_FILES[$i.":".$j]["error"] == UPLOAD_ERR_OK && is_file($_FILES[$i.":".$j]["tmp_name"]))
  1247. $blobFiles[$j] = $_FILES[$i.":".$j]["tmp_name"];
  1248. else
  1249. $blobFiles[$j] = null;
  1250. }
  1251. elseif($value===$tableInfo[$j]['dflt_value'])
  1252. {
  1253. // if the value is the default value, skip it
  1254. continue;
  1255. }
  1256. $all_default = false;
  1257. $query_cols .= $db->quote_id($tableInfo[$j]['name']).",";
  1258. $function = $_POST["function_".$j][$i];
  1259. if($function!="")
  1260. $query_vals .= $function."(";
  1261. if(preg_match('/^BLOB/', $type))
  1262. $query_vals .= ':blobval'.$j;
  1263. elseif(($typeAffinity=="TEXT" || $typeAffinity=="NONE") && !$null)
  1264. $query_vals .= $db->quote($value);
  1265. elseif(($typeAffinity=="INTEGER" || $typeAffinity=="REAL"|| $typeAffinity=="NUMERIC") && $value=="")
  1266. $query_vals .= "NULL";
  1267. elseif($null)
  1268. $query_vals .= "NULL";
  1269. else
  1270. $query_vals .= $db->quote($value);
  1271. if($function!="")
  1272. $query_vals .= ")";
  1273. $query_vals .= ",";
  1274. }
  1275. $query = "INSERT INTO ".$db->quote_id($target_table);
  1276. if(!$all_default)
  1277. {
  1278. $query_cols = substr($query_cols, 0, strlen($query_cols)-1);
  1279. $query_vals = substr($query_vals, 0, strlen($query_vals)-1);
  1280. $query.=" (". $query_cols . ") VALUES (". $query_vals. ")";
  1281. } else {
  1282. $query .= " DEFAULT VALUES";
  1283. }
  1284. if(isset($blobFiles))
  1285. {
  1286. // blob files need to be done using a prepared statement because the query size would be too large
  1287. $handle = $db->prepareQuery($query);
  1288. foreach($blobFiles as $j=>$filename)
  1289. $db->bindValue($handle, ':blobval'.$j, file_get_contents($filename), 'blob');
  1290. $result1 = $db->executePrepared($handle, false);
  1291. }
  1292. else
  1293. $result1 = $db->query($query);
  1294. if($result1===false)
  1295. $error = true;
  1296. $completed .= "<span style='font-size:11px;'>".htmlencode($query)."</span><br/>";
  1297. $z++;
  1298. }
  1299. }
  1300. if($error)
  1301. $completed = $db->getError(true);
  1302. else
  1303. $completed = $z." ".$lang['rows']." ".$lang['inserted'].".<br/><br/>".$completed;
  1304. $params->redirect(array('action'=>'row_view'), $completed);
  1305. break;
  1306. //- Delete row (=row_delete)
  1307. case "row_delete":
  1308. $pks = json_decode($_GET['pk']);
  1309. $query = "DELETE FROM ".$db->quote_id($target_table)." WHERE (".$db->wherePK($target_table,json_decode($pks[0])).")";
  1310. for($i=1; $i<sizeof($pks); $i++)
  1311. {
  1312. $query .= " OR (".$db->wherePK($target_table,json_decode($pks[$i])).")";
  1313. }
  1314. $result = $db->query($query);
  1315. if($result === false)
  1316. $completed = $db->getError(true);
  1317. else
  1318. $completed = sizeof($pks)." ".$lang['rows']." ".$lang['deleted'].".<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1319. $params->redirect(array('action'=>'row_view'), $completed);
  1320. break;
  1321. //- Edit row (=row_edit)
  1322. case "row_edit":
  1323. $pks = json_decode($_GET['pk']);
  1324. $z = 0;
  1325. $tableInfo = $db->getTableInfo($target_table);
  1326. if(isset($_POST['new_row']))
  1327. $completed = "";
  1328. else
  1329. $completed = sizeof($pks)." ".$lang['rows']." ".$lang['affected'].".<br/><br/>";
  1330. for($i=0; $i<sizeof($pks); $i++)
  1331. {
  1332. if(isset($_POST['new_row']))
  1333. {
  1334. $query_cols = "";
  1335. $query_vals = "";
  1336. $all_default = true;
  1337. for($j=0; $j<sizeof($tableInfo); $j++)
  1338. {
  1339. $null = isset($_POST[$j."_null"][$i]);
  1340. $type = strtoupper($tableInfo[$j]['type']);
  1341. $typeAffinity = get_type_affinity($type);
  1342. if(!$null)
  1343. {
  1344. if(preg_match('/^BLOB/', $type))
  1345. {
  1346. if(isset($_POST["row_".$i."_field_".$j."_blob_use"]) && $_POST["row_".$i."_field_".$j."_blob_use"]=='old')
  1347. {
  1348. $select = 'SELECT '.$db->quote_id($tableInfo[$j]['name']).' AS \'blob\' FROM '.$db->quote_id($target_table).' WHERE '.$db->wherePK($target_table, json_decode($pks[$i]));
  1349. $bl = $db->select($select);
  1350. $blobFiles[$j] = $bl['blob'];
  1351. unset($bl);
  1352. }
  1353. else
  1354. {
  1355. if($_FILES[$i.":".$j]["error"] == UPLOAD_ERR_OK && is_file($_FILES[$i.":".$j]["tmp_name"]))
  1356. $blobFiles[$j] = file_get_contents($_FILES[$i.":".$j]["tmp_name"]);
  1357. else
  1358. $blobFiles[$j] = null;
  1359. }
  1360. }
  1361. else
  1362. $value = $_POST[$j][$i];
  1363. }
  1364. else
  1365. $value = "";
  1366. if(!preg_match('/^BLOB/', $type) && $value===$tableInfo[$j]['dflt_value'])
  1367. {
  1368. // if the value is the default value, skip it
  1369. continue;
  1370. }
  1371. $all_default = false;
  1372. $query_cols .= $db->quote_id($tableInfo[$j]['name']).",";
  1373. $function = $_POST["function_".$j][$i];
  1374. if($function!="")
  1375. $query_vals .= $function."(";
  1376. if(preg_match('/^BLOB/', $type))
  1377. $query_vals .= ':blobval'.$j;
  1378. elseif(($typeAffinity=="TEXT" || $typeAffinity=="NONE") && !$null)
  1379. $query_vals .= $db->quote($value);
  1380. elseif(($typeAffinity=="INTEGER" || $typeAffinity=="REAL"|| $typeAffinity=="NUMERIC") && $value=="")
  1381. $query_vals .= "NULL";
  1382. elseif($null)
  1383. $query_vals .= "NULL";
  1384. else
  1385. $query_vals .= $db->quote($value);
  1386. if($function!="")
  1387. $query_vals .= ")";
  1388. $query_vals .= ",";
  1389. }
  1390. $query = "INSERT INTO ".$db->quote_id($target_table);
  1391. if(!$all_default)
  1392. {
  1393. $query_cols = substr($query_cols, 0, strlen($query_cols)-1);
  1394. $query_vals = substr($query_vals, 0, strlen($query_vals)-1);
  1395. $query.=" (". $query_cols . ") VALUES (". $query_vals. ")";
  1396. } else {
  1397. $query .= " DEFAULT VALUES";
  1398. }
  1399. if(isset($blobFiles))
  1400. {
  1401. // blob files need to be done using a prepared statement because the query size would be too large
  1402. $handle = $db->prepareQuery($query);
  1403. foreach($blobFiles as $j=>$blobval)
  1404. $db->bindValue($handle, ':blobval'.$j, $blobval, 'blob');
  1405. $result1 = $db->executePrepared($handle, false);
  1406. }
  1407. else
  1408. $result1 = $db->query($query);
  1409. if($result1===false)
  1410. $error = true;
  1411. $z++;
  1412. }
  1413. else
  1414. {
  1415. $query = "UPDATE ".$db->quote_id($target_table)." SET ";
  1416. for($j=0; $j<sizeof($tableInfo); $j++)
  1417. {
  1418. $type = strtoupper($tableInfo[$j]['type']);
  1419. $function = $_POST["function_".$j][$i];
  1420. $null = isset($_POST[$j."_null"][$i]);
  1421. // if the old BLOB value is chosen to be kept, just skip this column
  1422. if(!$null && preg_match('/^BLOB/', $type) && isset($_POST["row_".$i."_field_".$j."_blob_use"]) && $_POST["row_".$i."_field_".$j."_blob_use"]=='old')
  1423. continue;
  1424. if(!$null && preg_match('/^BLOB/', $type))
  1425. {
  1426. if($_FILES[$i.":".$j]["error"] == UPLOAD_ERR_OK && is_file($_FILES[$i.":".$j]["tmp_name"]))
  1427. $blobFiles[$j] = $_FILES[$i.":".$j]["tmp_name"];
  1428. else
  1429. $blobFiles[$j] = null;
  1430. }
  1431. $query .= $db->quote_id($tableInfo[$j]['name'])."=";
  1432. if($function!="")
  1433. $query .= $function."(";
  1434. if($null)
  1435. $query .= "NULL";
  1436. else
  1437. {
  1438. if(preg_match('/^BLOB/', $type))
  1439. $query .= ':blobval'.$j;
  1440. else
  1441. $query .= $db->quote($_POST[$j][$i]);
  1442. }
  1443. if($function!="")
  1444. $query .= ")";
  1445. $query .= ", ";
  1446. }
  1447. $query = substr($query, 0, -2);
  1448. $query .= " WHERE ".$db->wherePK($target_table, json_decode($pks[$i]));
  1449. if(isset($blobFiles))
  1450. {
  1451. // blob files need to be done using a prepared statement because the query size would be too large
  1452. $handle = $db->prepareQuery($query);
  1453. foreach($blobFiles as $j=>$filename)
  1454. $db->bindValue($handle, ':blobval'.$j, file_get_contents($filename), 'blob');
  1455. $result1 = $db->executePrepared($handle, false);
  1456. }
  1457. else
  1458. $result1 = $db->query($query);
  1459. if($result1===false)
  1460. {
  1461. $error = true;
  1462. }
  1463. }
  1464. $completed .= "<span style='font-size:11px;'>".htmlencode($query)."</span><br/>";
  1465. }
  1466. if($error)
  1467. $completed = $db->getError(true);
  1468. elseif(isset($_POST['new_row']))
  1469. $completed = $z." ".$lang['rows']." ".$lang['inserted'].".<br/><br/>".$completed;
  1470. $params->redirect(array('action'=>'row_view'), $completed);
  1471. break;
  1472. case "row_get_blob":
  1473. $blobVal = $db->select("SELECT ".$db->quote_id($_GET['column'])." AS 'blob' FROM ".$db->quote_id($target_table)." WHERE ".$db->wherePK($target_table, json_decode($_GET['pk'])));
  1474. $filename = 'download';
  1475. if(function_exists('getimagesizefromstring')) // introduced in PHP 5.4.0
  1476. $imagesize = getimagesizefromstring($blobVal['blob']);
  1477. if(isset($imagesize) && $imagesize!==false && isset($imagesize['mime']))
  1478. $mimetype = $imagesize['mime'];
  1479. elseif(class_exists('finfo')) // included since php 5.3.0, but might be disabled on Windows
  1480. {
  1481. $finfo = new finfo(FILEINFO_MIME);
  1482. $mimetype = $finfo->buffer($blobVal['blob']);
  1483. }
  1484. else
  1485. $mimetype = "application/octet-stream";
  1486. if(isset($imagesize) && $imagesize!==false && isset($imagesize[2]))
  1487. $extension = image_type_to_extension($imagesize[2]);
  1488. else
  1489. $extension = '.blob';
  1490. ob_end_clean();
  1491. header('Content-Length: '.strlen($blobVal['blob']));
  1492. header("Content-type: ".$mimetype);
  1493. if(isset($_GET['download_blob']) && $_GET['download_blob'])
  1494. header('Content-Disposition: attachment; filename="'.$filename.$extension.'";');
  1495. header("Pragma: no-cache");
  1496. header("Expires: 0");
  1497. echo $blobVal['blob'];
  1498. exit;
  1499. break;
  1500. //- Column actions
  1501. //- Create column (=column_create)
  1502. case "column_create":
  1503. $num = intval($_POST['rows']);
  1504. for($i=0; $i<$num; $i++)
  1505. {
  1506. if($_POST[$i.'_field']!="")
  1507. {
  1508. $query = "ALTER TABLE ".$db->quote_id($target_table)." ADD ".$db->quote($_POST[$i.'_field'])." ";
  1509. $query .= $_POST[$i.'_type']." ";
  1510. if(isset($_POST[$i.'_primarykey']))
  1511. $query .= "PRIMARY KEY ";
  1512. if(isset($_POST[$i.'_notnull']))
  1513. $query .= "NOT NULL ";
  1514. if($_POST[$i.'_defaultoption']!='defined' && $_POST[$i.'_defaultoption']!='none' && $_POST[$i.'_defaultoption']!='expr')
  1515. $query .= "DEFAULT ".$_POST[$i.'_defaultoption']." ";
  1516. elseif($_POST[$i.'_defaultoption']=='expr')
  1517. $query .= "DEFAULT (".$_POST[$i.'_defaultvalue'].") ";
  1518. elseif(isset($_POST[$i.'_defaultvalue']) && $_POST[$i.'_defaultoption']=='defined')
  1519. {
  1520. $typeAffinity = get_type_affinity($_POST[$i.'_type']);
  1521. if(($typeAffinity=="INTEGER" || $typeAffinity=="REAL" || $typeAffinity=="NUMERIC") && is_numeric($_POST[$i.'_defaultvalue']))
  1522. $query .= "DEFAULT ".$_POST[$i.'_defaultvalue']." ";
  1523. else
  1524. $query .= "DEFAULT ".$db->quote($_POST[$i.'_defaultvalue'])." ";
  1525. }
  1526. if($db->getVersion()==3 &&
  1527. ($_POST[$i.'_defaultoption']=='defined' || $_POST[$i.'_defaultoption']=='none' || $_POST[$i.'_defaultoption']=='NULL')
  1528. // Sqlite3 cannot add columns with default values that are not constant
  1529. && !isset($_POST[$i.'_primarykey'])
  1530. // sqlite3 cannot add primary key columns
  1531. && (!isset($_POST[$i.'_notnull']) || $_POST[$i.'_defaultoption']!='none')
  1532. // SQLite3 cannot add NOT NULL columns without DEFAULT even if the table is empty
  1533. )
  1534. // use SQLITE3 ALTER TABLE ADD COLUMN
  1535. $result = $db->query($query, true);
  1536. else
  1537. // use ALTER TABLE workaround
  1538. $result = $db->query($query, false);
  1539. if($result===false)
  1540. $error = true;
  1541. }
  1542. }
  1543. if($error)
  1544. $completed = $db->getError(true);
  1545. else
  1546. $completed = $lang['tbl']." '".htmlencode($target_table)."' ".$lang['altered'].".";
  1547. $params->redirect(array('action'=>'column_view'), $completed);
  1548. break;
  1549. //- Delete column (=column_delete)
  1550. case "column_delete":
  1551. $pks = explode(":", $_GET['pk']);
  1552. $query = "ALTER TABLE ".$db->quote_id($target_table).' DROP '.$db->quote_id($pks[0]);
  1553. for($i=1; $i<sizeof($pks); $i++)
  1554. {
  1555. $query .= ", DROP ".$db->quote_id($pks[$i]);
  1556. }
  1557. $result = $db->query($query);
  1558. if($result === false)
  1559. $completed = $db->getError(true);
  1560. else
  1561. $completed = $lang['tbl']." '".htmlencode($target_table)."' ".$lang['altered'].".";
  1562. $params->redirect(array('action'=>'column_view'), $completed);
  1563. break;
  1564. //- Add a primary key (=primarykey_add)
  1565. case "primarykey_add":
  1566. $pks = explode(":", $_GET['pk']);
  1567. $query = "ALTER TABLE ".$db->quote_id($target_table).' ADD PRIMARY KEY ('.$db->quote_id($pks[0]);
  1568. for($i=1; $i<sizeof($pks); $i++)
  1569. {
  1570. $query .= ", ".$db->quote_id($pks[$i]);
  1571. }
  1572. $query .= ")";
  1573. $result = $db->query($query);
  1574. if($result === false)
  1575. $completed = $db->getError(true);
  1576. else
  1577. $completed = $lang['tbl']." '".htmlencode($target_table)."' ".$lang['altered'].".";
  1578. $params->redirect(array('action'=>'column_view'), $completed);
  1579. break;
  1580. //- Edit column (=column_edit)
  1581. case "column_edit":
  1582. $query = "ALTER TABLE ".$db->quote_id($target_table).' CHANGE '.$db->quote_id($_POST['oldvalue'])." ".$db->quote($_POST['0_field'])." ".$_POST['0_type'];
  1583. $result = $db->query($query);
  1584. if($result === false)
  1585. $completed = $db->getError(true);
  1586. else
  1587. $completed = $lang['tbl']." '".htmlencode($target_table)."' ".$lang['altered'].".";
  1588. $params->redirect(array('action'=>'column_view'), $completed);
  1589. break;
  1590. //- Delete trigger (=trigger_delete)
  1591. case "trigger_delete":
  1592. $query = "DROP TRIGGER ".$db->quote_id($_GET['pk']);
  1593. $result = $db->query($query);
  1594. if($result === false)
  1595. $completed = $db->getError(true);
  1596. else
  1597. $completed = $lang['trigger']." '".htmlencode($_GET['pk'])."' ".$lang['deleted'].".<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1598. $params->redirect(array('action'=>'column_view'), $completed);
  1599. break;
  1600. //- Delete index (=index_delete)
  1601. case "index_delete":
  1602. $query = "DROP INDEX ".$db->quote_id($_GET['pk']);
  1603. $result = $db->query($query);
  1604. if($result === false)
  1605. $completed = $db->getError(true);
  1606. else
  1607. $completed = $lang['index']." '".htmlencode($_GET['pk'])."' ".$lang['deleted'].".<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1608. $params->redirect(array('action'=>'column_view'), $completed);
  1609. break;
  1610. //- Create trigger (=trigger_create)
  1611. case "trigger_create":
  1612. $str = "CREATE TRIGGER ".$db->quote($_POST['trigger_name']);
  1613. if($_POST['beforeafter']!="")
  1614. $str .= " ".$_POST['beforeafter'];
  1615. $str .= " ".$_POST['event']." ON ".$db->quote_id($target_table);
  1616. if(isset($_POST['foreachrow']))
  1617. $str .= " FOR EACH ROW";
  1618. if($_POST['whenexpression']!="")
  1619. $str .= " WHEN ".$_POST['whenexpression'];
  1620. $str .= " BEGIN";
  1621. $str .= " ".$_POST['triggersteps'];
  1622. $str .= " END";
  1623. $query = $str;
  1624. $result = $db->query($query);
  1625. if($result === false)
  1626. $completed = $db->getError(true);
  1627. else
  1628. $completed = $lang['trigger']." ".$lang['created'].".<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1629. $params->redirect(array('action'=>'column_view'), $completed);
  1630. break;
  1631. //- Create index (=index_create)
  1632. case "index_create":
  1633. $num = $_POST['num'];
  1634. if($_POST['name']=="")
  1635. {
  1636. $completed = $lang['blank_index'];
  1637. }
  1638. else if($_POST['0_field']=="")
  1639. {
  1640. $completed = $lang['one_index'];
  1641. }
  1642. else
  1643. {
  1644. $str = "CREATE ";
  1645. if($_POST['duplicate']=="no")
  1646. $str .= "UNIQUE ";
  1647. $str .= "INDEX ".$db->quote($_POST['name'])." ON ".$db->quote_id($target_table)." (";
  1648. $str .= $db->quote_id($_POST['0_field']).$_POST['0_order'];
  1649. for($i=1; $i<$num; $i++)
  1650. {
  1651. if($_POST[$i.'_field']!="")
  1652. $str .= ", ".$db->quote_id($_POST[$i.'_field']).$_POST[$i.'_order'];
  1653. }
  1654. $str .= ")";
  1655. if(isset($_POST['where']) && $_POST['where']!='')
  1656. $str.=" WHERE ".$_POST['where'];
  1657. $query = $str;
  1658. $result = $db->query($query);
  1659. if($result === false)
  1660. $completed = $db->getError(true);
  1661. else
  1662. $completed = $lang['index']." ".$lang['created'].".<br/><span style='font-size:11px;'>".htmlencode($query)."</span>";
  1663. }
  1664. $params->redirect(array('action'=>'column_view'), $completed);
  1665. break;
  1666. }
  1667. }
  1668. }
  1669. // if not in debug mode, destroy all output until here
  1670. if($debug)
  1671. $bufferedOutput = ob_get_contents();
  1672. ob_end_clean();
  1673. //- HTML: output starts here
  1674. header('Content-Type: text/html; charset=utf-8');
  1675. ?>
  1676. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  1677. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  1678. <head>
  1679. <!-- Copyright <?php echo date("Y").' '.PROJECT.' ('.PROJECT_URL.')'; ?> -->
  1680. <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
  1681. <link rel="shortcut icon" href="?resource=favicon" />
  1682. <title><?php echo PROJECT ?></title>
  1683. <?php
  1684. //- HTML: css/theme include
  1685. if(isset($_GET['theme'])) $theme = basename($_GET['theme']);
  1686. // allow themes to be dropped in subfolder "themes"
  1687. if(is_file('themes/'.$theme)) $theme = 'themes/'.$theme;
  1688. if (file_exists($theme))
  1689. // an external stylesheet exists - import it
  1690. echo "<link href='{$theme}' rel='stylesheet' type='text/css' />", PHP_EOL;
  1691. else
  1692. // only use the default stylesheet if an external one does not exist
  1693. echo "<link href='?resource=css' rel='stylesheet' type='text/css' />", PHP_EOL;
  1694. // HTML: output help text, then exit
  1695. if(isset($_GET['help']))
  1696. {
  1697. //help section array
  1698. $help = array($lang['help1'] => sprintf($lang['help1_x'], PROJECT, PROJECT, PROJECT));
  1699. for($i=2; isset($lang['help'.$i]); $i++)
  1700. $help[$lang['help'.$i]]=$lang['help'.$i.'_x'];
  1701. ?>
  1702. </head>
  1703. <body style="direction:<?php echo $lang['direction']; ?>;">
  1704. <div id='help_container'>
  1705. <?php
  1706. echo "<div class='help_list'>";
  1707. echo "<span style='font-size:18px;'>".PROJECT." v".VERSION." ".$lang['help_doc']."</span><br/><br/>";
  1708. foreach((array)$help as $key => $val)
  1709. {
  1710. echo "<a href='#".$key."'>".$key."</a><br/>";
  1711. }
  1712. echo "</div>";
  1713. echo "<br/><br/>";
  1714. foreach((array)$help as $key => $val)
  1715. {
  1716. echo "<div class='help_outer'>";
  1717. echo "<a class='headd' name='".$key."'>".$key."</a>";
  1718. echo "<div class='help_inner'>";
  1719. echo $val;
  1720. echo "</div>";
  1721. echo "<a class='help_top' href='#top'>".$lang['back_top']."</a>";
  1722. echo "</div>";
  1723. }
  1724. ?>
  1725. </div>
  1726. </body>
  1727. </html>
  1728. <?php
  1729. exit();
  1730. }
  1731. if($auth->isAuthorized())
  1732. {
  1733. //- Javascript include
  1734. ?>
  1735. <!-- JavaScript Support -->
  1736. <script type='text/javascript' src='?resource=javascript'></script>
  1737. <script type="text/javascript">
  1738. var fileUploadMaxSize = <?php echo fileUploadMaxSize(); ?>;
  1739. var fileUploadMaxSizeErrorMsg = '<?php echo $lang['err'].': \n'.$lang['max_file_size']; ?>';
  1740. </script>
  1741. <!-- SQL code editor with Syntax Highlighting etc. -->
  1742. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.24.2/codemirror.min.css">
  1743. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.24.2/addon/hint/show-hint.min.css">
  1744. <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.24.2/codemirror.min.js"></script>
  1745. <!-- Codemirror 5.24.2 does not yet include the SQLite support that we wrote, so we fetch changed files from rawgit for the time being-->
  1746. <script src="https://cdn.rawgit.com/codemirror/CodeMirror/c4387d6073b15ccf0f32773eb71a54f3b694f2f0/mode/sql/sql.js"></script>
  1747. <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.24.2/addon/hint/show-hint.min.js"></script>
  1748. <script src="https://cdn.rawgit.com/codemirror/CodeMirror/65c70cf5d18ac3a0c1a3fe717d90a81ff823aa9f/addon/hint/sql-hint.js"></script>
  1749. <?php
  1750. }
  1751. ?>
  1752. </head>
  1753. <body style="direction:<?php echo $lang['direction']; ?>;">
  1754. <?php
  1755. // if in debug mode, ouput all output that has been generated above now
  1756. if($debug)
  1757. echo $bufferedOutput;
  1758. if(ini_get("register_globals") == "on" || ini_get("register_globals")=="1") //check whether register_globals is turned on - if it is, we need to not continue
  1759. {
  1760. echo "<div class='confirm' style='margin:20px;'>".$lang['bad_php_directive']."</div>";
  1761. echo "</body></html>";
  1762. exit();
  1763. }
  1764. //- HTML: login screen if not authorized, exit
  1765. if(!$auth->isAuthorized())
  1766. {
  1767. echo "<div id='loginBox'>";
  1768. echo "<h1><span id='logo'>".PROJECT."</span> <span id='version'>v".VERSION."</span></h1>";
  1769. echo "<div style='padding:15px; text-align:center;'>";
  1770. if (isset($_GET['failed']))
  1771. echo "<span class='warning'>".$lang['passwd_incorrect']."</span><br/><br/>";
  1772. echo $params->getForm();
  1773. echo $lang['passwd'].": <input type='password' name='password' autofocus='autofocus'/><br/>";
  1774. echo "<label><input type='checkbox' name='remember' value='yes' checked='checked'/> ".$lang['remember']."</label><br/><br/>";
  1775. echo "<input type='submit' value='".$lang['login']."' class='btn'/>";
  1776. echo "<input type='hidden' name='login' value='true' />";
  1777. echo "</form>";
  1778. echo "</div>";
  1779. echo "</div>";
  1780. echo "<br/>";
  1781. echo "<div style='text-align:center;'>";
  1782. echo "<span style='font-size:11px;'>".$lang['powered']." <a href='".PROJECT_URL."' target='_blank' style='font-size:11px;'>".PROJECT."</a> | ";
  1783. printf($lang['page_gen'], $pageTimer);
  1784. echo "</span></div>";
  1785. echo "</body></html>";
  1786. exit();
  1787. }
  1788. //- User is authorized, display the main application
  1789. if(count($databases)==0) // the database array is empty, offer to create a new database
  1790. {
  1791. //- HTML: form to create a new database, exit
  1792. if($directory!==false && is_writable($directory))
  1793. {
  1794. echo "<div class='confirm' style='margin:20px;'>";
  1795. printf($lang['no_db'], PROJECT, PROJECT);
  1796. echo "</div>";
  1797. //if the user has performed some action, show the resulting message
  1798. if(isset($_GET['message']) && isset($_SESSION[COOKIENAME.'messages'][$_GET['message']]))
  1799. {
  1800. echo "<div class='confirm' style='margin:10px 20px;'>";
  1801. echo $_SESSION[COOKIENAME.'messages'][$_GET['message']];
  1802. echo "</div><br />";
  1803. unset($_SESSION[COOKIENAME.'messages'][$_GET['message']]);
  1804. }
  1805. echo "<fieldset style='margin:15px;'><legend><b>".$lang['db_create']."</b></legend>";
  1806. echo $params->getForm(array('table'=>null), 'post', false, 'create_database');
  1807. echo "<input type='text' name='new_dbname' style='width:150px;'/> ";
  1808. if(class_exists('SQLiteDatabase') && (class_exists('SQLite3') || class_exists('PDO')))
  1809. {
  1810. echo "<select name='new_dbtype' class='newDbType'>";
  1811. echo "<option value='3'>SQLite 3</option>";
  1812. echo "<option value='2'>SQLite 2</option>";
  1813. echo "</select>";
  1814. }
  1815. echo "<input type='submit' value='".$lang['create']."' class='btn'/>";
  1816. echo "</form>";
  1817. echo "</fieldset>";
  1818. }
  1819. elseif(($directory!==false && !is_executable($directory)))
  1820. {
  1821. echo "<div class='confirm' style='margin:20px;'>";
  1822. echo $lang['err'].": ".sprintf($lang['dir_not_executable'], PROJECT, $directory);
  1823. echo "</div><br/>";
  1824. }
  1825. else
  1826. {
  1827. echo "<div class='confirm' style='margin:20px;'>";
  1828. echo $lang['err'].": ".sprintf($lang['no_db2'], PROJECT);
  1829. echo "</div><br/>";
  1830. }
  1831. exit();
  1832. }
  1833. //- HTML: sidebar
  1834. echo '<table class="body_tbl" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td valign="top" class="left_td" style="width:100px; padding:9px 2px 9px 9px;">';
  1835. echo "<div id='leftNav'>";
  1836. echo "<h1><a href='".$params->getURL()."'>";
  1837. echo "<span id='logo'>".PROJECT."</span> <span id='version'>v".VERSION."</span>";
  1838. echo "</a></h1>";
  1839. echo "<div id='headerlinks'>";
  1840. echo "<a href='javascript:void' onclick='openHelp(\"top\");'>".$lang['docu']."</a> | ";
  1841. echo "<a href='https://www.gnu.org/licenses/gpl.html' target='_blank'>".$lang['license']."</a> | ";
  1842. echo "<a href='".PROJECT_URL."' target='_blank'>".$lang['proj_site']."</a>";
  1843. echo "</div>";
  1844. //- HTML: database list
  1845. $db->print_db_list();
  1846. echo "<fieldset style='margin:15px;'><legend>";
  1847. echo "<a href='".$params->getURL(array('table'=>null))."'";
  1848. if (!$target_table)
  1849. echo " class='active_table'";
  1850. $name = $currentDB['name'];
  1851. if(strlen($name)>25)
  1852. $name = "...".substr($name, strlen($name)-22, 22);
  1853. echo ">".htmlencode($name)."</a>";
  1854. echo "</legend>";
  1855. //- HTML: table list
  1856. $tables = $db->getTables(true, false);
  1857. foreach($tables as $tableName => $tableType)
  1858. {
  1859. echo "<span class='sidebar_table'>";
  1860. echo $params->getLink(array('action'=>'column_view', 'table'=>$tableName), "[".$lang[$tableType=='table'?'tbl':'view']."]");
  1861. echo "</span> ";
  1862. echo $params->getLink(array('action'=>'row_view', 'table'=>$tableName), htmlencode($tableName),
  1863. ($target_table == $tableName ? 'active_table' : '') );
  1864. echo "<br/>";
  1865. }
  1866. if(count($tables)==0)
  1867. echo $lang['no_tbl'];
  1868. echo "</fieldset>";
  1869. //- HTML: form to create a new database
  1870. if($directory!==false && is_writable($directory))
  1871. {
  1872. echo "<fieldset style='margin:15px;'><legend><b>".$lang['db_create']."</b> ".helpLink($lang['help2'])."</legend>";
  1873. echo $params->getForm(array('table'=>null), 'post', false, 'create_database');
  1874. echo "<input type='text' name='new_dbname' style='width:150px;'/>";
  1875. if(class_exists('SQLiteDatabase') && (class_exists('SQLite3') || class_exists('PDO')))
  1876. {
  1877. echo "<select name='new_dbtype' class='newDbType'>";
  1878. echo "<option value='3'>SQLite 3</option>";
  1879. echo "<option value='2'>SQLite 2</option>";
  1880. echo "</select>";
  1881. }
  1882. echo "<input type='submit' value='".$lang['create']."' class='btn'/>";
  1883. echo "</form>";
  1884. echo "</fieldset>";
  1885. }
  1886. echo "<div style='text-align:center;'>";
  1887. echo $params->getForm(array(),'get');
  1888. echo "<input type='submit' value='".$lang['logout']."' name='logout' class='btn'/>";
  1889. echo "</form>";
  1890. echo "</div>";
  1891. echo "</div>";
  1892. echo '</td><td valign="top" id="main_column" class="right_td" style="padding:9px 2px 9px 9px;">';
  1893. //- HTML: breadcrumb navigation
  1894. echo $params->getLink(array('table'=>null), htmlencode($currentDB['name']));
  1895. if ($target_table)
  1896. echo " &rarr; ".$params->getLink(array('action'=>'row_view'), htmlencode($target_table));
  1897. echo "<br/><br/>";
  1898. //- Show the various tab views for a table
  1899. if($target_table)
  1900. {
  1901. //- HTML: tabs
  1902. echo $params->getLink(array('action'=>'row_view'), $lang['browse'],
  1903. (in_array($_GET['action'], array('row_view', 'row_editordelete') ) ? 'tab_pressed' : 'tab'));
  1904. echo $params->getLink(array('action'=>'column_view'), $lang['struct'],
  1905. (in_array($_GET['action'], array('column_view', 'column_edit', 'column_confirm', 'primarykey_add', 'column_create', 'index_create', 'index_delete', 'trigger_create', 'trigger_delete') ) ? 'tab_pressed' : 'tab'));
  1906. echo $params->getLink(array('action'=>'table_sql'), $lang['sql'],
  1907. ($_GET['action']=="table_sql" ? 'tab_pressed' : 'tab'));
  1908. echo $params->getLink(array(
  1909. 'action' => 'table_search',
  1910. 'oldSearch' => (isset($_GET['search'])?$_GET['search']:null)
  1911. ), $lang['srch'], ($_GET['action']=="table_search" ? 'tab_pressed' : 'tab'));
  1912. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  1913. echo $params->getLink(array('action'=>'row_create'), $lang['insert'],
  1914. ($_GET['action']=="row_create" ? 'tab_pressed' : 'tab'));
  1915. echo $params->getLink(array('action'=>'table_export'), $lang['export'],
  1916. ($_GET['action']=="table_export" ? 'tab_pressed' : 'tab'));
  1917. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  1918. echo $params->getLink(array('action'=>'table_import'), $lang['import'],
  1919. ($_GET['action']=="table_import" ? 'tab_pressed' : 'tab'));
  1920. if($db->isWritable() && $db->isDirWritable())
  1921. echo $params->getLink(array('action'=>'table_rename'), $lang['rename'],
  1922. ($_GET['action']=="table_rename" ? 'tab_pressed' : 'tab'));
  1923. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  1924. {
  1925. echo $params->getLink(array('action'=>'table_empty'), $lang['empty'],
  1926. ($_GET['action']=="table_empty" ? 'tab_pressed empty' : 'tab empty'));
  1927. echo $params->getLink(array('action'=>'table_drop'), $lang['drop'],
  1928. ($_GET['action']=="table_drop" ? 'tab_pressed drop' : 'tab drop'));
  1929. } elseif($db->isWritable() && $db->isDirWritable()) {
  1930. echo $params->getLink(array('action'=>'view_drop'), $lang['drop'],
  1931. ($_GET['action']=="view_drop" ? 'tab_pressed drop' : 'tab drop'));
  1932. }
  1933. }
  1934. else
  1935. //- Show the various tab views for a database
  1936. {
  1937. $view = isset($_GET['view']) ? $_GET['view'] : 'structure';
  1938. echo $params->getLink(array('view'=>'structure'), $lang['struct'], ($view=="structure" ? 'tab_pressed': 'tab') );
  1939. echo $params->getLink(array('view'=>'sql'), $lang['sql'], ($view=="sql" ? 'tab_pressed': 'tab') );
  1940. echo $params->getLink(array('view'=>'export'), $lang['export'], ($view=="export" ? 'tab_pressed': 'tab') );
  1941. if($db->isWritable() && $db->isDirWritable())
  1942. echo $params->getLink(array('view'=>'import'), $lang['import'], ($view=="import" ? 'tab_pressed': 'tab') );
  1943. if($db->isWritable() && $db->isDirWritable())
  1944. echo $params->getLink(array('view'=>'vacuum'), $lang['vac'], ($view=="vacuum" ? 'tab_pressed': 'tab') );
  1945. if($directory!==false && is_writable($directory))
  1946. {
  1947. echo $params->getLink(array('view'=>'rename'), $lang['db_rename'], ($view=="rename" ? 'tab_pressed': 'tab') );
  1948. echo $params->getLink(array('view'=>'delete'), "<span>".$lang['db_del']."</span>", ($view=="delete" ? 'tab_pressed delete_db': 'tab delete_db') );
  1949. }
  1950. }
  1951. echo "<div style='clear:both;'></div>";
  1952. echo "<div id='main'>";
  1953. //- HTML: confirmation panel
  1954. //if the user has performed some action, show the resulting message
  1955. if(isset($_GET['message']) && isset($_SESSION[COOKIENAME.'messages'][$_GET['message']]))
  1956. {
  1957. echo "<div class='confirm'>";
  1958. echo $_SESSION[COOKIENAME.'messages'][$_GET['message']];
  1959. echo "</div><br />";
  1960. unset($_SESSION[COOKIENAME.'messages'][$_GET['message']]);
  1961. }
  1962. //- Switch on $_GET['action'] for operations with output
  1963. if(isset($_GET['action']) && !isset($_GET['confirm']))
  1964. {
  1965. switch($_GET['action'])
  1966. {
  1967. //- Table actions
  1968. //- Create table (=table_create)
  1969. case "table_create":
  1970. $query = "SELECT name FROM sqlite_master WHERE type='table' AND name=".$db->quote($_GET['tablename']);
  1971. $results = $db->selectArray($query);
  1972. if(sizeof($results)>0)
  1973. $exists = true;
  1974. else
  1975. $exists = false;
  1976. echo "<h2>".$lang['create_tbl'].": '".htmlencode($_GET['tablename'])."'</h2>";
  1977. if($_GET['tablefields']=="" || intval($_GET['tablefields'])<=0)
  1978. echo $lang['specify_fields'];
  1979. else if($_GET['tablename']=="")
  1980. echo $lang['specify_tbl'];
  1981. else if($exists)
  1982. echo $lang['tbl_exists'];
  1983. else
  1984. {
  1985. $num = intval($_GET['tablefields']);
  1986. $name = $_GET['tablename'];
  1987. echo $params->getForm(array('action'=>'table_create', 'confirm'=>'1'));
  1988. echo "<input type='hidden' name='tablename' value='".htmlencode($name)."'/>";
  1989. echo "<input type='hidden' name='rows' value='".$num."'/>";
  1990. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  1991. echo "<tr>";
  1992. $headings = array($lang['fld'], $lang['type'], $lang['prim_key']);
  1993. if($db->getType() != "SQLiteDatabase") $headings[] = $lang['autoincrement'];
  1994. $headings[] = $lang['not_null'];
  1995. $headings[] = $lang['def_val'];
  1996. for($k=0; $k<count($headings); $k++)
  1997. echo "<td class='tdheader'>" . $headings[$k] . "</td>";
  1998. echo "</tr>";
  1999. for($i=0; $i<$num; $i++)
  2000. {
  2001. $tdWithClass = "<td class='td" . ($i%2 ? "1" : "2") . "'>";
  2002. echo "<tr>";
  2003. echo $tdWithClass;
  2004. echo "<input type='text' name='".$i."_field' style='width:200px;'/>";
  2005. echo "</td>";
  2006. echo $tdWithClass;
  2007. echo "<select name='".$i."_type' id='i".$i."_type' onchange='toggleAutoincrement(".$i.");'>";
  2008. foreach ($sqlite_datatypes as $t) {
  2009. echo "<option value='".htmlencode($t)."'>".htmlencode($t)."</option>";
  2010. }
  2011. echo "</select>";
  2012. echo "</td>";
  2013. echo $tdWithClass;
  2014. echo "<label><input type='checkbox' name='".$i."_primarykey' id='i".$i."_primarykey' onclick='toggleNull(".$i."); toggleAutoincrement(".$i.");'/> ".$lang['yes']."</label>";
  2015. echo "</td>";
  2016. if($db->getType() != "SQLiteDatabase")
  2017. {
  2018. echo $tdWithClass;
  2019. echo "<label><input type='checkbox' name='".$i."_autoincrement' id='i".$i."_autoincrement'/> ".$lang['yes']."</label>";
  2020. echo "</td>";
  2021. }
  2022. echo $tdWithClass;
  2023. echo "<label><input type='checkbox' name='".$i."_notnull' id='i".$i."_notnull'/> ".$lang['yes']."</label>";
  2024. echo "</td>";
  2025. echo $tdWithClass;
  2026. echo "<select name='".$i."_defaultoption' id='i".$i."_defaultoption' onchange=\"if(this.value!='defined' && this.value!='expr') document.getElementById('i".$i."_defaultvalue').value='';\">";
  2027. echo "<option value='none'>".$lang['none']."</option><option value='defined'>".$lang['as_defined'].":</option><option>NULL</option><option>CURRENT_TIME</option><option>CURRENT_DATE</option><option>CURRENT_TIMESTAMP</option><option value='expr'>".$lang['expression'].":</option>";
  2028. echo "</select>";
  2029. echo "<input type='text' name='".$i."_defaultvalue' id='i".$i."_defaultvalue' style='width:100px;' onchange=\"if(document.getElementById('i".$i."_defaultoption').value!='expr') document.getElementById('i".$i."_defaultoption').value='defined';\"/>";
  2030. echo "</td>";
  2031. echo "</tr>";
  2032. }
  2033. echo "<tr>";
  2034. echo "<td class='tdheader' style='text-align:right;' colspan='6'>";
  2035. echo "<input type='submit' value='".$lang['create']."' class='btn'/> ";
  2036. echo $params->getLink(array(), $lang['cancel']);
  2037. echo "</td>";
  2038. echo "</tr>";
  2039. echo "</table>";
  2040. echo "</form>";
  2041. if($db->getType() != "SQLiteDatabase") echo "<script type='text/javascript'>window.onload=initAutoincrement;</script>";
  2042. }
  2043. break;
  2044. //- Perform SQL query on table (=table_sql)
  2045. case "table_sql":
  2046. if(isset($_POST['query']) && $_POST['query']!="")
  2047. {
  2048. $delimiter = $_POST['delimiter'];
  2049. $queryStr = $_POST['queryval'];
  2050. //save the queries in history if necessary
  2051. if($maxSavedQueries!=0 && $maxSavedQueries!=false)
  2052. {
  2053. if(!isset($_SESSION[COOKIENAME.'query_history']))
  2054. $_SESSION[COOKIENAME.'query_history'] = array();
  2055. $_SESSION[COOKIENAME.'query_history'][md5(strtolower($queryStr))] = $queryStr;
  2056. if(sizeof($_SESSION[COOKIENAME.'query_history']) > $maxSavedQueries)
  2057. array_shift($_SESSION[COOKIENAME.'query_history']);
  2058. }
  2059. $query = explode_sql($delimiter, $queryStr); //explode the query string into individual queries based on the delimiter
  2060. for($i=0; $i<sizeof($query); $i++) //iterate through the queries exploded by the delimiter
  2061. {
  2062. if(str_replace(" ", "", str_replace("\n", "", str_replace("\r", "", $query[$i])))!="") //make sure this query is not an empty string
  2063. {
  2064. $queryTimer = new MicroTimer();
  2065. $table_result = $db->query($query[$i]);
  2066. echo "<div class='confirm'>";
  2067. echo "<b>".htmlencode($query[$i])."</b>";
  2068. if($table_result === NULL || $table_result === false)
  2069. {
  2070. echo "<br /><b>".$lang['err'].": ".htmlencode($db->getError())."</b></div>";
  2071. }
  2072. echo "</div><br/>";
  2073. if($row = $db->fetch($table_result, 'num'))
  2074. {
  2075. for($j=0; $j<sizeof($row);$j++)
  2076. $headers[$j] = $db->getColumnName($table_result,$j);
  2077. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  2078. echo "<tr>";
  2079. for($j=0; $j<sizeof($headers); $j++)
  2080. {
  2081. echo "<td class='tdheader'>";
  2082. echo htmlencode($headers[$j]);
  2083. echo "</td>";
  2084. }
  2085. echo "</tr>";
  2086. $rowCount = 0;
  2087. for(; $rowCount==0 || $row = $db->fetch($table_result, 'num'); $rowCount++)
  2088. {
  2089. $tdWithClass = "<td class='td".($rowCount%2 ? "1" : "2")."'>";
  2090. echo "<tr>";
  2091. for($z=0; $z<sizeof($headers); $z++)
  2092. {
  2093. echo $tdWithClass;
  2094. if($row[$z]==="")
  2095. echo "&nbsp;";
  2096. elseif($row[$z]===NULL)
  2097. echo "<i class='null'>NULL</i>";
  2098. else
  2099. echo htmlencode(subString($row[$z]));
  2100. echo "</td>";
  2101. }
  2102. echo "</tr>";
  2103. }
  2104. $queryTimer->stop();
  2105. echo "</table><br/><br/>";
  2106. if($table_result !== NULL && $table_result !== false)
  2107. {
  2108. echo "<div class='confirm' style='margin-bottom: 2em'>";
  2109. if($rowCount>0 || $db->getAffectedRows()==0)
  2110. {
  2111. printf($lang['show_rows'], $rowCount);
  2112. }
  2113. if($db->getAffectedRows()>0 || $rowCount==0)
  2114. {
  2115. echo $db->getAffectedRows()." ".$lang['rows_aff']." ";
  2116. }
  2117. printf($lang['query_time'], $queryTimer);
  2118. echo "</div>";
  2119. }
  2120. }
  2121. }
  2122. }
  2123. }
  2124. else
  2125. {
  2126. $delimiter = ";";
  2127. $queryStr = "SELECT * FROM ".$db->quote_id($target_table)." WHERE 1";
  2128. }
  2129. echo "<fieldset>";
  2130. echo "<legend><b>".sprintf($lang['run_sql'],htmlencode($db->getName()))."</b></legend>";
  2131. echo $params->getForm(array('action'=>'table_sql'));
  2132. if(isset($_SESSION[COOKIENAME.'query_history']) && sizeof($_SESSION[COOKIENAME.'query_history'])>0)
  2133. {
  2134. echo "<b>".$lang['recent_queries']."</b><ul>";
  2135. foreach($_SESSION[COOKIENAME.'query_history'] as $key => $value)
  2136. echo "<li><a onclick='sqleditorSetValue(this.textContent); return false;' href='#'>".htmlencode($value)."</a></li>";
  2137. echo "</ul><br/><br/>";
  2138. }
  2139. echo "<div style='float:left; width:70%;'>";
  2140. echo "<textarea style='width:97%; height:300px;' name='queryval' id='queryval' cols='50' rows='8'>".htmlencode($queryStr)."</textarea>";
  2141. echo "<script>sqleditor(document.getElementById('queryval'),".json_encode($db->getTableDefinitions()).",'".htmlencode($target_table)."');</script>";
  2142. echo "</div>";
  2143. echo "<div style='float:left; width:28%; padding-left:10px;'>";
  2144. echo $lang['fields']."<br/>";
  2145. echo "<select multiple='multiple' style='width:100%;' id='fieldcontainer'>";
  2146. $tableInfo = $db->getTableInfo($target_table);
  2147. for($i=0; $i<sizeof($tableInfo); $i++)
  2148. {
  2149. echo "<option value='".htmlencode($tableInfo[$i][1])."'>".htmlencode($tableInfo[$i][1])."</option>";
  2150. }
  2151. echo "</select>";
  2152. echo "<input type='button' value='&lt;&lt;' onclick='moveFields();' class='btn'/>";
  2153. echo "</div>";
  2154. echo "<div style='clear:both;'></div>";
  2155. echo $lang['delimit']." <input type='text' name='delimiter' value='".htmlencode($delimiter)."' style='width:50px;'/> ";
  2156. echo "<input type='submit' name='query' value='".$lang['go']."' class='btn'/>";
  2157. echo "</form>";
  2158. echo "</fieldset>";
  2159. break;
  2160. //- Empty table (=table_empty)
  2161. case "table_empty":
  2162. echo $params->getForm(array('action'=>'table_empty','confirm'=>'1'));
  2163. echo "<div class='confirm'>";
  2164. echo sprintf($lang['ques_empty'], htmlencode($target_table))."<br/><br/>";
  2165. echo "<input type='checkbox' name='vacuum' checked='checked'/> ".$lang['vac_on_empty']."<br/><br/>";
  2166. echo "<input type='submit' value='".$lang['confirm']."' class='btn'/> ";
  2167. echo $params->getLink(array('table'=>null), $lang['cancel']);
  2168. echo "</div>";
  2169. break;
  2170. //- Drop table (=table_drop)
  2171. case "table_drop":
  2172. echo $params->getForm(array('action'=>'table_drop','confirm'=>'1'));
  2173. echo "<div class='confirm'>";
  2174. echo sprintf($lang['ques_drop'], htmlencode($target_table))."<br/><br/>";
  2175. echo "<input type='checkbox' name='vacuum' checked='checked'/> ".$lang['vac_on_empty']."<br/><br/>";
  2176. echo "<input type='submit' value='".$lang['confirm']."' class='btn'/> ";
  2177. echo $params->getLink(array('table'=>null), $lang['cancel']);
  2178. echo "</div>";
  2179. break;
  2180. //- Drop view (=view_drop)
  2181. case "view_drop":
  2182. echo $params->getForm(array('action'=>'view_drop','confirm'=>'1'));
  2183. echo "<input type='hidden' name='viewname' value='".htmlencode($target_table)."'/>";
  2184. echo "<div class='confirm'>";
  2185. echo sprintf($lang['ques_drop_view'], htmlencode($target_table))."<br/><br/>";
  2186. echo "<input type='submit' value='".$lang['confirm']."' class='btn'/> ";
  2187. echo $params->getLink(array('table'=>null), $lang['cancel']);
  2188. echo "</div>";
  2189. break;
  2190. //- Export table (=table_export)
  2191. case "table_export":
  2192. echo $params->getForm();
  2193. echo "<fieldset style='float:left; width:260px; margin-right:20px;'><legend><b>".$lang['export']."</b></legend>";
  2194. echo "<input type='hidden' value='".htmlencode($target_table)."' name='single_table'/>";
  2195. echo "<label><input type='radio' name='export_type' checked='checked' value='sql' onclick='toggleExports(\"sql\");'/> ".$lang['sql']."</label>";
  2196. echo "<br/><label><input type='radio' name='export_type' value='csv' onclick='toggleExports(\"csv\");'/> ".$lang['csv']."</label>";
  2197. echo "</fieldset>";
  2198. echo "<fieldset style='float:left; max-width:350px;' id='exportoptions_sql'><legend><b>".$lang['options']."</b></legend>";
  2199. echo "<label><input type='checkbox' checked='checked' name='structure'/> ".$lang['export_struct']."</label> ".helpLink($lang['help5'])."<br/>";
  2200. echo "<label><input type='checkbox' checked='checked' name='data'/> ".$lang['export_data']."</label> ".helpLink($lang['help6'])."<br/>";
  2201. echo "<label><input type='checkbox' name='drop'/> ".$lang['add_drop']."</label> ".helpLink($lang['help7'])."<br/>";
  2202. echo "<label><input type='checkbox' checked='checked' name='transaction'/> ".$lang['add_transact']."</label> ".helpLink($lang['help8'])."<br/>";
  2203. echo "<label><input type='checkbox' checked='checked' name='comments'/> ".$lang['comments']."</label> ".helpLink($lang['help9'])."<br/>";
  2204. echo "</fieldset>";
  2205. echo "<fieldset style='float:left; max-width:350px; display:none;' id='exportoptions_csv'><legend><b>".$lang['options']."</b></legend>";
  2206. echo "<div style='float:left;'>".$lang['fld_terminated']."</div>";
  2207. echo "<input type='text' value=';' name='export_csv_fieldsterminated' style='float:right;'/>";
  2208. echo "<div style='clear:both;'></div>";
  2209. echo "<div style='float:left;'>".$lang['fld_enclosed']."</div>";
  2210. echo "<input type='text' value='\"' name='export_csv_fieldsenclosed' style='float:right;'/>";
  2211. echo "<div style='clear:both;'></div>";
  2212. echo "<div style='float:left;'>".$lang['fld_escaped']."</div>";
  2213. echo "<input type='text' value='\' name='export_csv_fieldsescaped' style='float:right;'/>";
  2214. echo "<div style='clear:both;'></div>";
  2215. echo "<div style='float:left;'>".$lang['rep_null']."</div>";
  2216. echo "<input type='text' value='NULL' name='export_csv_replacenull' style='float:right;'/>";
  2217. echo "<div style='clear:both;'></div>";
  2218. echo "<label><input type='checkbox' name='export_csv_crlf'/> ".$lang['rem_crlf']."</label><br/>";
  2219. echo "<label><input type='checkbox' checked='checked' name='export_csv_fieldnames'/> ".$lang['put_fld']."</label>";
  2220. echo "</fieldset>";
  2221. echo "<div style='clear:both;'></div>";
  2222. echo "<br/><br/>";
  2223. echo "<fieldset><legend><b>".$lang['save_as']."</b></legend>";
  2224. $file = pathinfo($db->getPath());
  2225. $name = $file['filename'];
  2226. echo "<input type='text' name='filename' value='".htmlencode($name)."_".htmlencode($target_table)."_".date("Y-m-d").".dump' style='width:400px;'/> <input type='submit' name='export' value='".$lang['export']."' class='btn'/>";
  2227. echo "</fieldset>";
  2228. echo "</form>";
  2229. echo "<div class='confirm' style='margin-top: 2em'>".sprintf($lang['backup_hint'],
  2230. $params->getLink(array('download' => $currentDB['path'], 'token' => $_SESSION[COOKIENAME.'token']), $lang["backup_hint_linktext"], '', $lang['backup']))."</div>";
  2231. break;
  2232. //- Import table (=table_import)
  2233. case "table_import":
  2234. if(isset($_POST['import']))
  2235. {
  2236. echo "<div class='confirm'>";
  2237. if($importSuccess===true)
  2238. echo $lang['import_suc'];
  2239. else
  2240. echo $lang['err'].': '.htmlencode($importSuccess);
  2241. echo "</div><br/>";
  2242. }
  2243. echo $params->getForm(array('action' => 'table_import'), 'post', true);
  2244. echo "<fieldset style='float:left; width:260px; margin-right:20px;'><legend><b>".$lang['import_into']." ".htmlencode($target_table)."</b></legend>";
  2245. echo "<label><input type='radio' name='import_type' checked='checked' value='sql' onclick='toggleImports(\"sql\");'/> ".$lang['sql']."</label>";
  2246. echo "<br/><label><input type='radio' name='import_type' value='csv' onclick='toggleImports(\"csv\");'/> ".$lang['csv']."</label>";
  2247. echo "</fieldset>";
  2248. echo "<fieldset style='float:left; max-width:350px;' id='importoptions_sql'><legend><b>".$lang['options']."</b></legend>";
  2249. echo $lang['no_opt'];
  2250. echo "</fieldset>";
  2251. echo "<fieldset style='float:left; max-width:350px; display:none;' id='importoptions_csv'><legend><b>".$lang['options']."</b></legend>";
  2252. echo "<input type='hidden' value='".htmlencode($target_table)."' name='single_table'/>";
  2253. echo "<div style='float:left;'>".$lang['fld_terminated']."</div>";
  2254. echo "<input type='text' value=';' name='import_csv_fieldsterminated' style='float:right;'/>";
  2255. echo "<div style='clear:both;'>";
  2256. echo "<div style='float:left;'>".$lang['fld_enclosed']."</div>";
  2257. echo "<input type='text' value='\"' name='import_csv_fieldsenclosed' style='float:right;'/>";
  2258. echo "<div style='clear:both;'>";
  2259. echo "<div style='float:left;'>".$lang['fld_escaped']."</div>";
  2260. echo "<input type='text' value='\' name='import_csv_fieldsescaped' style='float:right;'/>";
  2261. echo "<div style='clear:both;'>";
  2262. echo "<div style='float:left;'>".$lang['rep_null']."</div>";
  2263. echo "<input type='text' value='NULL' name='import_csv_replacenull' style='float:right;'/>";
  2264. echo "<div style='clear:both;'>";
  2265. echo "<label><input type='checkbox' checked='checked' name='import_csv_fieldnames'/> ".$lang['fld_names']."</label>";
  2266. echo "</fieldset>";
  2267. echo "<div style='clear:both;'></div>";
  2268. echo "<br/><br/>";
  2269. echo "<fieldset><legend><b>".$lang['import_f']."</b></legend>";
  2270. echo "<em>".$lang['max_file_size'].": ".number_format(fileUploadMaxSize()/1024/1024)." MiB</em> ".helpLink($lang['help11'])."<br />";
  2271. echo "<input type='file' value='".$lang['choose_f']."' name='file' style='background-color:transparent; border-style:none; margin:0; padding:0' onchange='checkFileSize(this)'/>";
  2272. echo "<input type='submit' value='".$lang['import']."' name='import' class='btn'/>";
  2273. echo "</fieldset>";
  2274. break;
  2275. //- Rename table (=table_rename)
  2276. case "table_rename":
  2277. echo $params->getForm(array('action'=>'table_rename', 'confirm'=>'1'));
  2278. printf($lang['rename_tbl'], htmlencode($target_table));
  2279. echo " <input type='text' name='newname' value='".htmlencode($target_table)."' style='width:200px;'/> <input type='submit' value='".$lang['rename']."' name='rename' class='btn'/>";
  2280. echo "</form>";
  2281. break;
  2282. //- Search table (=table_search)
  2283. case "table_search":
  2284. if(!isset($_GET['search']))
  2285. {
  2286. $tableInfo = $db->getTableInfo($target_table);
  2287. echo $params->getForm(array('action'=>'table_search', 'confirm'=>'1'));
  2288. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  2289. echo "<tr>";
  2290. echo "<td class='tdheader'>".$lang['fld']."</td>";
  2291. echo "<td class='tdheader'>".$lang['type']."</td>";
  2292. echo "<td class='tdheader'>".$lang['operator']."</td>";
  2293. echo "<td class='tdheader'>".$lang['val']."</td>";
  2294. echo "</tr>";
  2295. for($i=0; $i<sizeof($tableInfo); $i++)
  2296. {
  2297. $field = $tableInfo[$i][1];
  2298. $type = $tableInfo[$i]['type'];
  2299. $typeAffinity = get_type_affinity($type);
  2300. $tdWithClass = "<td class='td".($i%2 ? "1" : "2")."'>";
  2301. $tdWithClassLeft = "<td class='td".($i%2 ? "1" : "2")."' style='text-align:left;'>";
  2302. if(isset($_GET['oldSearch']) && isset($_SESSION[COOKIENAME.'search'][$_GET['oldSearch']]['values'][$field]))
  2303. $value = implode($_SESSION[COOKIENAME.'search'][$_GET['oldSearch']]['values'][$field], ",");
  2304. else
  2305. $value = '';
  2306. if(isset($_GET['oldSearch']) && isset($_SESSION[COOKIENAME.'search'][$_GET['oldSearch']]['operators'][$field]))
  2307. $operator = $_SESSION[COOKIENAME.'search'][$_GET['oldSearch']]['operators'][$field];
  2308. elseif($typeAffinity=="TEXT" || $typeAffinity=="NONE")
  2309. $operator = 'LIKE';
  2310. else
  2311. $operator = '=';
  2312. echo "<tr>";
  2313. echo $tdWithClassLeft;
  2314. echo htmlencode($field);
  2315. echo "</td>";
  2316. echo $tdWithClassLeft;
  2317. echo htmlencode($type);
  2318. echo "</td>";
  2319. echo $tdWithClassLeft;
  2320. echo "<select name='field_".$i."_operator' onchange='checkLike(\"field_".$i."_value\", this.options[this.selectedIndex].value); '>";
  2321. $operators = array('=', '>', '>=', '<', '<=', "= ''", "!= ''", '!=', 'LIKE', 'LIKE%','NOT LIKE', 'IN', 'NOT IN', 'IS NULL', 'IS NOT NULL');
  2322. $operatorsDisplay = array('LIKE%' => 'LIKE %...%', 'IN'=>'IN (..., ...)', 'NOT IN'=>'NOT IN (..., ...)');
  2323. $operatorsNumbersOnly = array('>', '>=', '<', '<=');
  2324. $operatorsTextOnly = array("= ''", "!= ''");
  2325. foreach($operators as $op)
  2326. {
  2327. if($typeAffinity!="INTEGER" && $typeAffinity!="REAL" && $typeAffinity!="NUMERIC" && in_array($op, $operatorsNumbersOnly))
  2328. continue;
  2329. if($typeAffinity!="TEXT" && $typeAffinity!="NONE" && in_array($op, $operatorsTextOnly))
  2330. continue;
  2331. $display = (isset($operatorsDisplay[$op]) ? $operatorsDisplay[$op] : $op);
  2332. echo "<option value='".htmlencode($op)."'".($operator==$op?" selected='selected'":'').">".htmlencode($display)."</option>";
  2333. }
  2334. echo "</select>";
  2335. echo "</td>";
  2336. echo $tdWithClassLeft;
  2337. if($typeAffinity=="INTEGER" || $typeAffinity=="REAL" || $typeAffinity=="NUMERIC")
  2338. echo "<input type='text' id='field_".$i."_value' name='field_".$i."_value' value='".htmlencode($value)."'/>";
  2339. else
  2340. echo "<textarea id='field_".$i."_value' name='field_".$i."_value' rows='1' cols='60'>".htmlencode($value)."</textarea>";
  2341. echo "</td>";
  2342. echo "</tr>";
  2343. }
  2344. echo "<tr>";
  2345. echo "<td class='tdheader' style='text-align:right;' colspan='4'>";
  2346. echo "<input type='submit' value='".$lang['srch']."' class='btn'/>";
  2347. echo "</td>";
  2348. echo "</tr>";
  2349. echo "</table>";
  2350. echo "</form>";
  2351. break;
  2352. }
  2353. elseif(isset($_SESSION[COOKIENAME.'search'][$_GET['search']]))
  2354. {
  2355. $params->search = $_GET['search'];
  2356. $search = $_SESSION[COOKIENAME.'search'][$_GET['search']];
  2357. // NOTICE: we do not break here!! we just do the same now like row_view-action does
  2358. }
  2359. //- Row actions
  2360. //- View row (=row_view)
  2361. case "row_view":
  2362. if(!isset($_GET['startRow']))
  2363. $_GET['startRow'] = 0;
  2364. if(isset($_SESSION[COOKIENAME.'currentTable']) && $_SESSION[COOKIENAME.'currentTable']!=$target_table)
  2365. {
  2366. unset($_SESSION[COOKIENAME.'sortRows']);
  2367. unset($_SESSION[COOKIENAME.'orderRows']);
  2368. }
  2369. if(isset($_GET['viewtype']))
  2370. {
  2371. $_SESSION[COOKIENAME.'viewtype'] = $_GET['viewtype'];
  2372. }
  2373. //- Query execution
  2374. if(!isset($_GET['sort']))
  2375. $_GET['sort'] = NULL;
  2376. if(!isset($_GET['order']))
  2377. $_GET['order'] = NULL;
  2378. $numRows = $params->numRows;
  2379. $startRow = $_GET['startRow'];
  2380. if(isset($_GET['sort']))
  2381. {
  2382. $_SESSION[COOKIENAME.'sortRows'] = $_GET['sort'];
  2383. $_SESSION[COOKIENAME.'currentTable'] = $target_table;
  2384. }
  2385. if(isset($_GET['order']))
  2386. {
  2387. $_SESSION[COOKIENAME.'orderRows'] = $_GET['order'];
  2388. $_SESSION[COOKIENAME.'currentTable'] = $target_table;
  2389. }
  2390. $query = "SELECT * ";
  2391. // select the primary key column(s) last (ROWID if there is no PK).
  2392. // this will be used to identify rows, e.g. when editing/deleting rows
  2393. $primary_key = $db->getPrimaryKey($target_table);
  2394. foreach($primary_key as $pk)
  2395. {
  2396. $query.= ', '.$db->quote_id($pk);
  2397. $query.= ', typeof('.$db->quote_id($pk).')';
  2398. }
  2399. $query .= " FROM ".$db->quote_id($target_table);
  2400. $queryDisp = "SELECT * FROM ".$db->quote_id($target_table);
  2401. $queryCount = "SELECT COUNT(*) AS count FROM ".$db->quote_id($target_table);
  2402. $queryAdd = "";
  2403. if(isset($search) && isset($search['where']))
  2404. {
  2405. $queryAdd = $search['where'];
  2406. $queryCount .= $search['where'];
  2407. }
  2408. if(isset($_SESSION[COOKIENAME.'sortRows']))
  2409. $queryAdd .= " ORDER BY ".$db->quote_id($_SESSION[COOKIENAME.'sortRows']);
  2410. if(isset($_SESSION[COOKIENAME.'orderRows']))
  2411. $queryAdd .= " ".$_SESSION[COOKIENAME.'orderRows'];
  2412. $queryAdd .= " LIMIT ".$startRow.", ".$numRows;
  2413. $query .= $queryAdd;
  2414. $queryDisp .= $queryAdd;
  2415. $resultRows = $db->select($queryCount);
  2416. $totalRows = $resultRows['count'];
  2417. $shownRows = min($resultRows['count']-$startRow, $numRows);
  2418. //- HTML: pagination buttons
  2419. $lastPage = intval($totalRows / $params->numRows);
  2420. $remainder = intval($totalRows % $params->numRows);
  2421. if($remainder==0)
  2422. $remainder = $params->numRows;
  2423. echo "<div style=''>";
  2424. //previous button
  2425. if($_GET['startRow']>0)
  2426. {
  2427. echo "<div style='float:left;'>";
  2428. echo $params->getForm(array('action'=>$_GET['action']),'get');
  2429. echo "<input type='hidden' name='startRow' value='0'/>";
  2430. echo "<input type='submit' value='&larr;&larr;' class='btn'/> ";
  2431. echo "</form>";
  2432. echo "</div>";
  2433. echo "<div style='float:left; overflow:hidden; margin-right:20px;'>";
  2434. echo $params->getForm(array('action'=>$_GET['action']),'get');
  2435. echo "<input type='hidden' name='startRow' value='".max(0,intval($_GET['startRow']-$params->numRows))."'/>";
  2436. echo "<input type='submit' value='&larr;' class='btn'/> ";
  2437. echo "</form>";
  2438. echo "</div>";
  2439. }
  2440. //show certain number buttons
  2441. echo "<div style='float:left;'>";
  2442. echo $params->getForm(array('action'=>$_GET['action'], 'numRows'=>null),'get');
  2443. echo "<input type='submit' value='".$lang['show']." : ' name='show' class='btn'/> ";
  2444. echo "<input type='text' name='numRows' style='width:50px;' value='".$params->numRows."'/> ";
  2445. echo $lang['rows_records'];
  2446. if(intval($_GET['startRow']+$params->numRows) < $totalRows)
  2447. echo "<input type='text' name='startRow' style='width:90px;' value='".intval($_GET['startRow']+$params->numRows)."'/>";
  2448. else
  2449. echo "<input type='text' name='startRow' style='width:90px;' value='0'/> ";
  2450. echo $lang['as_a'];
  2451. echo " <select name='viewtype'>";
  2452. if(!isset($_SESSION[COOKIENAME.'viewtype']) || $_SESSION[COOKIENAME.'viewtype']=="table")
  2453. {
  2454. echo "<option value='table' selected='selected'>".$lang['tbl']."</option>";
  2455. echo "<option value='chart'>".$lang['chart']."</option>";
  2456. }
  2457. else
  2458. {
  2459. echo "<option value='table'>".$lang['tbl']."</option>";
  2460. echo "<option value='chart' selected='selected'>".$lang['chart']."</option>";
  2461. }
  2462. echo "</select>";
  2463. echo "</form>";
  2464. echo "</div>";
  2465. //next button
  2466. if(intval($_GET['startRow']+$params->numRows)<$totalRows)
  2467. {
  2468. echo "<div style='float:left; margin-left:20px; '>";
  2469. echo $params->getForm(array('action'=>$_GET['action']),'get');
  2470. echo "<input type='hidden' name='startRow' value='".intval($_GET['startRow']+$params->numRows)."'/>";
  2471. echo "<input type='submit' value='&rarr;' class='btn'/> ";
  2472. echo "</form>";
  2473. echo "</div>";
  2474. echo "<div style='float:left; '>";
  2475. echo $params->getForm(array('action'=>$_GET['action']),'get');
  2476. echo "<input type='hidden' name='startRow' value='".intval($totalRows-$remainder)."'/>";
  2477. echo "<input type='submit' value='&rarr;&rarr;' class='btn'/> ";
  2478. echo "</form>";
  2479. echo "</div>";
  2480. }
  2481. echo "<div style='clear:both;'></div>";
  2482. echo "</div>";
  2483. //- Show results
  2484. if($shownRows>0)
  2485. {
  2486. $queryTimer = new MicroTimer();
  2487. $table_result = $db->query($query);
  2488. $queryTimer->stop();
  2489. echo "<br/><div class='confirm'>";
  2490. echo "<b>".$lang['showing_rows']." ".$startRow." - ".($startRow + $shownRows-1).", ".$lang['total'].": ".$totalRows." ";
  2491. printf($lang['query_time'], $queryTimer);
  2492. echo "</b><br/>";
  2493. echo "<span style='font-size:11px;'>".htmlencode($queryDisp)."</span>";
  2494. echo "</div><br/>";
  2495. if($target_table_type == 'view')
  2496. {
  2497. echo sprintf($lang['readonly_tbl'], htmlencode($target_table))." <a href='https://en.wikipedia.org/wiki/View_(SQL)' target='_blank'>https://en.wikipedia.org/wiki/View_(SQL)</a>";
  2498. echo "<br/><br/>";
  2499. }
  2500. $tableInfo = $db->getTableInfo($target_table);
  2501. $pkFirstCol = sizeof($tableInfo)+1;
  2502. //- Table view
  2503. if(!isset($_SESSION[COOKIENAME.'viewtype']) || $_SESSION[COOKIENAME.'viewtype']=="table")
  2504. {
  2505. echo $params->getForm(array('action'=>'row_editordelete'), 'post', false, 'checkForm');
  2506. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  2507. echo "<tr>";
  2508. echo "<td colspan='3' class='tdheader' style='text-align:center'>";
  2509. echo "<a href='".$params->getURL(array('action'=>$_GET['action'], 'fulltexts'=>($params->fulltexts?0:1) ))."' title='".$lang[($params->fulltexts?'no_full_texts':'full_texts')]."'>";
  2510. echo "<b>&".($params->fulltexts?'r':'l')."arr;</b>&nbsp;T&nbsp;<b>&".($params->fulltexts?'l':'r')."arr;</b></a>";
  2511. echo "</td>";
  2512. for($i=0; $i<sizeof($tableInfo); $i++)
  2513. {
  2514. echo "<td class='tdheader'>";
  2515. if(isset($_SESSION[COOKIENAME.'sortRows']))
  2516. $orderTag = ($_SESSION[COOKIENAME.'sortRows']==$tableInfo[$i]['name'] && $_SESSION[COOKIENAME.'orderRows']=="ASC") ? "DESC" : "ASC";
  2517. else
  2518. $orderTag = "ASC";
  2519. echo $params->getLink(array('action'=>$_GET['action'], 'sort'=>$tableInfo[$i]['name'], 'order'=>$orderTag ), htmlencode($tableInfo[$i]['name']));
  2520. if(isset($_SESSION[COOKIENAME.'sortRows']) && $_SESSION[COOKIENAME.'sortRows']==$tableInfo[$i]['name'])
  2521. echo (($_SESSION[COOKIENAME.'orderRows']=="ASC") ? " <b>&uarr;</b>" : " <b>&darr;</b>");
  2522. echo "</td>";
  2523. }
  2524. echo "</tr>";
  2525. for($i=0; $row = $db->fetch($table_result, 'num'); $i++)
  2526. {
  2527. // -g-> $pk will always be the last columns in each row of the array because we are doing "SELECT *, PK_1, typeof(PK_1), PK2, typeof(PK_2), ... FROM ..."
  2528. $pk_arr = array();
  2529. for($col = $pkFirstCol; array_key_exists($col, $row); $col=$col+2)
  2530. {
  2531. // in $col we have the type and in $col-1 the value
  2532. if($row[$col]=='integer' || $row[$col]=='real')
  2533. // json encode as int or float, not string
  2534. $pk_arr[] = $row[$col-1]+0;
  2535. else
  2536. // encode as json string
  2537. $pk_arr[] = $row[$col-1];
  2538. }
  2539. $pk = json_encode($pk_arr);
  2540. $tdWithClass = "<td class='td".($i%2 ? "1" : "2")."'>";
  2541. $tdWithClassLeft = "<td class='td".($i%2 ? "1" : "2")."' style='text-align:left;'>";
  2542. echo "<tr>";
  2543. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  2544. {
  2545. echo $tdWithClass;
  2546. echo "<input type='checkbox' name='check[]' value='".htmlencode($pk)."' id='check_".htmlencode($i)."'/>";
  2547. echo "</td>";
  2548. echo $tdWithClass;
  2549. // -g-> Here, we need to put the PK in as the link for both the edit and delete.
  2550. echo $params->getLink(array('action'=>'row_editordelete', 'pk'=>$pk, 'type'=>'edit'),"<span>".$lang['edit']."</span>",'edit', $lang['edit']);
  2551. echo "</td>";
  2552. echo $tdWithClass;
  2553. echo $params->getLink(array('action'=>'row_editordelete', 'pk'=>$pk, 'type'=>'delete'),"<span>".$lang['del']."</span>",'delete', $lang['del']);
  2554. echo "</td>";
  2555. } else {
  2556. echo "<td class='td".($i%2 ? "1" : "2")."' colspan='3'></td>";
  2557. }
  2558. for($j=0; $j<sizeof($tableInfo); $j++)
  2559. {
  2560. $typeAffinity = get_type_affinity($tableInfo[$j]['type']);
  2561. if($typeAffinity=="INTEGER" || $typeAffinity=="REAL" || $typeAffinity=="NUMERIC")
  2562. echo $tdWithClass;
  2563. else
  2564. echo $tdWithClassLeft;
  2565. if($row[$j]==="")
  2566. echo "&nbsp;";
  2567. elseif($row[$j]===NULL)
  2568. echo "<i class='null'>NULL</i>";
  2569. elseif(preg_match('/^BLOB/i', $tableInfo[$j]['type']))
  2570. {
  2571. echo "<div style='float:left; text-align: left; padding-right:2em'>";
  2572. echo $params->getLink(array('action'=>'row_get_blob', 'confirm'=>1, 'pk'=>$pk, 'column'=>$tableInfo[$j]['name'], 'download_blob'=>1),$lang["download"]).' | ';
  2573. echo $params->getLink(array('action'=>'row_get_blob', 'confirm'=>1, 'pk'=>$pk, 'column'=>$tableInfo[$j]['name'], 'download_blob'=>0),$lang["open_in_browser"],'','','_blank');
  2574. echo "</div><div style='float:right; text-align: right'>";
  2575. echo 'Size: '.number_format(strlen($row[$j])).' Bytes';
  2576. echo "</div>";
  2577. }
  2578. elseif(isset($search))
  2579. echo markSearchWords(subString($row[$j]),$tableInfo[$j]['name'], $search);
  2580. else
  2581. echo htmlencode(subString($row[$j]));
  2582. echo "</td>";
  2583. }
  2584. echo "</tr>";
  2585. }
  2586. echo "</table>";
  2587. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  2588. {
  2589. echo "<a onclick='checkAll()'>".$lang['chk_all']."</a> / <a onclick='uncheckAll()'>".$lang['unchk_all']."</a> <i>".$lang['with_sel'].":</i> ";
  2590. echo "<select name='type'>";
  2591. echo "<option value='edit'>".$lang['edit']."</option>";
  2592. echo "<option value='delete'>".$lang['del']."</option>";
  2593. echo "</select> ";
  2594. echo "<input type='submit' value='".$lang['go']."' name='massGo' class='btn'/>";
  2595. }
  2596. echo "</form>";
  2597. }
  2598. else
  2599. //- Chart view
  2600. {
  2601. if(!isset($_SESSION[COOKIENAME.$target_table.'chartlabels']))
  2602. {
  2603. // No label-column set. Try to pick a text-column as label-column.
  2604. for($i=0; $i<sizeof($tableInfo); $i++)
  2605. {
  2606. if(get_type_affinity($tableInfo[$i]['type'])=='TEXT')
  2607. {
  2608. $_SESSION[COOKIENAME.$target_table.'chartlabels'] = $i;
  2609. break;
  2610. }
  2611. }
  2612. }
  2613. if(!isset($_SESSION[COOKIENAME.$target_table.'chartlabels']))
  2614. // no text column found, use the first column
  2615. $_SESSION[COOKIENAME.$target_table.'chartlabels'] = 0;
  2616. if(!isset($_SESSION[COOKIENAME.$target_table.'chartvalues']))
  2617. {
  2618. // No value-column set. Pick the first numeric column if possible.
  2619. // If not possible, pick the first column that is not the label-column.
  2620. $potential_value_column = null;
  2621. for($i=0; $i<sizeof($tableInfo); $i++)
  2622. {
  2623. if($potential_value_column===null && $i != $_SESSION[COOKIENAME.$target_table.'chartlabels'])
  2624. // the first column (of any type) that is not the label-column
  2625. $potential_value_column = $i;
  2626. // check if the col is numeric
  2627. $typeAffinity = get_type_affinity($tableInfo[$i]['type']);
  2628. if($typeAffinity=='INTEGER' || $typeAffinity=='REAL' || $typeAffinity=='NUMERIC')
  2629. {
  2630. // this is defined as a numeric column, so prefer this as a value column over $potential_value_column
  2631. $_SESSION[COOKIENAME.$target_table.'chartvalues'] = $i;
  2632. break;
  2633. }
  2634. }
  2635. if(!isset($_SESSION[COOKIENAME.$target_table.'chartvalues']))
  2636. {
  2637. // we did not find a numeric column
  2638. if($potential_value_column!==null)
  2639. // use the $potential_value_column, i.e. the second column which is not the label-column
  2640. $_SESSION[COOKIENAME.$target_table.'chartvalues'] = $potential_value_column;
  2641. else
  2642. // it's hopeless, there is only 1 column
  2643. $_SESSION[COOKIENAME.$target_table.'chartvalues'] = 0;
  2644. }
  2645. }
  2646. if(!isset($_SESSION[COOKIENAME.'charttype']))
  2647. $_SESSION[COOKIENAME.'charttype'] = 'bar';
  2648. if(isset($_POST['chartsettings']))
  2649. {
  2650. $_SESSION[COOKIENAME.'charttype'] = $_POST['charttype'];
  2651. $_SESSION[COOKIENAME.$target_table.'chartlabels'] = $_POST['chartlabels'];
  2652. $_SESSION[COOKIENAME.$target_table.'chartvalues'] = $_POST['chartvalues'];
  2653. }
  2654. //- Chart javascript code
  2655. ?>
  2656. <script type='text/javascript' src='https://www.google.com/jsapi'></script>
  2657. <script type='text/javascript'>
  2658. google.load('visualization', '1.0', {'packages':['corechart']});
  2659. google.setOnLoadCallback(drawChart);
  2660. function drawChart()
  2661. {
  2662. var data = new google.visualization.DataTable();
  2663. data.addColumn('string', '<?php echo $tableInfo[$_SESSION[COOKIENAME.$target_table.'chartlabels']]['name']; ?>');
  2664. data.addColumn('number', '<?php echo $tableInfo[$_SESSION[COOKIENAME.$target_table.'chartvalues']]['name']; ?>');
  2665. data.addRows([
  2666. <?php
  2667. for($i=0; $row = $db->fetch($table_result); $i++)
  2668. {
  2669. $label = str_replace("'", "", htmlencode($row[$_SESSION[COOKIENAME.$target_table.'chartlabels']]));
  2670. $value = htmlencode($row[$_SESSION[COOKIENAME.$target_table.'chartvalues']]);
  2671. if($value==NULL || $value=="")
  2672. $value = 0;
  2673. echo "['".$label."', ".$value."]";
  2674. if($i<$totalRows-1)
  2675. echo ",";
  2676. }
  2677. $height = ($totalRows+1) * 30;
  2678. if($height>1000)
  2679. $height = 1000;
  2680. else if($height<300)
  2681. $height = 300;
  2682. if($_SESSION[COOKIENAME.'charttype']=="pie")
  2683. $height = 800;
  2684. ?>
  2685. ]);
  2686. var chartWidth = document.getElementById("main_column").offsetWidth - document.getElementById("chartsettingsbox").offsetWidth - 100;
  2687. if(chartWidth>1000)
  2688. chartWidth = 1000;
  2689. var options =
  2690. {
  2691. 'width':chartWidth,
  2692. 'height':<?php echo $height; ?>,
  2693. 'title':'<?php echo $tableInfo[$_SESSION[COOKIENAME.$target_table.'chartlabels']]['name']." vs ".$tableInfo[$_SESSION[COOKIENAME.$target_table.'chartvalues']]['name']; ?>'
  2694. };
  2695. <?php
  2696. if($_SESSION[COOKIENAME.'charttype']=="bar")
  2697. echo "var chart = new google.visualization.BarChart(document.getElementById('chart_div'));";
  2698. else if($_SESSION[COOKIENAME.'charttype']=="pie")
  2699. echo "var chart = new google.visualization.PieChart(document.getElementById('chart_div'));";
  2700. else
  2701. echo "var chart = new google.visualization.LineChart(document.getElementById('chart_div'));";
  2702. ?>
  2703. chart.draw(data, options);
  2704. }
  2705. </script>
  2706. <div id="chart_div" style="float:left;"><?php echo $lang['no_chart']; ?></div>
  2707. <?php
  2708. echo "<fieldset style='float:right; text-align:center;' id='chartsettingsbox'><legend><b>Chart Settings</b></legend>";
  2709. echo $params->getForm(array('action'=>$_GET['action']));
  2710. echo $lang['chart_type'].": <select name='charttype'>";
  2711. echo "<option value='bar'";
  2712. if($_SESSION[COOKIENAME.'charttype']=="bar")
  2713. echo " selected='selected'";
  2714. echo ">".$lang['chart_bar']."</option>";
  2715. echo "<option value='pie'";
  2716. if($_SESSION[COOKIENAME.'charttype']=="pie")
  2717. echo " selected='selected'";
  2718. echo ">".$lang['chart_pie']."</option>";
  2719. echo "<option value='line'";
  2720. if($_SESSION[COOKIENAME.'charttype']=="line")
  2721. echo " selected='selected'";
  2722. echo ">".$lang['chart_line']."</option>";
  2723. echo "</select>";
  2724. echo "<br/><br/>";
  2725. echo $lang['lbl'].": <select name='chartlabels'>";
  2726. for($i=0; $i<sizeof($tableInfo); $i++)
  2727. {
  2728. if(isset($_SESSION[COOKIENAME.$target_table.'chartlabels']) && $_SESSION[COOKIENAME.$target_table.'chartlabels']==$i)
  2729. echo "<option value='".$i."' selected='selected'>".htmlencode($tableInfo[$i]['name'])."</option>";
  2730. else
  2731. echo "<option value='".$i."'>".htmlencode($tableInfo[$i]['name'])."</option>";
  2732. }
  2733. echo "</select>";
  2734. echo "<br/><br/>";
  2735. echo $lang['val'].": <select name='chartvalues'>";
  2736. for($i=0; $i<sizeof($tableInfo); $i++)
  2737. {
  2738. if(isset($_SESSION[COOKIENAME.$target_table.'chartvalues']) && $_SESSION[COOKIENAME.$target_table.'chartvalues']==$i)
  2739. echo "<option value='".$i."' selected='selected'>".htmlencode($tableInfo[$i]['name'])."</option>";
  2740. else
  2741. echo "<option value='".$i."'>".htmlencode($tableInfo[$i]['name'])."</option>";
  2742. }
  2743. echo "</select>";
  2744. echo "<br/><br/>";
  2745. echo "<input type='submit' name='chartsettings' value='".$lang['update']."' class='btn'/>";
  2746. echo "</form>";
  2747. echo "</fieldset>";
  2748. echo "<div style='clear:both;'></div>";
  2749. //end chart view
  2750. }
  2751. }
  2752. else //no rows - do nothing
  2753. {
  2754. echo "<br/><div class='confirm'>";
  2755. if(isset($search) || $totalRows>0)
  2756. echo $lang['no_rows']."<br/><br/>";
  2757. elseif($target_table_type == 'table')
  2758. echo $lang['empty_tbl']." ".$params->getLink(array('action'=>'row_create'), $lang['click']) ." ".$lang['insert_rows'].'<br/><br/>';
  2759. echo "<span style='font-size:11px;'>".htmlencode($queryDisp)."</span>";
  2760. echo "</div><br/>";
  2761. }
  2762. if(isset($search))
  2763. echo "<br/><br/>".$params->getLink(array('action'=>'table_search','search'=>null,'oldSearch' => (isset($_GET['search'])?$_GET['search']:null)), $lang['srch_again']);
  2764. break;
  2765. //- Create new row (=row_create)
  2766. case "row_create":
  2767. echo $params->getForm(array('action'=>'row_create'), 'get');
  2768. echo $lang['restart_insert'];
  2769. echo " <select name='newRows'>";
  2770. for($i=1; $i<=40; $i++)
  2771. {
  2772. if(isset($_GET['newRows']) && $_GET['newRows']==$i)
  2773. echo "<option value='".$i."' selected='selected'>".$i."</option>";
  2774. else
  2775. echo "<option value='".$i."'>".$i."</option>";
  2776. }
  2777. echo "</select> ";
  2778. echo $lang['rows'];
  2779. echo " <input type='submit' value='".$lang['go']."' class='btn'/>";
  2780. echo "</form>";
  2781. echo "<br/>";
  2782. echo $params->getForm(array('action'=>'row_create','confirm'=>'1'), 'post', true);
  2783. $tableInfo = $db->getTableInfo($target_table);
  2784. if(isset($_GET['newRows']))
  2785. $num = $_GET['newRows'];
  2786. else
  2787. $num = 1;
  2788. echo "<input type='hidden' name='newRows' value='".$num."'/>";
  2789. for($j=0; $j<$num; $j++)
  2790. {
  2791. if($j>0)
  2792. echo "<label><input type='checkbox' value='ignore' name='".$j.":ignore' id='row_".$j."_ignore' checked='checked'/> ".$lang['ignore']."</label><br/>";
  2793. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  2794. echo "<tr>";
  2795. echo "<td class='tdheader'>".$lang['fld']."</td>";
  2796. echo "<td class='tdheader'>".$lang['type']."</td>";
  2797. echo "<td class='tdheader'>".$lang['func']."</td>";
  2798. echo "<td class='tdheader'>Null</td>";
  2799. echo "<td class='tdheader'>".$lang['val']."</td>";
  2800. echo "</tr>";
  2801. for($i=0; $i<sizeof($tableInfo); $i++)
  2802. {
  2803. $field = $tableInfo[$i]['name'];
  2804. $type = strtoupper($tableInfo[$i]['type']);
  2805. $typeAffinity = get_type_affinity($type);
  2806. if($tableInfo[$i]['dflt_value'] === "NULL")
  2807. $value = NULL;
  2808. else
  2809. $value = htmlencode(trim(trim($tableInfo[$i]['dflt_value']), "'"));
  2810. $tdWithClassLeft = "<td class='td".($i%2 ? "1" : "2")."' style='text-align:left;'>";
  2811. echo "<tr>";
  2812. echo $tdWithClassLeft;
  2813. echo htmlencode($field);
  2814. echo "</td>";
  2815. echo $tdWithClassLeft;
  2816. echo htmlencode($type);
  2817. echo "</td>";
  2818. echo $tdWithClassLeft;
  2819. echo "<select name='function_".$i."[]' onchange='notNull(\"row_".$j."_field_".$i."_null\");'>";
  2820. echo "<option value=''>&nbsp;</option>";
  2821. foreach (array_merge($sqlite_functions, $custom_functions) as $f) {
  2822. echo "<option value='".htmlencode($f)."'>".htmlencode($f)."</option>";
  2823. }
  2824. echo "</select>";
  2825. echo "</td>";
  2826. echo $tdWithClassLeft;
  2827. if($tableInfo[$i]['notnull']==0)
  2828. {
  2829. if($value===NULL)
  2830. echo "<input type='checkbox' name='".$i."_null[]' id='row_".$j."_field_".$i."_null' checked='checked' onclick='disableText(this, \"row_".$j."_field_".$i."_value\");'/>";
  2831. else
  2832. echo "<input type='checkbox' name='".$i."_null[]' id='row_".$j."_field_".$i."_null' onclick='disableText(this, \"row_".$j."_field_".$i."_value\");'/>";
  2833. }
  2834. echo "</td>";
  2835. echo $tdWithClassLeft;
  2836. if($typeAffinity=="INTEGER" || $typeAffinity=="REAL" || $typeAffinity=="NUMERIC")
  2837. echo "<input type='text' id='row_".$j."_field_".$i."_value' name='".$j.":".$i."' value='".$value."' onblur='changeIgnore(this, \"row_".$j."_ignore\");' onclick='notNull(\"row_".$j."_field_".$i."_null\");'/>";
  2838. elseif(preg_match('/^BLOB/', $type))
  2839. echo "<input type='file' id='row_".$j."_field_".$i."_value' name='".$j.":".$i."' onblur='changeIgnore(this, \"row_".$j."_ignore\");' onclick='notNull(\"row_".$j."_field_".$i."_null\");'/>";
  2840. else
  2841. echo "<textarea id='row_".$j."_field_".$i."_value' name='".$j.":".$i."' rows='5' cols='60' onclick='notNull(\"row_".$j."_field_".$i."_null\");' onblur='changeIgnore(this, \"row_".$j."_ignore\");'>".$value."</textarea>";
  2842. echo "</td>";
  2843. echo "</tr>";
  2844. }
  2845. echo "<tr>";
  2846. echo "<td class='tdheader' style='text-align:right;' colspan='5'>";
  2847. echo "<input type='submit' value='".$lang['insert']."' class='btn'/>";
  2848. echo "</td>";
  2849. echo "</tr>";
  2850. echo "</table><br/>";
  2851. }
  2852. echo "</form>";
  2853. break;
  2854. //- Edit or delete row (=row_editordelete)
  2855. case "row_editordelete":
  2856. if(isset($_POST['check']))
  2857. $pks = $_POST['check'];
  2858. else if(isset($_GET['pk']))
  2859. $pks = array($_GET['pk']);
  2860. else $pks[0] = "";
  2861. $str = implode(', ', $pks);
  2862. if($str=="") //nothing was selected so show an error
  2863. {
  2864. echo "<div class='confirm'>";
  2865. echo $lang['err'].": ".$lang['no_sel'];
  2866. echo "</div>";
  2867. echo "<br/><br/>".$params->getLink(array('action'=>'row_view'),$lang['return']);
  2868. }
  2869. else
  2870. {
  2871. if((isset($_POST['type']) && $_POST['type']=="edit") || (isset($_GET['type']) && $_GET['type']=="edit")) //edit
  2872. {
  2873. echo $params->getForm(array('action'=>'row_edit', 'confirm'=>'1', 'pk'=>json_encode($pks)),'post',true);
  2874. $tableInfo = $db->getTableInfo($target_table);
  2875. $primary_key = $db->getPrimaryKey($target_table);
  2876. for($j=0; $j<sizeof($pks); $j++)
  2877. {
  2878. $query = "SELECT * FROM ".$db->quote_id($target_table)." WHERE " . $db->wherePK($target_table, json_decode($pks[$j]));
  2879. $result1 = $db->select($query, 'num');
  2880. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  2881. echo "<tr>";
  2882. echo "<td class='tdheader'>".$lang['fld']."</td>";
  2883. echo "<td class='tdheader'>".$lang['type']."</td>";
  2884. echo "<td class='tdheader'>".$lang['func']."</td>";
  2885. echo "<td class='tdheader'>Null</td>";
  2886. echo "<td class='tdheader'>".$lang['val']."</td>";
  2887. echo "</tr>";
  2888. for($i=0; $i<sizeof($tableInfo); $i++)
  2889. {
  2890. $field = $tableInfo[$i]['name'];
  2891. $type = strtoupper($tableInfo[$i]['type']);
  2892. $typeAffinity = get_type_affinity($type);
  2893. $value = $result1[$i];
  2894. $tdWithClassLeft = "<td class='td".($i%2 ? "1" : "2")."' style='text-align:left;'>";
  2895. echo "<tr>";
  2896. echo $tdWithClassLeft;
  2897. echo htmlencode($field);
  2898. echo "</td>";
  2899. echo $tdWithClassLeft;
  2900. echo htmlencode($type);
  2901. echo "</td>";
  2902. echo $tdWithClassLeft;
  2903. echo "<select name='function_".$i."[]' onchange='notNull(\"row_".$j."_field_".$i."_null\");'>";
  2904. echo "<option value=''></option>";
  2905. foreach (array_merge($sqlite_functions, $custom_functions) as $f) {
  2906. echo "<option value='".htmlencode($f)."'>".htmlencode($f)."</option>";
  2907. }
  2908. echo "</select>";
  2909. echo "</td>";
  2910. echo $tdWithClassLeft;
  2911. if($tableInfo[$i]['notnull']==0)
  2912. {
  2913. if($value===NULL)
  2914. echo "<input type='checkbox' name='".$i."_null[]' id='row_".$j."_field_".$i."_null' checked='checked' onclick='disableText(this, \"row_".$j."_field_".$i."_value\");'/>";
  2915. else
  2916. echo "<input type='checkbox' name='".$i."_null[]' id='row_".$j."_field_".$i."_null' onclick='disableText(this, \"row_".$j."_field_".$i."_value\");'/>";
  2917. }
  2918. echo "</td>";
  2919. echo $tdWithClassLeft;
  2920. if($typeAffinity=="INTEGER" || $typeAffinity=="REAL" || $typeAffinity=="NUMERIC")
  2921. echo "<input type='text' id='row_".$j."_field_".$i."_value' name='".$i."[]' value='".htmlencode($value)."' onblur='changeIgnore(this, \"".$j."\", \"row_".$j."_field_".$i."_null\")' />";
  2922. elseif(preg_match('/^BLOB/', $type))
  2923. {
  2924. if($value!==NULL)
  2925. {
  2926. echo "<input type='radio' name='row_".$j."_field_".$i."_blob_use' value='old' checked='checked'>";
  2927. echo $params->getLink(array('action'=>'row_get_blob', 'confirm'=>1, 'pk'=>$pks[$j], 'column'=>$field, 'download_blob'=>1),$lang["download"]).' | ';
  2928. echo $params->getLink(array('action'=>'row_get_blob', 'confirm'=>1, 'pk'=>$pks[$j], 'column'=>$field, 'download_blob'=>0),$lang["open_in_browser"],'','','_blank').'<br/>';
  2929. echo "<input type='radio' name='row_".$j."_field_".$i."_blob_use' value='new' id='row_".$j."_field_".$i."_blob_new'>";
  2930. }
  2931. echo "<input type='file' id='row_".$j."_field_".$i."_value' name='".$j.":".$i."'
  2932. onblur='changeIgnore(this, \"row_".$j."_ignore\");'
  2933. onchange='document.getElementById(\"row_".$j."_field_".$i."_blob_new\").checked=true;'
  2934. onclick='notNull(\"row_".$j."_field_".$i."_null\");'
  2935. ".($value===NULL?" disabled='disabled'":"")."/>";
  2936. }
  2937. else
  2938. echo "<textarea id='row_".$j."_field_".$i."_value' name='".$i."[]' rows='1' cols='60' class='".htmlencode($field)."_textarea' onblur='changeIgnore(this, \"".$j."\", \"row_".$j."_field_".$i."_null\")'>".htmlencode($value)."</textarea>";
  2939. echo "</td>";
  2940. echo "</tr>";
  2941. }
  2942. echo "<tr>";
  2943. echo "<td class='tdheader' style='text-align:right;' colspan='5'>";
  2944. // Note: the 'Save changes' button must be first in the code so it is the one used when submitting the form with the Enter key (issue #215)
  2945. echo "<input type='submit' value='".$lang['save_ch']."' class='btn'/> ";
  2946. echo "<input type='submit' name='new_row' value='".$lang['new_insert']."' class='btn'/> ";
  2947. echo $params->getLink(array('action'=>'row_view'), $lang['cancel']);
  2948. echo "</td>";
  2949. echo "</tr>";
  2950. echo "</table>";
  2951. echo "<br/>";
  2952. }
  2953. echo "</form>";
  2954. }
  2955. else //delete
  2956. {
  2957. echo $params->getForm(array('action'=>'row_delete', 'confirm'=>'1', 'pk'=>json_encode($pks)));
  2958. echo "<div class='confirm'>";
  2959. printf($lang['ques_del_rows'], htmlencode($str), htmlencode($target_table));
  2960. echo "<br/><br/>";
  2961. echo "<input type='submit' value='".$lang['confirm']."' class='btn'/> ";
  2962. echo $params->getLink(array('action'=>'row_view'), $lang['cancel']);
  2963. echo "</div>";
  2964. }
  2965. }
  2966. break;
  2967. //- Column actions
  2968. //- View table structure (=column_view)
  2969. case "column_view":
  2970. $tableInfo = $db->getTableInfo($target_table);
  2971. echo $params->getForm(array('action'=>'column_confirm'), 'get', false, 'checkForm');
  2972. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  2973. echo "<tr>";
  2974. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  2975. echo "<td colspan='3'></td>";
  2976. echo "<td class='tdheader'>".$lang['col']." #</td>";
  2977. echo "<td class='tdheader'>".$lang['fld']."</td>";
  2978. echo "<td class='tdheader'>".$lang['type']."</td>";
  2979. echo "<td class='tdheader'>".$lang['not_null']."</td>";
  2980. echo "<td class='tdheader'>".$lang['def_val']."</td>";
  2981. echo "<td class='tdheader'>".$lang['prim_key']."</td>";
  2982. echo "</tr>";
  2983. $noPrimaryKey = true;
  2984. for($i=0; $i<sizeof($tableInfo); $i++)
  2985. {
  2986. $colVal = $tableInfo[$i][0];
  2987. $fieldVal = $tableInfo[$i][1];
  2988. $typeVal = $tableInfo[$i]['type'];
  2989. $notnullVal = $tableInfo[$i][3];
  2990. $defaultVal = $tableInfo[$i][4];
  2991. $primarykeyVal = $tableInfo[$i][5];
  2992. if(intval($notnullVal)!=0)
  2993. $notnullVal = $lang['yes'];
  2994. else
  2995. $notnullVal = $lang['no'];
  2996. if(intval($primarykeyVal)!=0)
  2997. {
  2998. $primarykeyVal = $lang['yes'];
  2999. $noPrimaryKey = false;
  3000. }
  3001. else
  3002. $primarykeyVal = $lang['no'];
  3003. $tdWithClass = "<td class='td".($i%2 ? "1" : "2")."'>";
  3004. $tdWithClassLeft = "<td class='td".($i%2 ? "1" : "2")."' style='text-align:left;'>";
  3005. echo "<tr>";
  3006. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  3007. {
  3008. echo $tdWithClass;
  3009. echo "<input type='checkbox' name='check[]' value='".htmlencode($fieldVal)."' id='check_".$i."'/>";
  3010. echo "</td>";
  3011. echo $tdWithClass;
  3012. echo $params->getLink(array('action'=>'column_edit', 'pk'=>$fieldVal),"<span>".$lang['edit']."</span>",'edit', $lang['edit']);
  3013. echo "</td>";
  3014. echo $tdWithClass;
  3015. echo $params->getLink(array('action'=>'column_confirm', 'action2'=>'column_delete', 'pk'=>$fieldVal),"<span>".$lang['del']."</span>",'delete', $lang['del']);
  3016. echo "</td>";
  3017. }
  3018. echo $tdWithClass;
  3019. echo htmlencode($colVal);
  3020. echo "</td>";
  3021. echo $tdWithClassLeft;
  3022. echo htmlencode($fieldVal);
  3023. echo "</td>";
  3024. echo $tdWithClassLeft;
  3025. echo htmlencode($typeVal);
  3026. echo "</td>";
  3027. echo $tdWithClassLeft;
  3028. echo htmlencode($notnullVal);
  3029. echo "</td>";
  3030. echo $tdWithClassLeft;
  3031. if($defaultVal===NULL)
  3032. echo "<i class='null'>".$lang['none']."</i>";
  3033. elseif($defaultVal==="NULL")
  3034. echo "<i class='null'>NULL</i>";
  3035. else
  3036. echo htmlencode($defaultVal);
  3037. echo "</td>";
  3038. echo $tdWithClassLeft;
  3039. echo htmlencode($primarykeyVal);
  3040. echo "</td>";
  3041. echo "</tr>";
  3042. }
  3043. echo "</table>";
  3044. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  3045. {
  3046. echo "<a onclick='checkAll()'>".$lang['chk_all']."</a> / <a onclick='uncheckAll()'>".$lang['unchk_all']."</a> <i>".$lang['with_sel'].":</i> ";
  3047. echo "<select name='action2'>";
  3048. //echo "<option value='edit'>".$lang['edit']."</option>";
  3049. echo "<option value='column_delete'>".$lang['del']."</option>";
  3050. if($noPrimaryKey)
  3051. echo "<option value='primarykey_add'>".$lang['prim_key']."</option>";
  3052. echo "</select> ";
  3053. echo "<input type='submit' value='".$lang['go']."' name='massGo' class='btn'/>";
  3054. }
  3055. echo "</form>";
  3056. if($target_table_type == 'table' && $db->isWritable() && $db->isDirWritable())
  3057. {
  3058. echo "<br/>";
  3059. echo $params->getForm(array('action'=>'column_create'), 'get');
  3060. echo $lang['add']." <input type='text' name='tablefields' style='width:30px;' value='1'/> ".$lang['tbl_end']." <input type='submit' value='".$lang['go']."' name='addfields' class='btn'/>";
  3061. echo "</form>";
  3062. }
  3063. $query = "SELECT sql FROM sqlite_master WHERE name=".$db->quote($target_table);
  3064. $master = $db->selectArray($query);
  3065. echo "<br/>";
  3066. echo "<br/>";
  3067. echo "<div class='confirm'>";
  3068. echo "<b>".$lang['query_used_'.$target_table_type]."</b><br/>";
  3069. echo "<span style='font-size:11px;'>".htmlencode($master[0]['sql'])."</span>";
  3070. echo "</div>";
  3071. echo "<br/>";
  3072. if($target_table_type != 'view')
  3073. {
  3074. echo "<br/><hr/><br/>";
  3075. $query = "PRAGMA index_list(".$db->quote_id($target_table).")";
  3076. $result = $db->selectArray($query);
  3077. if(sizeof($result)>0)
  3078. {
  3079. echo "<h2>".$lang['indexes'].":</h2>";
  3080. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  3081. echo "<tr>";
  3082. echo "<td colspan='1'>";
  3083. echo "</td>";
  3084. echo "<td class='tdheader'>".$lang['name']."</td>";
  3085. echo "<td class='tdheader'>".$lang['unique']."</td>";
  3086. echo "<td class='tdheader'>".$lang['seq_no']."</td>";
  3087. echo "<td class='tdheader'>".$lang['col']." #</td>";
  3088. echo "<td class='tdheader'>".$lang['fld']."</td>";
  3089. echo "</tr>";
  3090. for($i=0; $i<sizeof($result); $i++)
  3091. {
  3092. if($result[$i]['unique']==0)
  3093. $unique = $lang['no'];
  3094. else
  3095. $unique = $lang['yes'];
  3096. $query = "PRAGMA index_info(".$db->quote_id($result[$i]['name']).")";
  3097. $info = $db->selectArray($query);
  3098. $span = sizeof($info);
  3099. $tdWithClass = "<td class='td".($i%2 ? "1" : "2")."'>";
  3100. $tdWithClassLeft = "<td class='td".($i%2 ? "1" : "2")."' style='text-align:left;'>";
  3101. $tdWithClassSpan = "<td class='td".($i%2 ? "1" : "2")."' rowspan='".$span."'>";
  3102. $tdWithClassLeftSpan = "<td class='td".($i%2 ? "1" : "2")."' style='text-align:left;' rowspan='".$span."'>";
  3103. echo "<tr>";
  3104. echo $tdWithClassSpan;
  3105. echo $params->getLink(array('action'=>'index_delete', 'pk'=>$result[$i]['name']), "<span>".$lang['del']."</span>", 'delete', $lang['del']);
  3106. echo "</td>";
  3107. echo $tdWithClassLeftSpan;
  3108. echo $result[$i]['name'];
  3109. echo "</td>";
  3110. echo $tdWithClassLeftSpan;
  3111. echo $unique;
  3112. echo "</td>";
  3113. for($j=0; $j<$span; $j++)
  3114. {
  3115. if($j!=0)
  3116. echo "<tr>";
  3117. echo $tdWithClassLeft;
  3118. echo htmlencode($info[$j]['seqno']);
  3119. echo "</td>";
  3120. echo $tdWithClassLeft;
  3121. echo htmlencode($info[$j]['cid']);
  3122. echo "</td>";
  3123. echo $tdWithClassLeft;
  3124. echo htmlencode($info[$j]['name']);
  3125. echo "</td>";
  3126. echo "</tr>";
  3127. }
  3128. }
  3129. echo "</table><br/><br/>";
  3130. }
  3131. $query = "SELECT * FROM sqlite_master WHERE type='trigger' AND tbl_name=".$db->quote($target_table)." ORDER BY name";
  3132. $result = $db->selectArray($query);
  3133. //print_r($result);
  3134. if(sizeof($result)>0)
  3135. {
  3136. echo "<h2>".$lang['triggers'].":</h2>";
  3137. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  3138. echo "<tr>";
  3139. echo "<td colspan='1'>";
  3140. echo "</td>";
  3141. echo "<td class='tdheader'>".$lang['name']."</td>";
  3142. echo "<td class='tdheader'>".$lang['sql']."</td>";
  3143. echo "</tr>";
  3144. for($i=0; $i<sizeof($result); $i++)
  3145. {
  3146. $tdWithClass = "<td class='td".($i%2 ? "1" : "2")."'>";
  3147. echo "<tr>";
  3148. echo $tdWithClass;
  3149. echo $params->getLink(array('action'=>'trigger_delete', 'pk'=>$result[$i]['name']), "<span>".$lang['del']."</span>", 'delete', $lang['del']);
  3150. echo "</td>";
  3151. echo $tdWithClass;
  3152. echo htmlencode($result[$i]['name']);
  3153. echo "</td>";
  3154. echo $tdWithClass;
  3155. echo htmlencode($result[$i]['sql']);
  3156. echo "</td>";
  3157. }
  3158. echo "</table><br/><br/>";
  3159. }
  3160. if($db->isWritable() && $db->isDirWritable())
  3161. {
  3162. echo $params->getForm(array('action'=>'index_create'),'get');
  3163. echo "<br/><div class='tdheader'>";
  3164. echo $lang['create_index2']." <input type='text' name='numcolumns' style='width:30px;' value='1'/> ".$lang['cols']." <input type='submit' value='".$lang['go']."' name='addindex' class='btn'/>";
  3165. echo "</div>";
  3166. echo "</form>";
  3167. echo $params->getForm(array('action'=>'trigger_create'),'get');
  3168. echo "<br/><div class='tdheader'>";
  3169. echo $lang['create_trigger2']." <input type='submit' value='".$lang['go']."' name='addindex' class='btn'/>";
  3170. echo "</div>";
  3171. echo "</form>";
  3172. }
  3173. }
  3174. break;
  3175. //- Create column (=column_create)
  3176. case "column_create":
  3177. echo "<h2>".sprintf($lang['new_fld'],htmlencode($_GET['table']))."</h2>";
  3178. if($_GET['tablefields']=="" || intval($_GET['tablefields'])<=0)
  3179. echo $lang['specify_fields'];
  3180. else if($_GET['table']=="")
  3181. echo $lang['specify_tbl'];
  3182. else
  3183. {
  3184. $num = intval($_GET['tablefields']);
  3185. $name = $_GET['table'];
  3186. echo $params->getForm(array('action'=>'column_create', 'confirm'=>'1'));
  3187. echo "<input type='hidden' name='rows' value='".$num."'/>";
  3188. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  3189. echo "<tr>";
  3190. $headings = array($lang["fld"], $lang["type"], $lang["prim_key"]);
  3191. if($db->getType() != "SQLiteDatabase") $headings[] = $lang["autoincrement"];
  3192. $headings[] = $lang["not_null"];
  3193. $headings[] = $lang["def_val"];
  3194. for($k=0; $k<count($headings); $k++)
  3195. echo "<td class='tdheader'>" . $headings[$k] . "</td>";
  3196. echo "</tr>";
  3197. for($i=0; $i<$num; $i++)
  3198. {
  3199. $tdWithClass = "<td class='td" . ($i%2 ? "1" : "2") . "'>";
  3200. echo "<tr>";
  3201. echo $tdWithClass;
  3202. echo "<input type='text' name='".$i."_field' style='width:200px;'/>";
  3203. echo "</td>";
  3204. echo $tdWithClass;
  3205. echo "<select name='".$i."_type' id='i".$i."_type' onchange='toggleAutoincrement(".$i.");'>";
  3206. foreach ($sqlite_datatypes as $t) {
  3207. echo "<option value='".htmlencode($t)."'>".htmlencode($t)."</option>";
  3208. }
  3209. echo "</select>";
  3210. echo "</td>";
  3211. echo $tdWithClass;
  3212. echo "<label><input type='checkbox' name='".$i."_primarykey'/> ".$lang['yes']."</label>";
  3213. echo "</td>";
  3214. if($db->getType() != "SQLiteDatabase")
  3215. {
  3216. echo $tdWithClass;
  3217. echo "<label><input type='checkbox' name='".$i."_autoincrement' id='i".$i."_autoincrement'/> ".$lang['yes']."</label>";
  3218. echo "</td>";
  3219. }
  3220. echo $tdWithClass;
  3221. echo "<label><input type='checkbox' name='".$i."_notnull'/> ".$lang['yes']."</label>";
  3222. echo "</td>";
  3223. echo $tdWithClass;
  3224. echo "<select name='".$i."_defaultoption' id='i".$i."_defaultoption' onchange=\"if(this.value!='defined' && this.value!='expr') document.getElementById('i".$i."_defaultvalue').value='';\">";
  3225. echo "<option value='none'>".$lang['none']."</option><option value='defined'>".$lang['as_defined'].":</option><option>NULL</option><option>CURRENT_TIME</option><option>CURRENT_DATE</option><option>CURRENT_TIMESTAMP</option><option value='expr'>".$lang['expression'].":</option>";
  3226. echo "</select>";
  3227. echo "<input type='text' name='".$i."_defaultvalue' id='i".$i."_defaultvalue' style='width:100px;' onchange=\"if(document.getElementById('i".$i."_defaultoption').value!='expr') document.getElementById('i".$i."_defaultoption').value='defined';\"/>";
  3228. echo "</td>";
  3229. echo "</tr>";
  3230. }
  3231. echo "<tr>";
  3232. echo "<td class='tdheader' style='text-align:right;' colspan='6'>";
  3233. echo "<input type='submit' value='".$lang['add_flds']."' class='btn'/> ";
  3234. echo $params->getLink(array('action'=>'column_view'), $lang['cancel']);
  3235. echo "</td>";
  3236. echo "</tr>";
  3237. echo "</table>";
  3238. echo "</form>";
  3239. }
  3240. break;
  3241. //- Delete column (=column_confirm)
  3242. case "column_confirm":
  3243. if(isset($_GET['check']))
  3244. $pks = $_GET['check'];
  3245. elseif(isset($_GET['pk']))
  3246. $pks = array($_GET['pk']);
  3247. else $pks = array();
  3248. if(sizeof($pks)==0) //nothing was selected so show an error
  3249. {
  3250. echo "<div class='confirm'>";
  3251. echo $lang['err'].": ".$lang['no_sel'];
  3252. echo "</div>";
  3253. echo "<br/><br/>";
  3254. echo $params->getLink(array('action'=>'column_view'), $lang['return']);
  3255. }
  3256. else
  3257. {
  3258. $str = $pks[0];
  3259. $pkVal = $pks[0];
  3260. for($i=1; $i<sizeof($pks); $i++)
  3261. {
  3262. $str .= ", ".$pks[$i];
  3263. $pkVal .= ":".$pks[$i];
  3264. }
  3265. echo $params->getForm(array('action'=>$_GET['action2'], 'confirm'=>'1', 'pk'=>$pkVal));
  3266. echo "<div class='confirm'>";
  3267. printf($lang['ques_'.$_GET['action2']], htmlencode($str), htmlencode($target_table));
  3268. echo "<br/><br/>";
  3269. echo "<input type='submit' value='".$lang['confirm']."' class='btn'/> ";
  3270. echo $params->getLink(array('action'=>'column_view'), $lang['cancel']);
  3271. echo "</div>";
  3272. }
  3273. break;
  3274. //- Edit column (=column_edit)
  3275. case "column_edit":
  3276. echo "<h2>".sprintf($lang['edit_col'], htmlencode($_GET['pk']))." ".$lang['on_tbl']." '".htmlencode($target_table)."'</h2>";
  3277. echo $lang['sqlite_limit']."<br/><br/>";
  3278. if(!isset($_GET['pk']))
  3279. echo $lang['specify_col'];
  3280. else if (!$target_table)
  3281. echo $lang['specify_tbl'];
  3282. else
  3283. {
  3284. $tableInfo = $db->getTableInfo($target_table);
  3285. for($i=0; $i<sizeof($tableInfo); $i++)
  3286. {
  3287. if($tableInfo[$i][1]==$_GET['pk'])
  3288. {
  3289. $colVal = $tableInfo[$i][0];
  3290. $fieldVal = $tableInfo[$i][1];
  3291. $typeVal = $tableInfo[$i]['type'];
  3292. $notnullVal = $tableInfo[$i][3];
  3293. $defaultVal = $tableInfo[$i][4];
  3294. $primarykeyVal = $tableInfo[$i][5];
  3295. break;
  3296. }
  3297. }
  3298. if(!isset($fieldVal))
  3299. {
  3300. echo "<div class='confirm'>".$lang['err'].": ".sprintf($lang['col_inexistent'], htmlencode($_GET['pk']))."</div>";
  3301. }
  3302. else
  3303. {
  3304. $name = $target_table;
  3305. echo $params->getForm(array('action'=>'column_edit', 'confirm'=>'1'));
  3306. echo "<input type='hidden' name='oldvalue' value='".htmlencode($_GET['pk'])."'/>";
  3307. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  3308. echo "<tr>";
  3309. //$headings = array("Field", "Type", "Primary Key", "Autoincrement", "Not NULL", "Default Value");
  3310. $headings = array($lang["fld"], $lang["type"]);
  3311. for($k=0; $k<count($headings); $k++)
  3312. echo "<td class='tdheader'>".$headings[$k]."</td>";
  3313. echo "</tr>";
  3314. $i = 0;
  3315. $tdWithClass = "<td class='td" . ($i%2 ? "1" : "2") . "'>";
  3316. echo "<tr>";
  3317. echo $tdWithClass;
  3318. echo "<input type='text' name='".$i."_field' style='width:200px;' value='".htmlencode($fieldVal)."'/>";
  3319. echo "</td>";
  3320. echo $tdWithClass;
  3321. echo "<select name='".$i."_type' id='i".$i."_type' onchange='toggleAutoincrement(".$i.");'>";
  3322. if(!in_array($typeVal, $sqlite_datatypes))
  3323. echo "<option value='".htmlencode($typeVal)."' selected='selected'>".htmlencode($typeVal)."</option>";
  3324. foreach ($sqlite_datatypes as $t) {
  3325. if($t==$typeVal)
  3326. echo "<option value='".htmlencode($t)."' selected='selected'>".htmlencode($t)."</option>";
  3327. else
  3328. echo "<option value='".htmlencode($t)."'>".htmlencode($t)."</option>";
  3329. }
  3330. echo "</select>";
  3331. echo "</td>";
  3332. /*
  3333. echo $tdWithClass;
  3334. if($primarykeyVal)
  3335. echo "<input type='checkbox' name='".$i."_primarykey' checked='checked'/> Yes";
  3336. else
  3337. echo "<input type='checkbox' name='".$i."_primarykey'/> Yes";
  3338. echo "</td>";
  3339. echo $tdWithClass;
  3340. if(1==2)
  3341. echo "<input type='checkbox' name='".$i."_autoincrement' id='".$i."_autoincrement' checked='checked'/> Yes";
  3342. else
  3343. echo "<input type='checkbox' name='".$i."_autoincrement' id='".$i."_autoincrement'/> Yes";
  3344. echo "</td>";
  3345. echo $tdWithClass;
  3346. if($notnullVal)
  3347. echo "<input type='checkbox' name='".$i."_notnull' checked='checked'/> Yes";
  3348. else
  3349. echo "<input type='checkbox' name='".$i."_notnull'/> Yes";
  3350. echo "</td>";
  3351. echo $tdWithClass;
  3352. echo "<input type='text' name='".$i."_defaultvalue' value='".$defaultVal."' style='width:100px;'/>";
  3353. echo "</td>";
  3354. */
  3355. echo "</tr>";
  3356. echo "<tr>";
  3357. echo "<td class='tdheader' style='text-align:right;' colspan='6'>";
  3358. echo "<input type='submit' value='".$lang['save_ch']."' class='btn'/> ";
  3359. echo $params->getLink(array('action'=>'column_view'), $lang['cancel']);
  3360. echo "</td>";
  3361. echo "</tr>";
  3362. echo "</table>";
  3363. echo "</form>";
  3364. }
  3365. }
  3366. break;
  3367. //- Delete index (=index_delete)
  3368. case "index_delete":
  3369. echo $params->getForm(array('action'=>'index_delete', 'pk'=>$_GET['pk'], 'confirm'=>'1'));
  3370. echo "<div class='confirm'>";
  3371. echo sprintf($lang['ques_del_index'], htmlencode($_GET['pk']))."<br/><br/>";
  3372. echo "<input type='submit' value='".$lang['confirm']."' class='btn'/> ";
  3373. echo $params->getLink(array('action'=>'column_view'), $lang['cancel']);
  3374. echo "</div>";
  3375. echo "</form>";
  3376. break;
  3377. //- Delete trigger (=trigger_delete)
  3378. case "trigger_delete":
  3379. echo $params->getForm(array('action'=>'trigger_delete', 'pk'=>$_GET['pk'], 'confirm'=>'1'));
  3380. echo "<div class='confirm'>";
  3381. echo sprintf($lang['ques_del_trigger'], htmlencode($_GET['pk']))."<br/><br/>";
  3382. echo "<input type='submit' value='".$lang['confirm']."' class='btn'/> ";
  3383. echo $params->getLink(array('action'=>'column_view'), $lang['cancel']);
  3384. echo "</div>";
  3385. echo "</form>";
  3386. break;
  3387. //- Create trigger (=trigger_create)
  3388. case "trigger_create":
  3389. echo "<h2>".$lang['create_trigger']." '".htmlencode($_GET['table'])."'</h2>";
  3390. if($_GET['table']=="")
  3391. echo $lang['specify_tbl'];
  3392. else
  3393. {
  3394. echo $params->getForm(array('action'=>'trigger_create', 'confirm'=>'1'));
  3395. echo $lang['trigger_name'].": <input type='text' name='trigger_name'/><br/><br/>";
  3396. echo "<fieldset><legend>".$lang['db_event']."</legend>";
  3397. echo $lang['before']."/".$lang['after'].": ";
  3398. echo "<select name='beforeafter'>";
  3399. echo "<option value=''></option>";
  3400. echo "<option value='BEFORE'>".$lang['before']."</option>";
  3401. echo "<option value='AFTER'>".$lang['after']."</option>";
  3402. echo "<option value='INSTEAD OF'>".$lang['instead']."</option>";
  3403. echo "</select>";
  3404. echo "<br/><br/>";
  3405. echo $lang['event'].": ";
  3406. echo "<select name='event'>";
  3407. echo "<option value='DELETE'>".$lang['del']."</option>";
  3408. echo "<option value='INSERT'>".$lang['insert']."</option>";
  3409. echo "<option value='UPDATE'>".$lang['update']."</option>";
  3410. echo "</select>";
  3411. echo "</fieldset><br/><br/>";
  3412. echo "<fieldset><legend>".$lang['trigger_act']."</legend>";
  3413. echo "<label><input type='checkbox' name='foreachrow'/> ".$lang['each_row']."</label><br/><br/>";
  3414. echo $lang['when_exp'].":<br/>";
  3415. echo "<textarea name='whenexpression' style='width:500px; height:100px;' rows='8' cols='50'></textarea>";
  3416. echo "<br/><br/>";
  3417. echo $lang['trigger_step'].":<br/>";
  3418. echo "<textarea name='triggersteps' style='width:500px; height:100px;' rows='8' cols='50'></textarea>";
  3419. echo "</fieldset><br/><br/>";
  3420. echo "<input type='submit' value='".$lang['create_trigger2']."' class='btn'/> ";
  3421. echo $params->getLink(array('action'=>'column_view'), $lang['cancel']);
  3422. echo "</form>";
  3423. }
  3424. break;
  3425. //- Create index (=index_create)
  3426. case "index_create":
  3427. echo "<h2>".$lang['create_index']." '".htmlencode($_GET['table'])."'</h2>";
  3428. if($_GET['numcolumns']=="" || intval($_GET['numcolumns'])<=0)
  3429. echo $lang['specify_fields'];
  3430. else if($_GET['table']=="")
  3431. echo $lang['specify_tbl'];
  3432. else
  3433. {
  3434. echo $params->getForm(array('action'=>'index_create', 'confirm'=>'1'));
  3435. $num = intval($_GET['numcolumns']);
  3436. $tableInfo = $db->getTableInfo($_GET['table']);
  3437. echo "<fieldset><legend>".$lang['define_index']."</legend>";
  3438. echo "<label for='index_name'>".$lang['index_name'].":</label> <input type='text' name='name' id='index_name'/><br/>";
  3439. echo "<label for='index_duplicate'>".$lang['dup_val'].":</label>";
  3440. echo "<select name='duplicate' id='index_duplicate'>";
  3441. echo "<option value='yes'>".$lang['allow']."</option>";
  3442. echo "<option value='no'>".$lang['not_allow']."</option>";
  3443. echo "</select><br/>";
  3444. if(version_compare($db->getSQLiteVersion(),'3.8.0')>=0)
  3445. echo "<label for='index_where'>WHERE:</label> <input type='text' name='where' id='index_where'/> ".helpLink($lang['help10']);
  3446. echo "</fieldset>";
  3447. echo "<br/>";
  3448. echo "<fieldset><legend>".$lang['define_in_col']."</legend>";
  3449. for($i=0; $i<$num; $i++)
  3450. {
  3451. echo "<select name='".$i."_field'>";
  3452. echo "<option value=''>--".$lang['ignore']."--</option>";
  3453. for($j=0; $j<sizeof($tableInfo); $j++)
  3454. echo "<option value='".htmlencode($tableInfo[$j][1])."'>".htmlencode($tableInfo[$j][1])."</option>";
  3455. echo "</select> ";
  3456. echo "<select name='".$i."_order'>";
  3457. echo "<option value=''></option>";
  3458. echo "<option value=' ASC'>".$lang['asc']."</option>";
  3459. echo "<option value=' DESC'>".$lang['desc']."</option>";
  3460. echo "</select><br/>";
  3461. }
  3462. echo "</fieldset>";
  3463. echo "<br/><br/>";
  3464. echo "<input type='hidden' name='num' value='".$num."'/>";
  3465. echo "<input type='submit' value='".$lang['create_index1']."' class='btn'/> ";
  3466. echo $params->getLink(array('action'=>'column_view'), $lang['cancel']);
  3467. echo "</form>";
  3468. }
  3469. break;
  3470. }
  3471. echo "</div>";
  3472. }
  3473. //- HMTL: views for databases
  3474. if(!$target_table && !isset($_GET['confirm']) && (!isset($_GET['action']) || (isset($_GET['action']) && $_GET['action']!="table_create"))) //the absence of these fields means we are viewing the database homepage
  3475. {
  3476. //- Switch on $view (actually a series of if-else)
  3477. if($view=="structure")
  3478. {
  3479. //- Database structure, shows all the tables (=structure)
  3480. if($db->isWritable() && !$db->isDirWritable())
  3481. {
  3482. echo "<div class='confirm' style='margin:10px 0'>";
  3483. echo $lang['attention'].': '.$lang['directory_not_writable'];
  3484. echo "</div><br/>";
  3485. }
  3486. elseif(!$db->isWritable())
  3487. {
  3488. echo "<div class='confirm' style='margin:10px 0;'>";
  3489. echo $lang['attention'].': '.$lang['database_not_writable'];
  3490. echo "</div><br/>";
  3491. }
  3492. if ($auth->isPasswordDefault())
  3493. {
  3494. echo "<div class='confirm' style='margin:20px 0px;'>";
  3495. echo sprintf($lang['warn_passwd'],(is_readable('phpliteadmin.config.php')?'phpliteadmin.config.php':basename(__FILE__)))."<br />".$lang['warn0'];
  3496. echo "</div>";
  3497. }
  3498. echo "<b>".$lang['db_name']."</b>: ".htmlencode($db->getName())."<br/>";
  3499. echo "<b>".$lang['db_path']."</b>: ".htmlencode($db->getPath())."<br/>";
  3500. echo "<b>".$lang['db_size']."</b>: ".number_format($db->getSize())." KiB<br/>";
  3501. echo "<b>".$lang['db_mod']."</b>: ".$db->getDate()."<br/>";
  3502. echo "<b>".$lang['sqlite_v']."</b>: ".$db->getSQLiteVersion()."<br/>";
  3503. echo "<b>".$lang['sqlite_ext']."</b> ".helpLink($lang['help1']).": ".$db->getType()."<br/>";
  3504. echo "<b>".$lang['php_v']."</b>: ".phpversion()."<br/>";
  3505. echo "<b>".PROJECT." ".$lang["ver"]."</b>: ".VERSION;
  3506. echo " <a href='".PROJECT_URL."' target='_blank' id='oldVersion' style='display: none;' class='warning'>".$lang['new_version']."</a><br/><br/>";
  3507. echo "<script type='text/javascript'>checkVersion('".VERSION."','".VERSION_CHECK_URL."');</script>";
  3508. if(isset($_GET['sort']) && ($_GET['sort']=='type' || $_GET['sort']=='name'))
  3509. $_SESSION[COOKIENAME.'sortTables'] = $_GET['sort'];
  3510. if(isset($_GET['order']) && ($_GET['order']=='ASC' || $_GET['order']=='DESC'))
  3511. $_SESSION[COOKIENAME.'orderTables'] = $_GET['order'];
  3512. if(!isset($_SESSION[COOKIENAME.'sortTables']))
  3513. $_SESSION[COOKIENAME.'sortTables'] = 'name';
  3514. if(!isset($_SESSION[COOKIENAME.'orderTables']))
  3515. $_SESSION[COOKIENAME.'orderTables'] = 'ASC';
  3516. $tables = $db->getTables(true, false, $_SESSION[COOKIENAME.'sortTables'], $_SESSION[COOKIENAME.'orderTables']);
  3517. if(sizeof($tables)==0)
  3518. echo $lang['no_tbl']."<br/><br/>";
  3519. else
  3520. {
  3521. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  3522. echo "<tr>";
  3523. echo "<td class='tdheader'>";
  3524. if(isset($_SESSION[COOKIENAME.'sortTables']))
  3525. $orderTag = ($_SESSION[COOKIENAME.'sortTables']=="type" && $_SESSION[COOKIENAME.'orderTables']=="ASC") ? "DESC" : "ASC";
  3526. else
  3527. $orderTag = "ASC";
  3528. echo $params->getLink(array('sort'=>'type', 'order'=>$orderTag), $lang['type']);
  3529. echo helpLink($lang['help3']);
  3530. if(isset($_SESSION[COOKIENAME.'sortTables']) && $_SESSION[COOKIENAME.'sortTables']=="type")
  3531. echo (($_SESSION[COOKIENAME.'orderTables']=="ASC") ? " <b>&uarr;</b>" : " <b>&darr;</b>");
  3532. echo "</td>";
  3533. echo "<td class='tdheader'>";
  3534. if(isset($_SESSION[COOKIENAME.'sortTables']))
  3535. $orderTag = ($_SESSION[COOKIENAME.'sortTables']=="name" && $_SESSION[COOKIENAME.'orderTables']=="ASC") ? "DESC" : "ASC";
  3536. else
  3537. $orderTag = "ASC";
  3538. echo $params->getLink(array('sort'=>'name', 'order'=>$orderTag), $lang['name']);
  3539. if(isset($_SESSION[COOKIENAME.'sortTables']) && $_SESSION[COOKIENAME.'sortTables']=="name")
  3540. echo (($_SESSION[COOKIENAME.'orderTables']=="ASC") ? " <b>&uarr;</b>" : " <b>&darr;</b>");
  3541. echo "</td>";
  3542. echo "<td class='tdheader' colspan='10'>".$lang['act']."</td>";
  3543. echo "<td class='tdheader'>".$lang['rec']."</td>";
  3544. echo "</tr>";
  3545. $totalRecords = 0;
  3546. $skippedTables = false;
  3547. foreach($tables as $tableName => $tableType)
  3548. {
  3549. $records = $db->numRows($tableName, (!isset($_GET['forceCount'])));
  3550. if($records == '?')
  3551. {
  3552. $skippedTables = true;
  3553. $records = $params->getLink(array('forceCount'=>'1'), '?');
  3554. }
  3555. else
  3556. $totalRecords += $records;
  3557. $tdWithClass = "<td class='td".($i%2 ? "1" : "2")."'>";
  3558. $tdWithClassLeft = "<td class='td".($i%2 ? "1" : "2")."' style='text-align:left;'>";
  3559. echo "<tr>";
  3560. echo $tdWithClassLeft;
  3561. echo ($tableType=="table"? $lang['tbl'] : $lang['view']);
  3562. echo "</td>";
  3563. echo $tdWithClassLeft;
  3564. echo $params->getLink(array('table'=>$tableName, 'action'=>'row_view'), htmlencode($tableName));
  3565. echo "</td>";
  3566. echo $tdWithClass;
  3567. echo $params->getLink(array('table'=>$tableName, 'action'=>'row_view'), $lang['browse']);
  3568. echo "</td>";
  3569. echo $tdWithClass;
  3570. echo $params->getLink(array('table'=>$tableName, 'action'=>'column_view'), $lang['struct']);
  3571. echo "</td>";
  3572. echo $tdWithClass;
  3573. echo $params->getLink(array('table'=>$tableName, 'action'=>'table_sql'), $lang['sql']);
  3574. echo "</td>";
  3575. echo $tdWithClass;
  3576. echo $params->getLink(array('table'=>$tableName, 'action'=>'table_search'), $lang['srch']);
  3577. echo "</td>";
  3578. echo $tdWithClass;
  3579. if($tableType=="table" && $db->isWritable() && $db->isDirWritable())
  3580. echo $params->getLink(array('table'=>$tableName, 'action'=>'row_create'), $lang['insert']);
  3581. else
  3582. echo $lang['insert'];
  3583. echo "</td>";
  3584. echo $tdWithClass;
  3585. echo $params->getLink(array('table'=>$tableName, 'action'=>'table_export'), $lang['export']);
  3586. echo "</td>";
  3587. echo $tdWithClass;
  3588. if($tableType=="table" && $db->isWritable() && $db->isDirWritable())
  3589. echo $params->getLink(array('table'=>$tableName, 'action'=>'table_import'), $lang['import']);
  3590. else
  3591. echo $lang['import'];
  3592. echo "</td>";
  3593. echo $tdWithClass;
  3594. if($db->isWritable() && $db->isDirWritable())
  3595. echo $params->getLink(array('table'=>$tableName, 'action'=>'table_rename'), $lang['rename']);
  3596. else
  3597. echo $lang['rename'];
  3598. echo "</td>";
  3599. echo $tdWithClass;
  3600. if($tableType=="table" && $db->isWritable() && $db->isDirWritable())
  3601. echo $params->getLink(array('table'=>$tableName, 'action'=>'table_empty'), $lang['empty'], 'empty');
  3602. else
  3603. echo $lang['empty'];
  3604. echo "</td>";
  3605. echo $tdWithClass;
  3606. if($db->isWritable() && $db->isDirWritable())
  3607. echo $params->getLink(array('table'=>$tableName, 'action'=>'table_drop'), $lang['drop'], 'drop');
  3608. else
  3609. echo $lang['drop'];
  3610. echo "</td>";
  3611. echo $tdWithClass;
  3612. echo $records;
  3613. echo "</td>";
  3614. echo "</tr>";
  3615. }
  3616. echo "<tr>";
  3617. echo "<td class='tdheader' colspan='12'>".sizeof($tables)." ".$lang['total']."</td>";
  3618. echo "<td class='tdheader' colspan='1' style='text-align:right;'>".$totalRecords.($skippedTables?" ".$params->getLink(array('forceCount'=>'1'),'+ ?'):"")."</td>";
  3619. echo "</tr>";
  3620. echo "</table>";
  3621. echo "<br/>";
  3622. if($skippedTables)
  3623. echo "<div class='confirm' style='margin-bottom:20px;'>".sprintf($lang["counting_skipped"],"<a href='".$params->getURL(array('forceCount'=>'1'))."'>","</a>")."</div>";
  3624. }
  3625. if($db->isWritable() && $db->isDirWritable())
  3626. {
  3627. echo "<fieldset>";
  3628. echo "<legend><b>".$lang['create_tbl_db']." '".htmlencode($db->getName())."'</b></legend>";
  3629. echo $params->getForm(array('action'=>'table_create'), 'get');
  3630. echo $lang['name'].": <input type='text' name='tablename' style='width:200px;'/> ";
  3631. echo $lang['fld_num'].": <input type='text' name='tablefields' style='width:90px;'/> ";
  3632. echo "<input type='submit' name='createtable' value='".$lang['go']."' class='btn'/>";
  3633. echo "</form>";
  3634. echo "</fieldset>";
  3635. echo "<br/>";
  3636. echo "<fieldset>";
  3637. echo "<legend><b>".$lang['create_view']." '".htmlencode($db->getName())."'</b></legend>";
  3638. echo $params->getForm(array('action'=>'view_create', 'confirm'=>'1'));
  3639. echo $lang['name'].": <input type='text' name='viewname' style='width:200px;'/> ";
  3640. echo $lang['sel_state']." ".helpLink($lang['help4']).": <input type='text' name='select' style='width:400px;'/> ";
  3641. echo "<input type='submit' name='createtable' value='".$lang['go']."' class='btn'/>";
  3642. echo "</form>";
  3643. echo "</fieldset>";
  3644. }
  3645. }
  3646. else if($view=="sql")
  3647. {
  3648. //- Database SQL editor (=sql)
  3649. if(isset($_POST['query']) && $_POST['query']!="")
  3650. {
  3651. $delimiter = $_POST['delimiter'];
  3652. $queryStr = $_POST['queryval'];
  3653. //save the queries in history if necessary
  3654. if($maxSavedQueries!=0 && $maxSavedQueries!=false)
  3655. {
  3656. if(!isset($_SESSION[COOKIENAME.'query_history']))
  3657. $_SESSION[COOKIENAME.'query_history'] = array();
  3658. $_SESSION[COOKIENAME.'query_history'][md5(strtolower($queryStr))] = $queryStr;
  3659. if(sizeof($_SESSION[COOKIENAME.'query_history']) > $maxSavedQueries)
  3660. array_shift($_SESSION[COOKIENAME.'query_history']);
  3661. }
  3662. $query = explode_sql($delimiter, $queryStr); //explode the query string into individual queries based on the delimiter
  3663. for($i=0; $i<sizeof($query); $i++) //iterate through the queries exploded by the delimiter
  3664. {
  3665. if(str_replace(" ", "", str_replace("\n", "", str_replace("\r", "", $query[$i])))!="") //make sure this query is not an empty string
  3666. {
  3667. $queryTimer = new MicroTimer();
  3668. $table_result = $db->query($query[$i]);
  3669. echo "<div class='confirm'>";
  3670. echo "<b>".htmlencode($query[$i])."</b>";
  3671. if($table_result === NULL || $table_result === false)
  3672. {
  3673. echo "<br /><b>".$lang['err'].": ".htmlencode($db->getError())."</b></div>";
  3674. }
  3675. echo "</div><br/>";
  3676. if($row = $db->fetch($table_result, 'num'))
  3677. {
  3678. for($j=0; $j<sizeof($row);$j++)
  3679. $headers[$j] = $db->getColumnName($table_result,$j);
  3680. echo "<table border='0' cellpadding='2' cellspacing='1' class='viewTable'>";
  3681. echo "<tr>";
  3682. for($j=0; $j<sizeof($headers); $j++)
  3683. {
  3684. echo "<td class='tdheader'>";
  3685. echo htmlencode($headers[$j]);
  3686. echo "</td>";
  3687. }
  3688. echo "</tr>";
  3689. $rowCount = 0;
  3690. for(; $rowCount==0 || $row = $db->fetch($table_result, 'num'); $rowCount++)
  3691. {
  3692. $tdWithClass = "<td class='td".($rowCount%2 ? "1" : "2")."'>";
  3693. echo "<tr>";
  3694. for($z=0; $z<sizeof($headers); $z++)
  3695. {
  3696. echo $tdWithClass;
  3697. if($row[$z]==="")
  3698. echo "&nbsp;";
  3699. elseif($row[$z]===NULL)
  3700. echo "<i class='null'>NULL</i>";
  3701. else
  3702. echo htmlencode(subString($row[$z]));
  3703. echo "</td>";
  3704. }
  3705. echo "</tr>";
  3706. }
  3707. $queryTimer->stop();
  3708. echo "</table><br/><br/>";
  3709. if($table_result !== NULL && $table_result !== false)
  3710. {
  3711. echo "<div class='confirm' style='margin-bottom: 2em'>";
  3712. if($rowCount>0 || $db->getAffectedRows()==0)
  3713. {
  3714. printf($lang['show_rows'], $rowCount);
  3715. }
  3716. if($db->getAffectedRows()>0 || $rowCount==0)
  3717. {
  3718. echo $db->getAffectedRows()." ".$lang['rows_aff']." ";
  3719. }
  3720. printf($lang['query_time'], $queryTimer);
  3721. echo "</div>";
  3722. }
  3723. }
  3724. }
  3725. }
  3726. }
  3727. else
  3728. {
  3729. $delimiter = ";";
  3730. $queryStr = "";
  3731. }
  3732. echo "<fieldset>";
  3733. echo "<legend><b>".sprintf($lang['run_sql'],htmlencode($db->getName()))."</b></legend>";
  3734. echo $params->getForm(array('view'=>'sql'));
  3735. if(isset($_SESSION[COOKIENAME.'query_history']) && sizeof($_SESSION[COOKIENAME.'query_history'])>0)
  3736. {
  3737. echo "<b>".$lang['recent_queries']."</b><ul>";
  3738. foreach($_SESSION[COOKIENAME.'query_history'] as $key => $value)
  3739. {
  3740. echo "<li><a onclick='sqleditorSetValue(this.textContent); return false;' href='#'>".htmlencode($value)."</a></li>";
  3741. }
  3742. echo "</ul><br/><br/>";
  3743. }
  3744. echo "<textarea style='width:100%; height:300px;' name='queryval' id='queryval' cols='50' rows='8'>".htmlencode($queryStr)."</textarea>";
  3745. echo "<script>sqleditor(document.getElementById('queryval'),".json_encode($db->getTableDefinitions()).", null);</script>";
  3746. echo $lang['delimit']." <input type='text' name='delimiter' value='".htmlencode($delimiter)."' style='width:50px;'/> ";
  3747. echo "<input type='submit' name='query' value='".$lang['go']."' class='btn'/>";
  3748. echo "</form>";
  3749. echo "</fieldset>";
  3750. }
  3751. else if($view=="vacuum")
  3752. {
  3753. //- Vacuum database confirmation (=vacuum)
  3754. if(isset($_POST['vacuum']))
  3755. {
  3756. $query = "VACUUM";
  3757. $db->query($query);
  3758. echo "<div class='confirm'>";
  3759. printf($lang['db_vac'], htmlencode($db->getName()));
  3760. echo "</div><br/>";
  3761. }
  3762. echo $params->getForm(array('view'=>'vacuum'));
  3763. printf($lang['vac_desc'],htmlencode($db->getName()));
  3764. echo "<br/><br/>";
  3765. echo "<input type='submit' value='".$lang['vac']."' name='vacuum' class='btn'/>";
  3766. echo "</form>";
  3767. }
  3768. else if($view=="export")
  3769. {
  3770. //- Export view (=export)
  3771. echo $params->getForm(array('view'=>'export'));
  3772. echo "<fieldset style='float:left; width:260px; margin-right:20px;'><legend><b>".$lang['export']."</b></legend>";
  3773. echo "<select multiple='multiple' size='10' style='width:240px;' name='tables[]'>";
  3774. $tables = $db->getTables(true, false);
  3775. foreach($tables as $tableName => $tableType)
  3776. {
  3777. echo "<option value='".htmlencode($tableName)."' selected='selected'>".htmlencode($tableName)."</option>";
  3778. }
  3779. echo "</select>";
  3780. echo "<br/><br/>";
  3781. echo "<label><input type='radio' name='export_type' checked='checked' value='sql' onclick='toggleExports(\"sql\");'/> ".$lang['sql']."</label>";
  3782. echo "<br/><label><input type='radio' name='export_type' value='csv' onclick='toggleExports(\"csv\");'/> ".$lang['csv']."</label>";
  3783. echo "</fieldset>";
  3784. echo "<fieldset style='float:left; max-width:350px;' id='exportoptions_sql'><legend><b>".$lang['options']."</b></legend>";
  3785. echo "<label><input type='checkbox' checked='checked' name='structure'/> ".$lang['export_struct']."</label> ".helpLink($lang['help5'])."<br/>";
  3786. echo "<label><input type='checkbox' checked='checked' name='data'/> ".$lang['export_data']."</label> ".helpLink($lang['help6'])."<br/>";
  3787. echo "<label><input type='checkbox' name='drop'/> ".$lang['add_drop']."</label> ".helpLink($lang['help7'])."<br/>";
  3788. echo "<label><input type='checkbox' checked='checked' name='transaction'/> ".$lang['add_transact']."</label> ".helpLink($lang['help8'])."<br/>";
  3789. echo "<label><input type='checkbox' checked='checked' name='comments'/> ".$lang['comments']."</label> ".helpLink($lang['help9'])."<br/>";
  3790. echo "</fieldset>";
  3791. echo "<fieldset style='float:left; max-width:350px; display:none;' id='exportoptions_csv'><legend><b>".$lang['options']."</b></legend>";
  3792. echo "<div style='float:left;'>".$lang['fld_terminated']."</div>";
  3793. echo "<input type='text' value=';' name='export_csv_fieldsterminated' style='float:right;'/>";
  3794. echo "<div style='clear:both;'>";
  3795. echo "<div style='float:left;'>".$lang['fld_enclosed']."</div>";
  3796. echo "<input type='text' value='\"' name='export_csv_fieldsenclosed' style='float:right;'/>";
  3797. echo "<div style='clear:both;'>";
  3798. echo "<div style='float:left;'>".$lang['fld_escaped']."</div>";
  3799. echo "<input type='text' value='\' name='export_csv_fieldsescaped' style='float:right;'/>";
  3800. echo "<div style='clear:both;'>";
  3801. echo "<div style='float:left;'>".$lang['rep_null']."</div>";
  3802. echo "<input type='text' value='NULL' name='export_csv_replacenull' style='float:right;'/>";
  3803. echo "<div style='clear:both;'>";
  3804. echo "<label><input type='checkbox' name='export_csv_crlf'/> ".$lang['rem_crlf']."</label><br/>";
  3805. echo "<label><input type='checkbox' checked='checked' name='export_csv_fieldnames'/> ".$lang['put_fld']."</label>";
  3806. echo "</fieldset>";
  3807. echo "<div style='clear:both;'></div>";
  3808. echo "<br/><br/>";
  3809. echo "<fieldset><legend><b>".$lang['save_as']."</b></legend>";
  3810. $file = pathinfo($db->getPath());
  3811. $name = $file['filename'];
  3812. echo "<input type='text' name='filename' value='".htmlencode($name)."_".date("Y-m-d").".dump' style='width:400px;'/> <input type='submit' name='export' value='".$lang['export']."' class='btn'/>";
  3813. echo "</fieldset>";
  3814. echo "</form>";
  3815. echo "<div class='confirm' style='margin-top: 2em'>".sprintf($lang['backup_hint'],
  3816. $params->getLink(array('download'=>$currentDB['path'], 'token'=>$_SESSION[COOKIENAME.'token']), $lang["backup_hint_linktext"], '', $lang['backup'])
  3817. )."</div>";
  3818. }
  3819. else if($view=="import")
  3820. {
  3821. //- Import view (=import)
  3822. if(isset($_POST['import']))
  3823. {
  3824. echo "<div class='confirm'>";
  3825. if($importSuccess===true)
  3826. echo $lang['import_suc'];
  3827. else
  3828. echo $importSuccess;
  3829. echo "</div><br/>";
  3830. }
  3831. echo $params->getForm(array('view'=>'import'), 'post', true);
  3832. echo "<fieldset style='float:left; width:260px; margin-right:20px;'><legend><b>".$lang['import']."</b></legend>";
  3833. echo "<label><input type='radio' name='import_type' checked='checked' value='sql' onclick='toggleImports(\"sql\");'/> ".$lang['sql']."</label>";
  3834. echo "<br/><label><input type='radio' name='import_type' value='csv' onclick='toggleImports(\"csv\");'/> ".$lang['csv']."</label>";
  3835. echo "</fieldset>";
  3836. echo "<fieldset style='float:left; max-width:350px;' id='importoptions_sql'><legend><b>".$lang['options']."</b></legend>";
  3837. echo $lang['no_opt'];
  3838. echo "</fieldset>";
  3839. echo "<fieldset style='float:left; max-width:350px; display:none;' id='importoptions_csv'><legend><b>".$lang['options']."</b></legend>";
  3840. echo "<div style='float:left;'>".$lang['csv_tbl']."</div>";
  3841. echo "<select name='single_table' style='float:right;'>";
  3842. $tables = $db->getTables(true, false);
  3843. echo "<option value=''>(".$lang['create_tbl'].")</option>";
  3844. foreach($tables as $tableName => $tableType)
  3845. {
  3846. echo "<option value='".htmlencode($tableName)."'>".htmlencode($tableName)."</option>";
  3847. }
  3848. echo "</select>";
  3849. echo "<div style='clear:both;'>";
  3850. echo "<div style='float:left;'>".$lang['fld_terminated']."</div>";
  3851. echo "<input type='text' value=';' name='import_csv_fieldsterminated' style='float:right;'/>";
  3852. echo "<div style='clear:both;'>";
  3853. echo "<div style='float:left;'>".$lang['fld_enclosed']."</div>";
  3854. echo "<input type='text' value='\"' name='import_csv_fieldsenclosed' style='float:right;'/>";
  3855. echo "<div style='clear:both;'>";
  3856. echo "<div style='float:left;'>".$lang['fld_escaped']."</div>";
  3857. echo "<input type='text' value='\' name='import_csv_fieldsescaped' style='float:right;'/>";
  3858. echo "<div style='clear:both;'>";
  3859. echo "<div style='float:left;'>".$lang['null_represent']."</div>";
  3860. echo "<input type='text' value='NULL' name='import_csv_replacenull' style='float:right;'/>";
  3861. echo "<div style='clear:both;'>";
  3862. echo "<label><input type='checkbox' checked='checked' name='import_csv_fieldnames'/> ".$lang['fld_names']."</label>";
  3863. echo "</fieldset>";
  3864. echo "<div style='clear:both;'></div>";
  3865. echo "<br/><br/>";
  3866. echo "<fieldset><legend><b>".$lang['import_f']."</b></legend>";
  3867. echo "<em>".$lang['max_file_size'].": ".number_format(fileUploadMaxSize()/1024/1024)." MiB</em> ".helpLink($lang['help11'])."<br />";
  3868. echo "<input type='file' value='".$lang['choose_f']."' name='file' style='background-color:transparent; border-style:none; margin:0; padding:0' onchange='checkFileSize(this)'/>";
  3869. echo "<input type='submit' value='".$lang['import']."' name='import' class='btn'/>";
  3870. echo "</fieldset>";
  3871. }
  3872. else if($view=="rename")
  3873. {
  3874. //- Rename database confirmation (=rename)
  3875. echo $params->getForm(array('view'=>'rename', 'database_rename'=>'1'));
  3876. echo "<input type='hidden' name='oldname' value='".htmlencode($db->getPath())."'/>";
  3877. echo $lang['db_rename']." '".htmlencode($db->getPath())."' ".$lang['to']." <input type='text' name='newname' style='width:200px;' value='".htmlencode($db->getPath())."'/> <input type='submit' value='".$lang['rename']."' name='rename' class='btn'/>";
  3878. echo "</form>";
  3879. }
  3880. else if($view=="delete")
  3881. {
  3882. //- Delete database confirmation (=delete)
  3883. echo $params->getForm(array('database_delete'=>'1'));
  3884. echo "<div class='confirm'>";
  3885. echo sprintf($lang['ques_del_db'],htmlencode($db->getPath()))."<br/><br/>";
  3886. echo "<input name='database_delete' value='".htmlencode($db->getPath())."' type='hidden'/>";
  3887. echo "<input type='submit' value='".$lang['confirm']."' class='btn'/> ";
  3888. echo $params->getLink(array(), $lang['cancel']);
  3889. echo "</div>";
  3890. echo "</form>";
  3891. }
  3892. echo "</div>";
  3893. }
  3894. echo "</div>";
  3895. //- HTML: page footer
  3896. echo "<br/>";
  3897. echo "<span style='font-size:11px;'>".$lang['powered']." <a href='".PROJECT_URL."' target='_blank' style='font-size:11px;'>".PROJECT."</a> | ";
  3898. echo $lang['free_software']." <a href='".DONATE_URL."' target='_blank' style='font-size:11px;'>".$lang['please_donate']."</a> | ";
  3899. printf($lang['page_gen'], $pageTimer);
  3900. echo "</span>";
  3901. echo "</td></tr></table>";
  3902. $db->close(); //close the database
  3903. echo "</body>";
  3904. echo "</html>";
  3905. //- End of main code
  3906. // Authorization class
  3907. // Maintains user's logged-in state and security of application
  3908. //
  3909. class Authorization
  3910. {
  3911. private $authorized;
  3912. private $login_failed;
  3913. private $system_password_encrypted;
  3914. public function __construct()
  3915. {
  3916. // first, make sure a CSRF token is generated
  3917. $this->generateToken();
  3918. // second, check for possible CSRF attacks. to protect logins, this is done before checking login
  3919. $this->checkToken();
  3920. // the salt and password encrypting is probably unnecessary protection but is done just
  3921. // for the sake of being very secure
  3922. if(!isset($_SESSION[COOKIENAME.'_salt']) && !isset($_COOKIE[COOKIENAME.'_salt']))
  3923. {
  3924. // create a random salt for this session if a cookie doesn't already exist for it
  3925. $_SESSION[COOKIENAME.'_salt'] = self::generateSalt(22);
  3926. }
  3927. else if(!isset($_SESSION[COOKIENAME.'_salt']) && isset($_COOKIE[COOKIENAME.'_salt']))
  3928. {
  3929. // session doesn't exist, but cookie does so grab it
  3930. $_SESSION[COOKIENAME.'_salt'] = $_COOKIE[COOKIENAME.'_salt'];
  3931. }
  3932. // salted and encrypted password used for checking
  3933. $this->system_password_encrypted = md5(SYSTEMPASSWORD."_".$_SESSION[COOKIENAME.'_salt']);
  3934. $this->authorized =
  3935. // no password
  3936. SYSTEMPASSWORD == ''
  3937. // correct password stored in session
  3938. || isset($_SESSION[COOKIENAME.'password']) && hash_equals($_SESSION[COOKIENAME.'password'], $this->system_password_encrypted)
  3939. // correct password stored in cookie
  3940. || isset($_COOKIE[COOKIENAME]) && isset($_COOKIE[COOKIENAME.'_salt']) && hash_equals(md5(SYSTEMPASSWORD."_".$_COOKIE[COOKIENAME.'_salt']), $_COOKIE[COOKIENAME]);
  3941. }
  3942. public function attemptGrant($password, $remember)
  3943. {
  3944. $hashed_password = crypt(SYSTEMPASSWORD, '$2a$07$'.self::generateSalt(22).'$');
  3945. if (hash_equals($hashed_password, crypt($password, $hashed_password))) {
  3946. if ($remember) {
  3947. // user wants to be remembered, so set a cookie
  3948. $expire = time()+60*60*24*30; //set expiration to 1 month from now
  3949. setcookie(COOKIENAME, $this->system_password_encrypted, $expire, null, null, null, true);
  3950. setcookie(COOKIENAME."_salt", $_SESSION[COOKIENAME.'_salt'], $expire, null, null, null, true);
  3951. } else {
  3952. // user does not want to be remembered, so destroy any potential cookies
  3953. setcookie(COOKIENAME, "", time()-86400, null, null, null, true);
  3954. setcookie(COOKIENAME."_salt", "", time()-86400, null, null, null, true);
  3955. unset($_COOKIE[COOKIENAME]);
  3956. unset($_COOKIE[COOKIENAME.'_salt']);
  3957. }
  3958. $_SESSION[COOKIENAME.'password'] = $this->system_password_encrypted;
  3959. $this->authorized = true;
  3960. return true;
  3961. }
  3962. $this->login_failed = true;
  3963. return false;
  3964. }
  3965. public function revoke()
  3966. {
  3967. //destroy everything - cookies and session vars
  3968. setcookie(COOKIENAME, "", time()-86400, null, null, null, true);
  3969. setcookie(COOKIENAME."_salt", "", time()-86400, null, null, null, true);
  3970. unset($_COOKIE[COOKIENAME]);
  3971. unset($_COOKIE[COOKIENAME.'_salt']);
  3972. session_unset();
  3973. session_destroy();
  3974. $this->authorized = false;
  3975. // start a new session and generate a new CSRF token for the login form
  3976. session_start();
  3977. $this->generateToken();
  3978. }
  3979. public function isAuthorized()
  3980. {
  3981. return $this->authorized;
  3982. }
  3983. public function isFailedLogin()
  3984. {
  3985. return $this->login_failed;
  3986. }
  3987. public function isPasswordDefault()
  3988. {
  3989. return SYSTEMPASSWORD == 'admin';
  3990. }
  3991. private static function generateSalt($saltSize)
  3992. {
  3993. $set = 'ABCDEFGHiJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  3994. $setLast = strlen($set) - 1;
  3995. $salt = '';
  3996. while ($saltSize-- > 0) {
  3997. $salt .= $set[mt_rand(0, $setLast)];
  3998. }
  3999. return $salt;
  4000. }
  4001. private function generateToken()
  4002. {
  4003. // generate CSRF token
  4004. if (empty($_SESSION[COOKIENAME.'token']))
  4005. {
  4006. if (function_exists('random_bytes')) // introduced in PHP 7.0
  4007. {
  4008. $_SESSION[COOKIENAME.'token'] = bin2hex(random_bytes(32));
  4009. }
  4010. elseif (function_exists('openssl_random_pseudo_bytes')) // introduced in PHP 5.3.0
  4011. {
  4012. $_SESSION[COOKIENAME.'token'] = bin2hex(openssl_random_pseudo_bytes(32));
  4013. }
  4014. else
  4015. {
  4016. // For PHP 5.2.x - This case can be removed once we drop support for 5.2.x
  4017. $_SESSION[COOKIENAME.'token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
  4018. }
  4019. }
  4020. }
  4021. private function checkToken()
  4022. {
  4023. // checking CSRF token
  4024. if($_SERVER['REQUEST_METHOD'] === 'POST' || isset($_GET['download'])) // all POST forms need tokens! downloads are protected as well
  4025. {
  4026. if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['token']))
  4027. $check_token=$_POST['token'];
  4028. elseif($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['token']))
  4029. $check_token=$_GET['token'];
  4030. if (!isset($check_token))
  4031. {
  4032. die("CSRF token missing");
  4033. }
  4034. elseif(!hash_equals($_SESSION[COOKIENAME.'token'], $check_token))
  4035. {
  4036. die("CSRF token is wrong - please try to login again");
  4037. }
  4038. }
  4039. }
  4040. }
  4041. // Database class
  4042. // Generic database abstraction class to manage interaction with database without worrying about SQLite vs. PHP versions
  4043. //
  4044. class Database
  4045. {
  4046. protected $db; //reference to the DB object
  4047. protected $type; //the extension for PHP that handles SQLite
  4048. protected $data;
  4049. protected $lastResult;
  4050. protected $alterError;
  4051. protected $debugOutput ='';
  4052. public function __construct($data)
  4053. {
  4054. global $lang, $params;
  4055. $this->data = $data;
  4056. try
  4057. {
  4058. if(!file_exists($this->data["path"]) && !is_writable(dirname($this->data["path"]))) //make sure the containing directory is writable if the database does not exist
  4059. {
  4060. echo "<div class='confirm' style='margin:20px;'>";
  4061. printf($lang['db_not_writeable'], htmlencode($this->data["path"]), htmlencode(dirname($this->data["path"])));
  4062. echo $params->getForm();
  4063. echo "<input type='submit' value='Log Out' name='".$lang['logout']."' class='btn'/>";
  4064. echo "</form>";
  4065. echo "</div><br/>";
  4066. exit();
  4067. }
  4068. $ver = $this->getVersion();
  4069. switch(true)
  4070. {
  4071. case ((!isset($data['type']) || $data['type']!=2) && (FORCETYPE=="PDO" || (FORCETYPE==false && class_exists("PDO") && in_array("sqlite", PDO::getAvailableDrivers()) && ($ver==-1 || $ver==3)))):
  4072. $this->db = new PDO("sqlite:".$this->data['path']);
  4073. if($this->db!=NULL)
  4074. {
  4075. $this->type = "PDO";
  4076. break;
  4077. }
  4078. case ((!isset($data['type']) || $data['type']!=2) && (FORCETYPE=="SQLite3" || (FORCETYPE==false && class_exists("SQLite3") && ($ver==-1 || $ver==3)))):
  4079. $this->db = new SQLite3($this->data['path']);
  4080. if($this->db!=NULL)
  4081. {
  4082. $this->type = "SQLite3";
  4083. break;
  4084. }
  4085. case (FORCETYPE=="SQLiteDatabase" || (FORCETYPE==false && class_exists("SQLiteDatabase") && ($ver==-1 || $ver==2))):
  4086. $this->db = new SQLiteDatabase($this->data['path']);
  4087. if($this->db!=NULL)
  4088. {
  4089. $this->type = "SQLiteDatabase";
  4090. break;
  4091. }
  4092. default:
  4093. $this->showError();
  4094. exit();
  4095. }
  4096. $this->query("PRAGMA foreign_keys = ON");
  4097. }
  4098. catch(Exception $e)
  4099. {
  4100. $this->showError();
  4101. exit();
  4102. }
  4103. }
  4104. public function registerUserFunction($ids)
  4105. {
  4106. // in case a single function id was passed
  4107. if (is_string($ids))
  4108. $ids = array($ids);
  4109. if ($this->type == 'PDO') {
  4110. foreach ($ids as $id) {
  4111. $this->db->sqliteCreateFunction($id, $id, -1);
  4112. }
  4113. } else { // type is Sqlite3 or SQLiteDatabase
  4114. foreach ($ids as $id) {
  4115. $this->db->createFunction($id, $id, -1);
  4116. }
  4117. }
  4118. }
  4119. public function getError($complete_msg = false)
  4120. {
  4121. global $lang, $debug;
  4122. $error = "unknown";
  4123. if($this->alterError!='')
  4124. {
  4125. $error = $this->alterError;
  4126. $this->alterError = "";
  4127. }
  4128. else if($this->type=="PDO")
  4129. {
  4130. $e = $this->db->errorInfo();
  4131. $error = $e[2];
  4132. }
  4133. else if($this->type=="SQLite3")
  4134. {
  4135. $error = $this->db->lastErrorMsg();
  4136. }
  4137. else
  4138. {
  4139. $error = sqlite_error_string($this->db->lastError());
  4140. }
  4141. if($complete_msg)
  4142. {
  4143. $error = $lang['err'].": ".htmlencode($error);
  4144. // do not suggest to report a bug when constraints fail
  4145. if(strpos($error, 'constraint failed')===false)
  4146. $error.="<br/>".$lang['bug_report'].' '.PROJECT_BUGTRACKER_LINK;
  4147. }
  4148. if($debug)
  4149. $error .= $this->getDebugOutput();
  4150. return $error;
  4151. }
  4152. function getDebugOutput()
  4153. {
  4154. return ($this->debugOutput != "" ? "<hr /><strong>DEBUG:</strong><br />".$this->debugOutput : $this->debugOutput);
  4155. }
  4156. public function showError()
  4157. {
  4158. global $lang;
  4159. $classPDO = class_exists("PDO");
  4160. $classSQLite3 = class_exists("SQLite3");
  4161. $classSQLiteDatabase = class_exists("SQLiteDatabase");
  4162. if($classPDO) // PDO is there, check if the SQLite driver for PDO is missing
  4163. $PDOSqliteDriver = (in_array("sqlite", PDO::getAvailableDrivers() ));
  4164. else
  4165. $PDOSqliteDriver = false;
  4166. echo "<div class='confirm' style='margin:20px;'>";
  4167. printf($lang['db_setup'], $this->getPath());
  4168. echo ".<br/><br/><i>".$lang['chk_ext']."...<br/><br/>";
  4169. echo "<b>PDO</b>: ".($classPDO ? $lang['installed'] : $lang['not_installed'])."<br/>";
  4170. echo "<b>PDO SQLite Driver</b>: ".($PDOSqliteDriver ? $lang['installed'] : $lang['not_installed'])."<br/>";
  4171. echo "<b>SQLite3</b>: ".($classSQLite3 ? $lang['installed'] : $lang['not_installed'])."<br/>";
  4172. echo "<b>SQLiteDatabase</b>: ".($classSQLiteDatabase ? $lang['installed'] : $lang['not_installed'])."<br/>";
  4173. echo "<br/>...".$lang['done'].".</i><br/><br/>";
  4174. if(!$classPDO && !$classSQLite3 && !$classSQLiteDatabase)
  4175. printf($lang['sqlite_ext_support'], PROJECT);
  4176. else
  4177. {
  4178. if(!$PDOSqliteDriver && !$classSQLite3 && $this->getVersion()==3)
  4179. printf($lang['sqlite_v_error'], 3, PROJECT, 2);
  4180. else if(!$classSQLiteDatabase && $this->getVersion()==2)
  4181. printf($lang['sqlite_v_error'], 2, PROJECT, 3);
  4182. else
  4183. echo $lang['report_issue'].' '.PROJECT_BUGTRACKER_LINK.'.';
  4184. }
  4185. echo "<p>See ".PROJECT_INSTALL_LINK." for help.</p>";
  4186. $this->print_db_list();
  4187. echo "</div>";
  4188. }
  4189. // print the list of databases
  4190. public function print_db_list()
  4191. {
  4192. global $databases, $lang, $params, $currentDB;
  4193. echo "<fieldset style='margin:15px;' class='databaseList'><legend><b>".$lang['db_ch']."</b></legend>";
  4194. if(sizeof($databases)<10) //if there aren't a lot of databases, just show them as a list of links instead of drop down menu
  4195. {
  4196. $i=0;
  4197. foreach($databases as $database)
  4198. {
  4199. $i++;
  4200. $name = $database['name'];
  4201. if(mb_strlen($name)>25)
  4202. $name = "...".mb_substr($name, mb_strlen($name)-22, 22);
  4203. echo '[' . ($database['readable'] ? 'r':' ' ) . ($database['writable'] && $database['writable_dir'] ? 'w':' ' ) . ']&nbsp;';
  4204. echo $params->getLink(array('database'=>$database['path'], 'table'=>null), htmlencode($name), ($database == $currentDB? 'active_db': '') );
  4205. echo "&nbsp;&nbsp;";
  4206. echo $params->getLink(array('download'=>$database['path'], 'table'=>null, 'token'=>$_SESSION[COOKIENAME.'token']), '[&darr;]', '', $lang['backup']);
  4207. if($i<sizeof($databases))
  4208. echo "<br/>";
  4209. }
  4210. }
  4211. else //there are a lot of databases - show a drop down menu
  4212. {
  4213. echo $params->getForm(array('table'=>null), 'get');
  4214. echo "<select name='database' onchange='this.form.submit()'>";
  4215. foreach($databases as $database)
  4216. {
  4217. $perms_string = htmlencode('[' . ($database['readable'] ? 'r':' ' ) . ($database['writable'] && $database['writable_dir'] ? 'w':' ' ) . '] ');
  4218. if($database == $currentDB)
  4219. echo "<option value='".htmlencode($database['path'])."' selected='selected'>".$perms_string.htmlencode($database['name'])."</option>";
  4220. else
  4221. echo "<option value='".htmlencode($database['path'])."'>".$perms_string.htmlencode($database['name'])."</option>";
  4222. }
  4223. echo "</select>";
  4224. echo "<noscript><input type='submit' value='".$lang['go']."' class='btn'></noscript>";
  4225. echo "</form>";
  4226. }
  4227. echo "</fieldset>";
  4228. }
  4229. public function __destruct()
  4230. {
  4231. if($this->db)
  4232. $this->close();
  4233. }
  4234. //get the exact PHP extension being used for SQLite
  4235. public function getType()
  4236. {
  4237. return $this->type;
  4238. }
  4239. // get the version of the SQLite library
  4240. public function getSQLiteVersion()
  4241. {
  4242. $queryVersion = $this->select("SELECT sqlite_version() AS sqlite_version");
  4243. return $queryVersion['sqlite_version'];
  4244. }
  4245. //get the name of the database
  4246. public function getName()
  4247. {
  4248. return $this->data["name"];
  4249. }
  4250. //get the filename of the database
  4251. public function getPath()
  4252. {
  4253. return $this->data["path"];
  4254. }
  4255. //is the db-file writable?
  4256. public function isWritable()
  4257. {
  4258. return $this->data["writable"];
  4259. }
  4260. //is the db-folder writable?
  4261. public function isDirWritable()
  4262. {
  4263. return $this->data["writable_dir"];
  4264. }
  4265. //get the version of the database
  4266. public function getVersion()
  4267. {
  4268. if(file_exists($this->data['path'])) //make sure file exists before getting its contents
  4269. {
  4270. $content = strtolower(file_get_contents($this->data['path'], NULL, NULL, 0, 40)); //get the first 40 characters of the database file
  4271. $p = strpos($content, "** this file contains an sqlite 2"); //this text is at the beginning of every SQLite2 database
  4272. if($p!==false) //the text is found - this is version 2
  4273. return 2;
  4274. else
  4275. return 3;
  4276. }
  4277. else //return -1 to indicate that it does not exist and needs to be created
  4278. {
  4279. return -1;
  4280. }
  4281. }
  4282. //get the size of the database (in KiB)
  4283. public function getSize()
  4284. {
  4285. return round(filesize($this->data["path"])*0.0009765625, 1);
  4286. }
  4287. //get the last modified time of database
  4288. public function getDate()
  4289. {
  4290. global $lang;
  4291. return date($lang['date_format'], filemtime($this->data['path']));
  4292. }
  4293. //get number of affected rows from last query
  4294. public function getAffectedRows()
  4295. {
  4296. if($this->type=="PDO")
  4297. if(!is_object($this->lastResult))
  4298. // in case it was an alter table statement, there is no lastResult object
  4299. return 0;
  4300. else
  4301. return $this->lastResult->rowCount();
  4302. else if($this->type=="SQLite3")
  4303. return $this->db->changes();
  4304. else if($this->type=="SQLiteDatabase")
  4305. return $this->db->changes();
  4306. }
  4307. public function getTypeOfTable($table)
  4308. {
  4309. $result = $this->select("SELECT `type` FROM `sqlite_master` WHERE `name`=" . $this->quote($table), 'assoc');
  4310. return $result['type'];
  4311. }
  4312. public function getTableInfo($table)
  4313. {
  4314. return $this->selectArray("PRAGMA table_info(".$this->quote_id($table).")");
  4315. }
  4316. // returns the list of tables (opt. incl. views) as
  4317. // array( Tablename => tableType ) with tableType being 'view' or 'table'
  4318. public function getTables($alsoViews=true, $alsoInternal=false, $orderBy='name', $orderDirection='ASC')
  4319. {
  4320. $query = "SELECT name, type FROM sqlite_master "
  4321. . "WHERE (type='table'".($alsoViews?" OR type='view'":"").") "
  4322. . "AND name!='' ".($alsoInternal? "":" AND name NOT LIKE 'sqlite_%' ")
  4323. . "ORDER BY ".$this->quote_id($orderBy)." ".$orderDirection;
  4324. $result = $this->selectArray($query);
  4325. $list = array();
  4326. for($i=0; $i<sizeof($result); $i++)
  4327. {
  4328. $list[$result[$i]['name']] = $result[$i]['type'];
  4329. }
  4330. return $list;
  4331. }
  4332. // returns an array of all tables and their columns as
  4333. // array( tablename => array(columName) )
  4334. public function getTableDefinitions()
  4335. {
  4336. $tables = $this->getTables(true, true);
  4337. $result = array();
  4338. foreach ($tables as $tableName => $tableType)
  4339. {
  4340. $tableInfo = $this->getTableInfo($tableName);
  4341. $columns = array();
  4342. foreach($tableInfo as $column)
  4343. $columns[] = $column['name'];
  4344. $result[$tableName] = $columns;
  4345. }
  4346. return $result;
  4347. }
  4348. public function close()
  4349. {
  4350. if($this->type=="PDO")
  4351. $this->db = NULL;
  4352. else if($this->type=="SQLite3")
  4353. $this->db->close();
  4354. else if($this->type=="SQLiteDatabase")
  4355. $this->db = NULL;
  4356. }
  4357. public function beginTransaction()
  4358. {
  4359. $this->query("BEGIN");
  4360. }
  4361. public function commitTransaction()
  4362. {
  4363. $this->query("COMMIT");
  4364. }
  4365. public function rollbackTransaction()
  4366. {
  4367. $this->query("ROLLBACK");
  4368. }
  4369. //generic query wrapper
  4370. //returns false on error and the query result on success
  4371. public function query($query, $ignoreAlterCase=false)
  4372. {
  4373. global $debug;
  4374. if(strtolower(substr(ltrim($query),0,5))=='alter' && $ignoreAlterCase==false) //this query is an ALTER query - call the necessary function
  4375. {
  4376. preg_match("/^\s*ALTER\s+TABLE\s+\"((?:[^\"]|\"\")+)\"\s+(.*)$/i",$query,$matches);
  4377. if(!isset($matches[1]) || !isset($matches[2]))
  4378. {
  4379. if($debug) echo "<span title='".htmlencode($query)."' onclick='this.innerHTML=\"".htmlencode(str_replace('"','\"',$query))."\"' style='cursor:pointer'>SQL?</span><br />";
  4380. return false;
  4381. }
  4382. $tablename = str_replace('""','"',$matches[1]);
  4383. $alterdefs = $matches[2];
  4384. if($debug) echo "ALTER TABLE QUERY=(".htmlencode($query)."), tablename=($tablename), alterdefs=($alterdefs)<br />";
  4385. $result = $this->alterTable($tablename, $alterdefs);
  4386. }
  4387. else //this query is normal - proceed as normal
  4388. {
  4389. $result = $this->db->query($query);
  4390. if($debug) echo "<span title='".htmlencode($query)."' onclick='this.innerHTML=\"".htmlencode(str_replace('"','\"',$query))."\"' style='cursor:pointer'>SQL?</span><br />";
  4391. }
  4392. if($result===false)
  4393. return false;
  4394. $this->lastResult = $result;
  4395. return $result;
  4396. }
  4397. //wrapper for an INSERT and returns the ID of the inserted row
  4398. public function insert($query)
  4399. {
  4400. $result = $this->query($query);
  4401. if($this->type=="PDO")
  4402. return $this->db->lastInsertId();
  4403. else if($this->type=="SQLite3")
  4404. return $this->db->lastInsertRowID();
  4405. else if($this->type=="SQLiteDatabase")
  4406. return $this->db->lastInsertRowid();
  4407. }
  4408. //returns an array for SELECT
  4409. public function select($query, $mode="both")
  4410. {
  4411. $result = $this->query($query);
  4412. if(!$result) //make sure the result is valid
  4413. return NULL;
  4414. if($this->type=="PDO")
  4415. {
  4416. if($mode=="assoc")
  4417. $mode = PDO::FETCH_ASSOC;
  4418. else if($mode=="num")
  4419. $mode = PDO::FETCH_NUM;
  4420. else
  4421. $mode = PDO::FETCH_BOTH;
  4422. $ret = $result->fetch($mode);
  4423. $result->closeCursor();
  4424. return $ret;
  4425. }
  4426. else if($this->type=="SQLite3")
  4427. {
  4428. if($mode=="assoc")
  4429. $mode = SQLITE3_ASSOC;
  4430. else if($mode=="num")
  4431. $mode = SQLITE3_NUM;
  4432. else
  4433. $mode = SQLITE3_BOTH;
  4434. $ret = $result->fetchArray($mode);
  4435. $result->finalize();
  4436. return $ret;
  4437. }
  4438. else if($this->type=="SQLiteDatabase")
  4439. {
  4440. if($mode=="assoc")
  4441. $mode = SQLITE_ASSOC;
  4442. else if($mode=="num")
  4443. $mode = SQLITE_NUM;
  4444. else
  4445. $mode = SQLITE_BOTH;
  4446. return $result->fetch($mode);
  4447. }
  4448. }
  4449. //returns an array of arrays after doing a SELECT
  4450. public function selectArray($query, $mode="both")
  4451. {
  4452. $result = $this->query($query);
  4453. //make sure the result is valid
  4454. if($result=== false || $result===NULL)
  4455. return NULL; // error
  4456. if(!is_object($result)) // no rows returned
  4457. return array();
  4458. if($this->type=="PDO")
  4459. {
  4460. if($mode=="assoc")
  4461. $mode = PDO::FETCH_ASSOC;
  4462. else if($mode=="num")
  4463. $mode = PDO::FETCH_NUM;
  4464. else
  4465. $mode = PDO::FETCH_BOTH;
  4466. $ret = $result->fetchAll($mode);
  4467. $result->closeCursor();
  4468. return $ret;
  4469. }
  4470. else if($this->type=="SQLite3")
  4471. {
  4472. if($mode=="assoc")
  4473. $mode = SQLITE3_ASSOC;
  4474. else if($mode=="num")
  4475. $mode = SQLITE3_NUM;
  4476. else
  4477. $mode = SQLITE3_BOTH;
  4478. $arr = array();
  4479. $i = 0;
  4480. while($res = $result->fetchArray($mode))
  4481. {
  4482. $arr[$i] = $res;
  4483. $i++;
  4484. }
  4485. $result->finalize();
  4486. return $arr;
  4487. }
  4488. else if($this->type=="SQLiteDatabase")
  4489. {
  4490. if($mode=="assoc")
  4491. $mode = SQLITE_ASSOC;
  4492. else if($mode=="num")
  4493. $mode = SQLITE_NUM;
  4494. else
  4495. $mode = SQLITE_BOTH;
  4496. return $result->fetchAll($mode);
  4497. }
  4498. }
  4499. //returns an array of the next row in $result
  4500. public function fetch($result, $mode="both")
  4501. {
  4502. //make sure the result is valid
  4503. if($result=== false || $result===NULL)
  4504. return NULL; // error
  4505. if(!is_object($result)) // no rows returned
  4506. return array();
  4507. if($this->type=="PDO")
  4508. {
  4509. if($mode=="assoc")
  4510. $mode = PDO::FETCH_ASSOC;
  4511. else if($mode=="num")
  4512. $mode = PDO::FETCH_NUM;
  4513. else
  4514. $mode = PDO::FETCH_BOTH;
  4515. return $result->fetch($mode);
  4516. }
  4517. else if($this->type=="SQLite3")
  4518. {
  4519. if($mode=="assoc")
  4520. $mode = SQLITE3_ASSOC;
  4521. else if($mode=="num")
  4522. $mode = SQLITE3_NUM;
  4523. else
  4524. $mode = SQLITE3_BOTH;
  4525. return $result->fetchArray($mode);
  4526. }
  4527. else if($this->type=="SQLiteDatabase")
  4528. {
  4529. if($mode=="assoc")
  4530. $mode = SQLITE_ASSOC;
  4531. else if($mode=="num")
  4532. $mode = SQLITE_NUM;
  4533. else
  4534. $mode = SQLITE_BOTH;
  4535. return $result->fetch($mode);
  4536. }
  4537. }
  4538. public function getColumnName($result, $colNum)
  4539. {
  4540. //make sure the result is valid
  4541. if($result=== false || $result===NULL || !is_object($result))
  4542. return ""; // error or no rows returned
  4543. if($this->type=="PDO")
  4544. {
  4545. $meta = $result->getColumnMeta($colNum);
  4546. return $meta['name'];
  4547. }
  4548. else if($this->type=="SQLite3")
  4549. {
  4550. return $result->columnName($colNum);
  4551. }
  4552. else if($this->type=="SQLiteDatabase")
  4553. {
  4554. return $result->fieldName($colNum);
  4555. }
  4556. }
  4557. // SQlite supports multiple ways of surrounding names in quotes:
  4558. // single-quotes, double-quotes, backticks, square brackets.
  4559. // As sqlite does not keep this strict, we also need to be flexible here.
  4560. // This function generates a regex that matches any of the possibilities.
  4561. private function sqlite_surroundings_preg($name,$preg_quote=true,$notAllowedCharsIfNone="'\"",$notAllowedName=false)
  4562. {
  4563. if($name=="*" || $name=="+")
  4564. {
  4565. if($notAllowedName!==false && $preg_quote)
  4566. $notAllowedName = preg_quote($notAllowedName,"/");
  4567. // use possesive quantifiers to save memory
  4568. // (There is a bug in PCRE starting in 8.13 and fixed in PCRE 8.36
  4569. // why we can't use posesive quantifiers - See issue #310).
  4570. if(version_compare(strstr(constant('PCRE_VERSION'), ' ', true), '8.36', '>=') ||
  4571. version_compare(strstr(constant('PCRE_VERSION'), ' ', true), '8.12', '<='))
  4572. $posessive='+';
  4573. else
  4574. $posessive='';
  4575. $nameSingle = ($notAllowedName!==false?"(?!".$notAllowedName."')":"")."(?:[^']$name+|'')$name".$posessive;
  4576. $nameDouble = ($notAllowedName!==false?"(?!".$notAllowedName."\")":"")."(?:[^\"]$name+|\"\")$name".$posessive;
  4577. $nameBacktick = ($notAllowedName!==false?"(?!".$notAllowedName."`)":"")."(?:[^`]$name+|``)$name".$posessive;
  4578. $nameSquare = ($notAllowedName!==false?"(?!".$notAllowedName."\])":"")."(?:[^\]]$name+|\]\])$name".$posessive;
  4579. $nameNo = ($notAllowedName!==false?"(?!".$notAllowedName."\s)":"")."[^".$notAllowedCharsIfNone."]$name";
  4580. }
  4581. else
  4582. {
  4583. if($preg_quote) $name = preg_quote($name,"/");
  4584. $nameSingle = str_replace("'","''",$name);
  4585. $nameDouble = str_replace('"','""',$name);
  4586. $nameBacktick = str_replace('`','``',$name);
  4587. $nameSquare = str_replace(']',']]',$name);
  4588. $nameNo = $name;
  4589. }
  4590. $preg = "(?:'".$nameSingle."'|". // single-quote surrounded or not in quotes (correct SQL for values/new names)
  4591. $nameNo."|". // not surrounded (correct SQL if not containing reserved words, spaces or some special chars)
  4592. "\"".$nameDouble."\"|". // double-quote surrounded (correct SQL for identifiers)
  4593. "`".$nameBacktick."`|". // backtick surrounded (MySQL-Style)
  4594. "\[".$nameSquare."\])"; // square-bracket surrounded (MS Access/SQL server-Style)
  4595. return $preg;
  4596. }
  4597. // Returns the last PREG error as a string, '' if no error occured
  4598. private function getPregError()
  4599. {
  4600. $error = preg_last_error();
  4601. switch ($error)
  4602. {
  4603. case PREG_NO_ERROR: return 'No error';
  4604. case PREG_INTERNAL_ERROR: return 'There is an internal error!';
  4605. case PREG_BACKTRACK_LIMIT_ERROR: return 'Backtrack limit was exhausted!';
  4606. case PREG_RECURSION_LIMIT_ERROR: return 'Recursion limit was exhausted!';
  4607. case PREG_BAD_UTF8_ERROR: return 'Bad UTF8 error!';
  4608. // PREG_BAD_UTF8_OFFSET_ERROR is introduced in PHP 5.3.0, which is not yet required by PLA, so we use its value 5 instead so long
  4609. case 5: return 'Bad UTF8 offset error!';
  4610. default: return 'Unknown Error';
  4611. }
  4612. }
  4613. // function that is called for an alter table statement in a query
  4614. // code borrowed with permission from http://code.jenseng.com/db/
  4615. // this has been completely debugged / rewritten by Christopher Kramer
  4616. public function alterTable($table, $alterdefs)
  4617. {
  4618. global $debug, $lang;
  4619. $this->alterError="";
  4620. $errormsg = sprintf($lang['alter_failed'],htmlencode($table)).' - ';
  4621. if($debug) $this->debugOutput .= "ALTER TABLE: table=($table), alterdefs=($alterdefs), PCRE version=(".PCRE_VERSION.")<hr /><br />";
  4622. if($alterdefs != '')
  4623. {
  4624. $recreateQueries = array();
  4625. $resultArr = $this->selectArray("SELECT sql,name,type FROM sqlite_master WHERE tbl_name = ".$this->quote($table));
  4626. if(sizeof($resultArr)<1)
  4627. {
  4628. $this->alterError = $errormsg . sprintf($lang['tbl_inexistent'], htmlencode($table));
  4629. if($debug) $this->debugOutput .= "ERROR: unknown table<hr /><br />";
  4630. return false;
  4631. }
  4632. for($i=0; $i<sizeof($resultArr); $i++)
  4633. {
  4634. $row = $resultArr[$i];
  4635. if($row['type'] != 'table' && $row['type'] != 'view')
  4636. {
  4637. if($row['sql']!='')
  4638. {
  4639. // store the CREATE statements of triggers and indexes to recreate them later
  4640. $recreateQueries[] = $row;
  4641. if($debug) $this->debugOutput .= "recreate=(".$row['sql'].";)<br />";
  4642. }
  4643. }
  4644. elseif($row['type']=='view') // workaround to rename views
  4645. {
  4646. $origsql = $row['sql'];
  4647. $preg_remove_create_view = "/^\s*+CREATE\s++VIEW\s++".$this->sqlite_surroundings_preg($table)."\s*+(AS\s++SELECT\s++.*+)$/is";
  4648. $origsql_no_create = preg_replace($preg_remove_create_view, '$1', $origsql, 1);
  4649. if($debug) $this->debugOutput .= "origsql=($origsql)<br />preg_remove_create_table=($preg_remove_create_view)<br />";
  4650. preg_match("/RENAME\s++TO\s++(?:\"((?:[^\"]|\"\")+)\"|'((?:[^']|'')+)')/is", $alterdefs, $matches);
  4651. if(isset($matches[1]) && $matches[1]!='')
  4652. $newname = $matches[1];
  4653. elseif(isset($matches[2]) && $matches[2]!='')
  4654. $newname = $matches[2];
  4655. else
  4656. {
  4657. $this->alterError = $errormsg . ' could not detect new view name. It needs to be in single or double quotes.';
  4658. if($debug) $this->debugOutput .= "ERROR: could not detect new view name<hr />";
  4659. return false;
  4660. }
  4661. $dropoldSQL = 'DROP VIEW '.$this->quote_id($table);
  4662. $createnewSQL = 'CREATE VIEW '.$this->quote_id($newname).' '.$origsql_no_create;
  4663. $alter_transaction = 'BEGIN; ' . $dropoldSQL .'; '. $createnewSQL . '; ' . 'COMMIT;';
  4664. if($debug) $this->debugOutput .= $alter_transaction;
  4665. return $this->multiQuery($alter_transaction);
  4666. }
  4667. else
  4668. {
  4669. // ALTER the table
  4670. $tmpname = 't'.time();
  4671. $origsql = $row['sql'];
  4672. $preg_remove_create_table = "/^\s*+CREATE\s++TABLE\s++".$this->sqlite_surroundings_preg($table)."\s*+(\(.*+)$/is";
  4673. $origsql_no_create = preg_replace($preg_remove_create_table, '$1', $origsql, 1);
  4674. if($debug) $this->debugOutput .= "origsql=($origsql)<br />preg_remove_create_table=($preg_remove_create_table)<br />";
  4675. if($origsql_no_create == $origsql)
  4676. {
  4677. $this->alterError = $errormsg . $lang['alter_tbl_name_not_replacable'];
  4678. if($debug) $this->debugOutput .= "ERROR: could not get rid of CREATE TABLE<hr />";
  4679. return false;
  4680. }
  4681. $createtemptableSQL = "CREATE TABLE ".$this->quote($tmpname)." ".$origsql_no_create;
  4682. if($debug) $this->debugOutput .= "createtemptableSQL=($createtemptableSQL)<br />";
  4683. $createindexsql = array();
  4684. $preg_alter_part = "/(?:DROP(?! PRIMARY KEY)|ADD(?! PRIMARY KEY)|CHANGE|RENAME TO|ADD PRIMARY KEY|DROP PRIMARY KEY)" // the ALTER command
  4685. ."(?:"
  4686. ."\s+\(".$this->sqlite_surroundings_preg("+",false,"\"'\[`)")."+\)" // stuff in brackets (in case of ADD PRIMARY KEY)
  4687. ."|" // or
  4688. ."\s+".$this->sqlite_surroundings_preg("+",false,",'\"\[`") // column names and stuff like this
  4689. .")*/i";
  4690. if($debug)
  4691. $this->debugOutput .= "preg_alter_part=(".$preg_alter_part.")<br />";
  4692. preg_match_all($preg_alter_part,$alterdefs,$matches);
  4693. $defs = $matches[0];
  4694. $result_oldcols = $this->getTableInfo($table);
  4695. $newcols = array();
  4696. $coltypes = array();
  4697. $primarykey = array();
  4698. foreach($result_oldcols as $column_info)
  4699. {
  4700. $newcols[$column_info['name']] = $column_info['name'];
  4701. $coltypes[$column_info['name']] = $column_info['type'];
  4702. if($column_info['pk'])
  4703. $primarykey[] = $column_info['name'];
  4704. }
  4705. $newcolumns = '';
  4706. $oldcolumns = '';
  4707. reset($newcols);
  4708. while(list($key, $val) = each($newcols))
  4709. {
  4710. $newcolumns .= ($newcolumns?', ':'').$this->quote_id($val);
  4711. $oldcolumns .= ($oldcolumns?', ':'').$this->quote_id($key);
  4712. }
  4713. $copytotempsql = 'INSERT INTO '.$this->quote_id($tmpname).'('.$newcolumns.') SELECT '.$oldcolumns.' FROM '.$this->quote_id($table);
  4714. $dropoldsql = 'DROP TABLE '.$this->quote_id($table);
  4715. $createtesttableSQL = $createtemptableSQL;
  4716. if(count($defs)<1)
  4717. {
  4718. $this->alterError = $errormsg . $lang['alter_no_def'];
  4719. if($debug) $this->debugOutput .= "ERROR: defs&lt;1<hr /><br />";
  4720. return false;
  4721. }
  4722. foreach($defs as $def)
  4723. {
  4724. if($debug) $this->debugOutput .= "<hr />def=$def<br />";
  4725. $preg_parse_def =
  4726. "/^(DROP(?! PRIMARY KEY)|ADD(?! PRIMARY KEY)|CHANGE|RENAME TO|ADD PRIMARY KEY|DROP PRIMARY KEY)" // $matches[1]: command
  4727. ."(?:" // this is either
  4728. ."(?:\s+\((.+)\)\s*$)" // anything in brackets (for ADD PRIMARY KEY)
  4729. // then $matches[2] is what there is in brackets
  4730. ."|" // OR:
  4731. ."(?:\s+\"((?:[^\"]|\"\")+)\"|\s+'((?:[^']|'')+)')"// (first) column name, either in single or double quotes
  4732. // in case of RENAME TO, it is the new a table name
  4733. // $matches[3] will be the column/table name without the quotes if double quoted
  4734. // $matches[4] will be the column/table name without the quotes if single quoted
  4735. ."(" // $matches[5]: anything after the column name
  4736. ."(?:\s+'((?:[^']|'')+)')?" // $matches[6] (optional): a second column name surrounded with single quotes
  4737. // (the match does not contain the quotes)
  4738. ."\s*"
  4739. ."((?:[A-Z]+\s*)+(?:\(\s*[+-]?\s*[0-9]+(?:\s*,\s*[+-]?\s*[0-9]+)?\s*\))?)?\s*" // $matches[7] (optional): a type name
  4740. .".*".
  4741. ")"
  4742. ."?\s*$"
  4743. .")?\s*$/i"; // in case of DROP PRIMARY KEY, there is nothing after the command
  4744. if($debug) $this->debugOutput .= "preg_parse_def=$preg_parse_def<br />";
  4745. $parse_def = preg_match($preg_parse_def,$def,$matches);
  4746. if($parse_def===false)
  4747. {
  4748. $this->alterError = $errormsg . $lang['alter_parse_failed'];
  4749. if($debug) $this->debugOutput .= "ERROR: !parse_def<hr /><br />";
  4750. return false;
  4751. }
  4752. if(!isset($matches[1]))
  4753. {
  4754. $this->alterError = $errormsg . $lang['alter_action_not_recognized'];
  4755. if($debug) $this->debugOutput .= "ERROR: !isset(matches[1])<hr /><br />";
  4756. return false;
  4757. }
  4758. $action = strtolower($matches[1]);
  4759. if(($action == 'add' || $action == 'rename to') && isset($matches[4]) && $matches[4]!='')
  4760. $column = str_replace("''","'",$matches[4]); // enclosed in ''
  4761. elseif($action == 'add primary key' && isset($matches[2]) && $matches[2]!='')
  4762. $column = $matches[2];
  4763. elseif($action == 'drop primary key')
  4764. $column = ''; // DROP PRIMARY KEY has no column definition
  4765. elseif(isset($matches[3]) && $matches[3]!='')
  4766. $column = str_replace('""','"',$matches[3]); // enclosed in ""
  4767. else
  4768. $column = '';
  4769. $column_escaped = str_replace("'","''",$column);
  4770. if($debug) $this->debugOutput .= "action=($action), column=($column), column_escaped=($column_escaped)<br />";
  4771. /* we build a regex that devides the CREATE TABLE statement parts:
  4772. Part example Group Explanation
  4773. 1. CREATE TABLE t... ( $1
  4774. 2. 'col1' ..., 'col2' ..., 'colN' ..., $3 (with col1-colN being columns that are not changed and listed before the col to change)
  4775. 3. 'colX' ..., (with colX being the column to change/drop)
  4776. 4. 'colX+1' ..., ..., 'colK') $5 (with colX+1-colK being columns after the column to change/drop)
  4777. */
  4778. $preg_create_table = "\s*+(CREATE\s++TABLE\s++".preg_quote($this->quote($tmpname),"/")."\s*+\()"; // This is group $1 (keep unchanged)
  4779. $preg_column_definiton = "\s*+".$this->sqlite_surroundings_preg("+",true," '\"\[`,",$column)."(?:\s*+".$this->sqlite_surroundings_preg("*",false,"'\",`\[ ").")++"; // catches a complete column definition, even if it is
  4780. // 'column' TEXT NOT NULL DEFAULT 'we have a comma, here and a double ''quote!'
  4781. // this definition does NOT match columns with the column name $column
  4782. if($debug) $this->debugOutput .= "preg_column_definition=(".$preg_column_definiton.")<br />";
  4783. $preg_columns_before = // columns before the one changed/dropped (keep)
  4784. "(?:".
  4785. "(". // group $2. Keep this one unchanged!
  4786. "(?:".
  4787. "$preg_column_definiton,\s*+". // column definition + comma
  4788. ")*". // there might be any number of such columns here
  4789. $preg_column_definiton. // last column definition
  4790. ")". // end of group $2
  4791. ",\s*+" // the last comma of the last column before the column to change. Do not keep it!
  4792. .")?"; // there might be no columns before
  4793. if($debug) $this->debugOutput .= "preg_columns_before=(".$preg_columns_before.")<br />";
  4794. $preg_columns_after = "(,\s*(.+))?"; // the columns after the column to drop. This is group $3 (drop) or $4(change) (keep!)
  4795. // we could remove the comma using $6 instead of $5, but then we might have no comma at all.
  4796. // Keeping it leaves a problem if we drop the first column, so we fix that case in another regex.
  4797. $table_new = $table;
  4798. switch($action)
  4799. {
  4800. case 'add':
  4801. if($column=='')
  4802. {
  4803. $this->alterError = $errormsg . ' (add) - '. $lang['alter_no_add_col'];
  4804. return false;
  4805. }
  4806. $new_col_definition = "'$column_escaped' ".(isset($matches[5])?$matches[5]:'');
  4807. $preg_pattern_add = "/^".$preg_create_table. // the CREATE TABLE statement ($1)
  4808. "((?:(?!,\s*(?:PRIMARY\s+KEY\s*\(|CONSTRAINT\s|UNIQUE\s*\(|CHECK\s*\(|FOREIGN\s+KEY\s*\()).)*)". // column definitions ($2)
  4809. "(.*)\\)\s*$/si"; // table-constraints like PRIMARY KEY(a,b) ($3) and the closing bracket
  4810. // append the column definiton in the CREATE TABLE statement
  4811. $newSQL = preg_replace($preg_pattern_add, '$1$2, '.strtr($new_col_definition, array('\\' => '\\\\', '$' => '\$')).' $3', $createtesttableSQL).')';
  4812. $preg_error = $this->getPregError();
  4813. if($debug)
  4814. {
  4815. $this->debugOutput .= $createtesttableSQL."<hr /><br />";
  4816. $this->debugOutput .= $newSQL."<hr /><br />";
  4817. $this->debugOutput .= $preg_pattern_add."<hr /><br />";
  4818. }
  4819. if($newSQL==$createtesttableSQL) // pattern did not match, so column adding did not succed
  4820. {
  4821. $this->alterError = $errormsg . ' (add) - '.$lang['alter_pattern_mismatch'].'. PREG ERROR: '.$preg_error;
  4822. return false;
  4823. }
  4824. $createtesttableSQL = $newSQL;
  4825. break;
  4826. case 'change':
  4827. var_dump($matches);
  4828. if(!isset($matches[6]))
  4829. {
  4830. $this->alterError = $errormsg . ' (change) - '.$lang['alter_col_not_recognized'];
  4831. return false;
  4832. }
  4833. $new_col_name = $matches[6];
  4834. if(!isset($matches[7]))
  4835. $new_col_type = '';
  4836. else
  4837. $new_col_type = $matches[7];
  4838. $new_col_definition = "'$new_col_name' $new_col_type";
  4839. $preg_column_to_change = "\s*".$this->sqlite_surroundings_preg($column)."(?:\s+".preg_quote($coltypes[$column]).")?(\s+(?:".$this->sqlite_surroundings_preg("*",false,",'\"`\[").")+)?";
  4840. // replace this part (we want to change this column)
  4841. // group $3 contains the column constraints (keep!). the name & data type is replaced.
  4842. $preg_pattern_change = "/^".$preg_create_table.$preg_columns_before.$preg_column_to_change.$preg_columns_after."\s*\\)\s*$/s";
  4843. // replace the column definiton in the CREATE TABLE statement
  4844. $newSQL = preg_replace($preg_pattern_change, '$1$2,'.strtr($new_col_definition, array('\\' => '\\\\', '$' => '\$')).'$3$4)', $createtesttableSQL);
  4845. $preg_error = $this->getPregError();
  4846. // remove comma at the beginning if the first column is changed
  4847. // probably somebody is able to put this into the first regex (using lookahead probably).
  4848. $newSQL = preg_replace("/^\s*(CREATE\s+TABLE\s+".preg_quote($this->quote($tmpname),"/")."\s+\(),\s*/",'$1',$newSQL);
  4849. if($debug)
  4850. {
  4851. $this->debugOutput .= "preg_column_to_change=(".$preg_column_to_change.")<hr /><br />";
  4852. $this->debugOutput .= $createtesttableSQL."<hr /><br />";
  4853. $this->debugOutput .= $newSQL."<hr /><br />";
  4854. $this->debugOutput .= $preg_pattern_change."<hr /><br />";
  4855. }
  4856. if($newSQL==$createtesttableSQL || $newSQL=="") // pattern did not match, so column removal did not succed
  4857. {
  4858. $this->alterError = $errormsg . ' (change) - '.$lang['alter_pattern_mismatch'].'. PREG ERROR: '.$preg_error;
  4859. return false;
  4860. }
  4861. $createtesttableSQL = $newSQL;
  4862. $newcols[$column] = str_replace("''","'",$new_col_name);
  4863. break;
  4864. case 'drop':
  4865. $preg_column_to_drop = "\s*".$this->sqlite_surroundings_preg($column)."\s+(?:".$this->sqlite_surroundings_preg("*",false,",'\"\[`").")+"; // delete this part (we want to drop this column)
  4866. $preg_pattern_drop = "/^".$preg_create_table.$preg_columns_before.$preg_column_to_drop.$preg_columns_after."\s*\\)\s*$/s";
  4867. // remove the column out of the CREATE TABLE statement
  4868. $newSQL = preg_replace($preg_pattern_drop, '$1$2$3)', $createtesttableSQL);
  4869. $preg_error = $this->getPregError();
  4870. // remove comma at the beginning if the first column is removed
  4871. // probably somebody is able to put this into the first regex (using lookahead probably).
  4872. $newSQL = preg_replace("/^\s*(CREATE\s+TABLE\s+".preg_quote($this->quote($tmpname),"/")."\s+\(),\s*/",'$1',$newSQL);
  4873. if($debug)
  4874. {
  4875. $this->debugOutput .= $createtesttableSQL."<hr /><br />";
  4876. $this->debugOutput .= $newSQL."<hr /><br />";
  4877. $this->debugOutput .= $preg_pattern_drop."<hr /><br />";
  4878. }
  4879. if($newSQL==$createtesttableSQL || $newSQL=="") // pattern did not match, so column removal did not succed
  4880. {
  4881. $this->alterError = $errormsg . ' (drop) - '.$lang['alter_pattern_mismatch'].'. PREG ERROR: '.$preg_error;
  4882. return false;
  4883. }
  4884. $createtesttableSQL = $newSQL;
  4885. unset($newcols[$column]);
  4886. break;
  4887. case 'rename to':
  4888. // don't change column definition at all
  4889. $newSQL = $createtesttableSQL;
  4890. // only change the name of the table
  4891. $table_new = $column;
  4892. break;
  4893. case 'add primary key':
  4894. // we want to add a primary key for the column(s) stored in $column
  4895. $newSQL = preg_replace("/\)\s*$/", ", PRIMARY KEY (".$column.") )", $createtesttableSQL);
  4896. $createtesttableSQL = $newSQL;
  4897. break;
  4898. case 'drop primary key':
  4899. // we want to drop the primary key
  4900. if($debug) $this->debugOutput .= "DROP";
  4901. if(sizeof($primarykey)==1)
  4902. {
  4903. // if not compound primary key, might be a column constraint -> try removal
  4904. $column = $primarykey[0];
  4905. if($debug) $this->debugOutput .= "<br>Trying to drop column constraint for column $column <br>";
  4906. /*
  4907. TODO: This does not work yet:
  4908. CREATE TABLE 't12' ('t1' INTEGER CONSTRAINT "bla" NOT NULL CONSTRAINT 'pk' PRIMARY KEY ); ALTER TABLE "t12" DROP PRIMARY KEY
  4909. This does: ! !
  4910. CREATE TABLE 't12' ('t1' INTEGER CONSTRAINT bla NOT NULL CONSTRAINT 'pk' PRIMARY KEY ); ALTER TABLE "t12" DROP PRIMARY KEY
  4911. */
  4912. $preg_column_to_change = "(\s*".$this->sqlite_surroundings_preg($column).")". // column ($3)
  4913. "(?:". // opt. type and column constraints
  4914. "(\s+(?:".$this->sqlite_surroundings_preg("(?:[^PC,'\"`\[]|P(?!RIMARY\s+KEY)|".
  4915. "C(?!ONSTRAINT\s+".$this->sqlite_surroundings_preg("+",false," ,'\"\[`")."\s+PRIMARY\s+KEY))",false,",'\"`\[").")*)". // column constraints before PRIMARY KEY ($3)
  4916. // primary key constraint (remove this!):
  4917. "(?:CONSTRAINT\s+".$this->sqlite_surroundings_preg("+",false," ,'\"\[`")."\s+)?".
  4918. "PRIMARY\s+KEY".
  4919. "(?:\s+(?:ASC|DESC))?".
  4920. "(?:\s+ON\s+CONFLICT\s+(?:ROLLBACK|ABORT|FAIL|IGNORE|REPLACE))?".
  4921. "(?:\s+AUTOINCREMENT)?".
  4922. "((?:".$this->sqlite_surroundings_preg("*",false,",'\"`\[").")*)". // column constraints after PRIMARY KEY ($4)
  4923. ")";
  4924. // replace this part (we want to change this column)
  4925. // group $3 (column) $4 (constraints before) and $5 (constraints after) contain the part to keep
  4926. $preg_pattern_change = "/^".$preg_create_table.$preg_columns_before.$preg_column_to_change.$preg_columns_after."\s*\\)\s*$/si";
  4927. // replace the column definiton in the CREATE TABLE statement
  4928. $newSQL = preg_replace($preg_pattern_change, '$1$2,$3$4$5$6)', $createtesttableSQL);
  4929. // remove comma at the beginning if the first column is changed
  4930. // probably somebody is able to put this into the first regex (using lookahead probably).
  4931. $newSQL = preg_replace("/^\s*(CREATE\s+TABLE\s+".preg_quote($this->quote($tmpname),"/")."\s+\(),\s*/",'$1',$newSQL);
  4932. if($debug)
  4933. {
  4934. $this->debugOutput .= "preg_column_to_change=(".$preg_column_to_change.")<hr /><br />";
  4935. $this->debugOutput .= $createtesttableSQL."<hr /><br />";
  4936. $this->debugOutput .= $newSQL."<hr /><br />";
  4937. $this->debugOutput .= $preg_pattern_change."<hr /><br />";
  4938. }
  4939. if($newSQL!=$createtesttableSQL && $newSQL!="") // pattern did match, so PRIMARY KEY constraint removed :)
  4940. {
  4941. $createtesttableSQL = $newSQL;
  4942. if($debug) $this->debugOutput .= "<br>SUCCEEDED<br>";
  4943. }
  4944. else
  4945. {
  4946. if($debug) $this->debugOutput .= "NO LUCK";
  4947. // TODO: try removing table constraint
  4948. return false;
  4949. }
  4950. $createtesttableSQL = $newSQL;
  4951. } else
  4952. // TODO: Try removing table constraint
  4953. return false;
  4954. break;
  4955. default:
  4956. if($debug) $this->debugOutput .= 'ERROR: unknown alter operation!<hr /><br />';
  4957. $this->alterError = $errormsg . $lang['alter_unknown_operation'];
  4958. return false;
  4959. }
  4960. }
  4961. $droptempsql = 'DROP TABLE '.$this->quote_id($tmpname);
  4962. $createnewtableSQL = "CREATE TABLE ".$this->quote($table_new)." ".preg_replace("/^\s*CREATE\s+TABLE\s+'?".str_replace("'","''",preg_quote($tmpname,"/"))."'?\s+(.*)$/is", '$1', $createtesttableSQL, 1);
  4963. $newcolumns = '';
  4964. $oldcolumns = '';
  4965. reset($newcols);
  4966. while(list($key,$val) = each($newcols))
  4967. {
  4968. $newcolumns .= ($newcolumns?', ':'').$this->quote_id($val);
  4969. $oldcolumns .= ($oldcolumns?', ':'').$this->quote_id($key);
  4970. }
  4971. $copytonewsql = 'INSERT INTO '.$this->quote_id($table_new).'('.$newcolumns.') SELECT '.$oldcolumns.' FROM '.$this->quote_id($tmpname);
  4972. }
  4973. }
  4974. $alter_transaction = 'BEGIN; ';
  4975. $alter_transaction .= $createtemptableSQL.'; '; //create temp table
  4976. $alter_transaction .= $copytotempsql.'; '; //copy to table
  4977. $alter_transaction .= $dropoldsql.'; '; //drop old table
  4978. $alter_transaction .= $createnewtableSQL.'; '; //recreate original table
  4979. $alter_transaction .= $copytonewsql.'; '; //copy back to original table
  4980. $alter_transaction .= $droptempsql.'; '; //drop temp table
  4981. $preg_index="/^\s*(CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?:".$this->sqlite_surroundings_preg("+",false," '\"\[`")."\s*)*ON\s+)(".$this->sqlite_surroundings_preg($table).")(\s*\((?:".$this->sqlite_surroundings_preg("+",false," '\"\[`")."\s*)*\)\s*)\s*$/i";
  4982. foreach($recreateQueries as $recreate_query)
  4983. {
  4984. if($recreate_query['type']=='index')
  4985. {
  4986. // this is an index. We need to make sure the index is not on a column that we drop. If it is, we drop the index as well.
  4987. $indexInfos = $this->selectArray('PRAGMA index_info('.$this->quote_id($recreate_query['name']).')');
  4988. foreach($indexInfos as $indexInfo)
  4989. {
  4990. if(!isset($newcols[$indexInfo['name']]))
  4991. {
  4992. if($debug) $this->debugOutput .= 'Not recreating the following index: <hr /><br />'.htmlencode($recreate_query['sql']).'<hr /><br />';
  4993. // Index on a column that was dropped. Skip recreation.
  4994. continue 2;
  4995. }
  4996. }
  4997. }
  4998. // TODO: In case we renamed a column on which there is an index, we need to recreate the index with the column name adjusted.
  4999. // recreate triggers / indexes
  5000. if($table == $table_new)
  5001. {
  5002. // we had no RENAME TO, so we can recreate indexes/triggers just like the original ones
  5003. $alter_transaction .= $recreate_query['sql'].';';
  5004. } else
  5005. {
  5006. // we had a RENAME TO, so we need to exchange the table-name in the CREATE-SQL of triggers & indexes
  5007. switch ($recreate_query['type'])
  5008. {
  5009. case 'index':
  5010. $recreate_queryIndex = preg_replace($preg_index, '$1'.$this->quote_id(strtr($table_new, array('\\' => '\\\\', '$' => '\$'))).'$3 ', $recreate_query['sql']);
  5011. if($recreate_queryIndex!=$recreate_query['sql'] && $recreate_queryIndex != NULL)
  5012. $alter_transaction .= $recreate_queryIndex.';';
  5013. else
  5014. {
  5015. // the CREATE INDEX regex did not match. this normally should not happen
  5016. if($debug) $this->debugOutput .= 'ERROR: CREATE INDEX regex did not match!?<hr /><br />';
  5017. // just try to recreate the index originally (will fail most likely)
  5018. $alter_transaction .= $recreate_query['sql'].';';
  5019. }
  5020. break;
  5021. case 'trigger':
  5022. // TODO: IMPLEMENT
  5023. $alter_transaction .= $recreate_query['sql'].';';
  5024. break;
  5025. default:
  5026. if($debug) $this->debugOutput .= 'ERROR: Unknown type '.htmlencode($recreate_query['type']).'<hr /><br />';
  5027. $alter_transaction .= $recreate_query['sql'].';';
  5028. }
  5029. }
  5030. }
  5031. $alter_transaction .= 'COMMIT;';
  5032. if($debug) $this->debugOutput .= $alter_transaction;
  5033. return $this->multiQuery($alter_transaction);
  5034. }
  5035. }
  5036. //multiple query execution
  5037. //returns true on success, false otherwise. Use getError() to fetch the error.
  5038. public function multiQuery($query)
  5039. {
  5040. if($this->type=="PDO")
  5041. $success = $this->db->exec($query);
  5042. else if($this->type=="SQLite3")
  5043. $success = $this->db->exec($query);
  5044. else
  5045. $success = $this->db->queryExec($query, $error);
  5046. return $success;
  5047. }
  5048. // checks whether a table has a primary key
  5049. public function hasPrimaryKey($table)
  5050. {
  5051. $table_info = $this->getTableInfo($table);
  5052. foreach($table_info as $row_id => $row_data)
  5053. {
  5054. if($row_data['pk'])
  5055. {
  5056. return true;
  5057. }
  5058. }
  5059. return false;
  5060. }
  5061. // Returns an array of columns by which rows can be uniquely adressed.
  5062. // For tables with a rowid column, this is always array('rowid')
  5063. // for tables without rowid, this is an array of the primary key columns.
  5064. public function getPrimaryKey($table)
  5065. {
  5066. $primary_key = array();
  5067. // check if this table has a rowid
  5068. $getRowID = $this->select('SELECT ROWID FROM '.$this->quote_id($table).' LIMIT 0,1');
  5069. if(isset($getRowID[0]))
  5070. // it has, so we prefer addressing rows by rowid
  5071. return array('rowid');
  5072. else
  5073. {
  5074. // the table is without rowid, so use the primary key
  5075. $table_info = $this->getTableInfo($table);
  5076. if(is_array($table_info))
  5077. {
  5078. foreach($table_info as $row_id => $row_data)
  5079. {
  5080. if($row_data['pk'])
  5081. $primary_key[] = $row_data['name'];
  5082. }
  5083. }
  5084. }
  5085. return $primary_key;
  5086. }
  5087. // selects a row by a given key $pk, which is an array of values
  5088. // for the columns by which a row can be adressed (rowid or primary key)
  5089. public function wherePK($table, $pk)
  5090. {
  5091. $where = "";
  5092. $primary_key = $this->getPrimaryKey($table);
  5093. foreach($primary_key as $pk_index => $column)
  5094. {
  5095. if($where!="")
  5096. $where .= " AND ";
  5097. $where .= $this->quote_id($column) . ' = ';
  5098. if(is_int($pk[$pk_index]) || is_float($pk[$pk_index]))
  5099. $where .= $pk[$pk_index];
  5100. else
  5101. $where .= $this->quote($pk[$pk_index]);
  5102. }
  5103. return $where;
  5104. }
  5105. //get number of rows in table
  5106. public function numRows($table, $dontTakeLong = false)
  5107. {
  5108. // as Count(*) can be slow on huge tables without PK,
  5109. // if $dontTakeLong is set and the size is > 2MB only count() if there is a PK
  5110. if(!$dontTakeLong || $this->getSize() <= 2000 || $this->hasPrimaryKey($table))
  5111. {
  5112. $result = $this->select("SELECT Count(*) FROM ".$this->quote_id($table));
  5113. return $result[0];
  5114. } else
  5115. {
  5116. return '?';
  5117. }
  5118. }
  5119. //correctly escape a string to be injected into an SQL query
  5120. public function quote($value)
  5121. {
  5122. if($this->type=="PDO")
  5123. {
  5124. // PDO quote() escapes and adds quotes
  5125. return $this->db->quote($value);
  5126. }
  5127. else if($this->type=="SQLite3")
  5128. {
  5129. return "'".$this->db->escapeString($value)."'";
  5130. }
  5131. else
  5132. {
  5133. return "'".sqlite_escape_string($value)."'";
  5134. }
  5135. }
  5136. //correctly escape an identifier (column / table / trigger / index name) to be injected into an SQL query
  5137. public function quote_id($value)
  5138. {
  5139. // double-quotes need to be escaped by doubling them
  5140. $value = str_replace('"','""',$value);
  5141. return '"'.$value.'"';
  5142. }
  5143. //import sql
  5144. //returns true on success, error message otherwise
  5145. public function import_sql($query)
  5146. {
  5147. $import = $this->multiQuery($query);
  5148. if(!$import)
  5149. return $this->getError();
  5150. else
  5151. return true;
  5152. }
  5153. public function prepareQuery($query)
  5154. {
  5155. if($this->type=='PDO' || $this->type=='SQLite3')
  5156. return $this->db->prepare($query);
  5157. else
  5158. {
  5159. // here we are in trouble, SQLiteDatabase cannot prepare statements.
  5160. // we need to emulate prepare as best as we can
  5161. # todo: implement this
  5162. return null;
  5163. }
  5164. }
  5165. public function bindValue($handle, $parameter, $value, $type)
  5166. {
  5167. if($this->type=='SQLite3')
  5168. {
  5169. $types = array(
  5170. 'bool'=>SQLITE3_INTEGER,
  5171. 'int'=>SQLITE3_INTEGER,
  5172. 'float'=>SQLITE3_FLOAT,
  5173. 'text'=>SQLITE3_TEXT,
  5174. 'blob'=>SQLITE3_BLOB,
  5175. 'null'=>SQLITE3_NULL);
  5176. if(!isset($types[$type]))
  5177. $type = 'text';
  5178. // there is no SQLITE_BOOL, so check value and make sure it is 0/1
  5179. if($type=='bool')
  5180. {
  5181. if($value===1 || $value===true)
  5182. $value=1;
  5183. elseif($value===0 || $value===false)
  5184. $value=0;
  5185. else
  5186. return false;
  5187. }
  5188. return $handle->bindValue($parameter, $value, $types[$type]);
  5189. }
  5190. if($this->type=='PDO')
  5191. {
  5192. $types = array(
  5193. 'bool'=>PDO::PARAM_BOOL,
  5194. 'int'=>PDO::PARAM_INT,
  5195. 'float'=>PDO::PARAM_STR,
  5196. 'text'=>PDO::PARAM_STR,
  5197. 'blob'=>PDO::PARAM_LOB,
  5198. 'null'=>PDO::PARAM_NULL);
  5199. if(!isset($types[$type]))
  5200. $type = 'text';
  5201. // there is no PDO::PARAM_FLOAT, so we check it ourself
  5202. if($type=='float')
  5203. {
  5204. if(is_numeric($value))
  5205. $value = (float) $value;
  5206. else
  5207. return false;
  5208. }
  5209. return $handle->bindValue($parameter, $value, $types[$type]);
  5210. }
  5211. else
  5212. # todo: workaround
  5213. return false;
  5214. }
  5215. public function executePrepared($handle, $fetchResult=false)
  5216. {
  5217. if($this->type=='PDO')
  5218. {
  5219. $ok=$handle->execute();
  5220. if($fetchResult && $ok)
  5221. {
  5222. $res = $handle->fetchAll();
  5223. $handle->closeCursor();
  5224. return $res;
  5225. }
  5226. else
  5227. {
  5228. if($ok)
  5229. $handle->closeCursor();
  5230. return $ok;
  5231. }
  5232. }
  5233. elseif($this->type=='SQLite3')
  5234. {
  5235. $resultset=$handle->execute();
  5236. if($fetchResult && $resultset!==false)
  5237. {
  5238. $res = $resultset->fetchArray();
  5239. $resultset->finalize();
  5240. return $res;
  5241. }
  5242. else
  5243. {
  5244. if($resultset!==false)
  5245. $resultset->finalize();
  5246. if($resultset===false)
  5247. return false;
  5248. else
  5249. return true;
  5250. }
  5251. }
  5252. else
  5253. {
  5254. #todo.
  5255. return false;
  5256. }
  5257. }
  5258. //import csv
  5259. //returns true on success, error message otherwise
  5260. public function import_csv($filename, $table, $field_terminate, $field_enclosed, $field_escaped, $null, $fields_in_first_row)
  5261. {
  5262. @set_time_limit(-1);
  5263. $csv_handle = fopen($filename,'r');
  5264. $csv_insert = "BEGIN;\n";
  5265. $csv_number_of_rows = 0;
  5266. // PHP requires enclosure defined, but has no problem if it was not used
  5267. if($field_enclosed=="") $field_enclosed='"';
  5268. // PHP requires escaper defined
  5269. if($field_escaped=="") $field_escaped='\\';
  5270. // support tab delimiters
  5271. if($field_terminate=='\t') $field_terminate = "\t";
  5272. while($csv_handle!==false && !feof($csv_handle))
  5273. {
  5274. $csv_data = fgetcsv($csv_handle, 0, $field_terminate, $field_enclosed, $field_escaped);
  5275. if(is_array($csv_data) && ($csv_data[0] != NULL || count($csv_data)>1))
  5276. {
  5277. $csv_number_of_rows++;
  5278. if($csv_number_of_rows==1)
  5279. {
  5280. if($this->getTypeOfTable($table)!="table")
  5281. {
  5282. // First,Create a new table
  5283. $csv_insert .="CREATE TABLE ".$this->quote($table)." (";
  5284. $number_of_cols = count($csv_data);
  5285. foreach($csv_data as $csv_col => $csv_cell)
  5286. {
  5287. if($fields_in_first_row)
  5288. $csv_insert .= $this->quote($csv_cell);
  5289. else
  5290. $csv_insert.= $this->quote("col{$csv_col}");
  5291. if($csv_col < $number_of_cols-1)
  5292. $csv_insert .= ", ";
  5293. }
  5294. $csv_insert .=");";
  5295. } else {
  5296. $number_of_cols = count($this->getTableInfo($table));
  5297. }
  5298. if($fields_in_first_row)
  5299. continue;
  5300. }
  5301. $csv_insert .= "INSERT INTO ".$this->quote_id($table)." VALUES (";
  5302. for($csv_col = 0; $csv_col < $number_of_cols; $csv_col++)
  5303. {
  5304. if(isset($csv_data[$csv_col]))
  5305. $csv_cell = $csv_data[$csv_col];
  5306. else
  5307. $csv_cell = $null;
  5308. if($csv_cell == $null)
  5309. $csv_insert .= "NULL";
  5310. else
  5311. $csv_insert.= $this->quote($csv_cell);
  5312. if($csv_col < $number_of_cols-1)
  5313. $csv_insert .= ",";
  5314. }
  5315. $csv_insert .= ");\n";
  5316. if($csv_number_of_rows % 5000 == 0)
  5317. {
  5318. $csv_insert .= "COMMIT;\nBEGIN;\n";
  5319. }
  5320. }
  5321. }
  5322. if($csv_handle === false)
  5323. return "Error reading CSV file";
  5324. else
  5325. {
  5326. $csv_insert .= "COMMIT;";
  5327. fclose($csv_handle);
  5328. $import = $this->multiQuery($csv_insert);
  5329. if(!$import)
  5330. return $this->getError();
  5331. else
  5332. return true;
  5333. }
  5334. }
  5335. //export csv
  5336. public function export_csv($tables, $field_terminate, $field_enclosed, $field_escaped, $null, $crlf, $fields_in_first_row)
  5337. {
  5338. @set_time_limit(-1);
  5339. // we use \r\n if the _client_ OS is windows (as the exported file is downloaded to the client), \n otherwise
  5340. $crlf = (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Win')!==false ? "\r\n" : "\n");
  5341. $query = "SELECT * FROM sqlite_master WHERE type='table' or type='view' ORDER BY type DESC";
  5342. $result = $this->selectArray($query);
  5343. for($i=0; $i<sizeof($result); $i++)
  5344. {
  5345. $valid = false;
  5346. for($j=0; $j<sizeof($tables); $j++)
  5347. {
  5348. if($result[$i]['tbl_name']==$tables[$j])
  5349. $valid = true;
  5350. }
  5351. if($valid)
  5352. {
  5353. $temp = $this->getTableInfo($result[$i]['tbl_name']);
  5354. $cols = array();
  5355. for($z=0; $z<sizeof($temp); $z++)
  5356. $cols[$z] = $temp[$z][1];
  5357. if($fields_in_first_row)
  5358. {
  5359. for($z=0; $z<sizeof($cols); $z++)
  5360. {
  5361. echo $field_enclosed.$cols[$z].$field_enclosed;
  5362. // do not terminate the last column!
  5363. if($z < sizeof($cols)-1)
  5364. echo $field_terminate;
  5365. }
  5366. echo $crlf;
  5367. }
  5368. $query = "SELECT * FROM ".$this->quote_id($result[$i]['tbl_name']);
  5369. $table_result = $this->query($query);
  5370. $firstRow=true;
  5371. while($row = $this->fetch($table_result, "assoc"))
  5372. {
  5373. if(!$firstRow)
  5374. echo $crlf;
  5375. else
  5376. $firstRow=false;
  5377. for($y=0; $y<sizeof($cols); $y++)
  5378. {
  5379. $cell = $row[$cols[$y]];
  5380. if($crlf)
  5381. {
  5382. $cell = str_replace("\n","", $cell);
  5383. $cell = str_replace("\r","", $cell);
  5384. }
  5385. $cell = str_replace($field_terminate,$field_escaped.$field_terminate,$cell);
  5386. $cell = str_replace($field_enclosed,$field_escaped.$field_enclosed,$cell);
  5387. // do not enclose NULLs
  5388. if($cell == NULL)
  5389. echo $null;
  5390. else
  5391. echo $field_enclosed.$cell.$field_enclosed;
  5392. // do not terminate the last column!
  5393. if($y < sizeof($cols)-1)
  5394. echo $field_terminate;
  5395. }
  5396. }
  5397. if($i<sizeof($result)-1)
  5398. echo $crlf;
  5399. }
  5400. }
  5401. }
  5402. //export sql
  5403. public function export_sql($tables, $drop, $structure, $data, $transaction, $comments)
  5404. {
  5405. global $lang;
  5406. @set_time_limit(-1);
  5407. // we use \r\n if the _client_ OS is windows (as the exported file is downloaded to the client), \n otherwise
  5408. $crlf = (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Win')!==false ? "\r\n" : "\n");
  5409. if($comments)
  5410. {
  5411. echo "----".$crlf;
  5412. echo "-- ".PROJECT." ".$lang['db_dump']." (".PROJECT_URL.")".$crlf;
  5413. echo "-- ".PROJECT." ".$lang['ver'].": ".VERSION.$crlf;
  5414. echo "-- ".$lang['exported'].": ".date($lang['date_format']).$crlf;
  5415. echo "-- ".$lang['db_f'].": ".$this->getPath().$crlf;
  5416. echo "----".$crlf;
  5417. }
  5418. $query = "SELECT * FROM sqlite_master WHERE type='table' OR type='index' OR type='view' OR type='trigger' ORDER BY type='trigger', type='index', type='view', type='table'";
  5419. $result = $this->selectArray($query);
  5420. if($transaction)
  5421. echo "BEGIN TRANSACTION;".$crlf;
  5422. //iterate through each table
  5423. for($i=0; $i<sizeof($result); $i++)
  5424. {
  5425. $valid = false;
  5426. for($j=0; $j<sizeof($tables); $j++)
  5427. {
  5428. if($result[$i]['tbl_name']==$tables[$j])
  5429. $valid = true;
  5430. }
  5431. if($valid)
  5432. {
  5433. if($drop)
  5434. {
  5435. if($comments)
  5436. {
  5437. echo "\r\n----".$crlf;
  5438. echo "-- ".$lang['drop']." ".$result[$i]['type']." ".$lang['for']." ".$result[$i]['name'].$crlf;
  5439. echo "----".$crlf;
  5440. }
  5441. echo "DROP ".strtoupper($result[$i]['type'])." IF EXISTS ".$this->quote_id($result[$i]['name']).";".$crlf;
  5442. }
  5443. if($structure)
  5444. {
  5445. if($comments)
  5446. {
  5447. echo "\r\n----".$crlf;
  5448. if($result[$i]['type']=="table" || $result[$i]['type']=="view")
  5449. echo "-- ".ucfirst($result[$i]['type'])." ".$lang['struct_for']." ".$result[$i]['tbl_name'].$crlf;
  5450. else // index or trigger
  5451. echo "-- ".$lang['struct_for']." ".$result[$i]['type']." ".$result[$i]['name']." ".$lang['on_tbl']." ".$result[$i]['tbl_name'].$crlf;
  5452. echo "----".$crlf;
  5453. }
  5454. echo $result[$i]['sql'].";".$crlf;
  5455. }
  5456. if($data && $result[$i]['type']=="table")
  5457. {
  5458. $query = "SELECT * FROM ".$this->quote_id($result[$i]['tbl_name']);
  5459. $table_result = $this->query($query, "assoc");
  5460. if($comments)
  5461. {
  5462. $numRows = $this->numRows($result[$i]['tbl_name']);
  5463. echo "\r\n----".$crlf;
  5464. echo "-- ".$lang['data_dump']." ".$result[$i]['tbl_name'].", ".sprintf($lang['total_rows'], $numRows).$crlf;
  5465. echo "----".$crlf;
  5466. }
  5467. $temp = $this->getTableInfo($result[$i]['tbl_name']);
  5468. $cols = array();
  5469. $cols_quoted = array();
  5470. for($z=0; $z<sizeof($temp); $z++)
  5471. {
  5472. $cols[$z] = $temp[$z][1];
  5473. $cols_quoted[$z] = $this->quote_id($temp[$z][1]);
  5474. }
  5475. while($row = $this->fetch($table_result))
  5476. {
  5477. $vals = array();
  5478. for($y=0; $y<sizeof($cols); $y++)
  5479. {
  5480. if($row[$cols[$y]] === NULL)
  5481. $vals[$cols[$y]] = 'NULL';
  5482. else
  5483. $vals[$cols[$y]] = $this->quote($row[$cols[$y]]);
  5484. }
  5485. echo "INSERT INTO ".$this->quote_id($result[$i]['tbl_name'])." (".implode(",", $cols_quoted).") VALUES (".implode(",", $vals).");".$crlf;
  5486. }
  5487. }
  5488. }
  5489. }
  5490. if($transaction)
  5491. echo "COMMIT;".$crlf;
  5492. }
  5493. }
  5494. class GetParameters
  5495. {
  5496. private $_fields;
  5497. public function __construct(array $defaults = array())
  5498. {
  5499. $this->_fields = $defaults;
  5500. }
  5501. public function __set($key, $value)
  5502. {
  5503. $this->_fields[$key] = $value;
  5504. }
  5505. public function __isset($key)
  5506. {
  5507. return isset($this->_fields[$key]);
  5508. }
  5509. public function __unset($key)
  5510. {
  5511. unset($this->_fields[$key]);
  5512. }
  5513. public function __get($key)
  5514. {
  5515. return $this->_fields[$key];
  5516. }
  5517. public function getURL(array $assoc = array(), $html = true, $prefix='?')
  5518. {
  5519. $arg_sep = ($html?'&amp;':'&');
  5520. return $prefix . http_build_query(array_merge($this->_fields, $assoc), '', $arg_sep);
  5521. }
  5522. public function getLink(array $assoc = array(), $content = '[ link ]', $class = '', $title = '', $target='')
  5523. {
  5524. return '<a href="' . $this->getURL($assoc) . '"'
  5525. . ($class != '' ? ' class="' . $class . '"' : '')
  5526. . ($title != '' ? ' title="' . $title . '"' : '')
  5527. . ($target != '' ? ' target="' . $target . '"' : '')
  5528. . '>' . $content . '</a>';
  5529. }
  5530. public function getForm(array $assoc = array(), $method = 'post', $upload = false, $name = '', $csrf = true)
  5531. {
  5532. $hidden = '';
  5533. if($method == 'get')
  5534. {
  5535. $url = '';
  5536. foreach(array_merge($this->_fields, $assoc) as $key => $value)
  5537. {
  5538. if(!is_null($value))
  5539. $hidden .= '<input type="hidden" name="'.htmlencode($key).'" value="'.htmlencode($value).'" /> ';
  5540. }
  5541. }
  5542. else
  5543. $url = $this->getURL($assoc);
  5544. if($csrf && $method == 'post')
  5545. $hidden .= '<input type="hidden" name="token" value="'.$_SESSION[COOKIENAME.'token'].'" />';
  5546. return "<form action='". $url ."' method='" . $method . "'" .
  5547. ($name!=''? " name='". $name ."'" : '') .
  5548. ($upload? " enctype='multipart/form-data'" : '') . ">" .
  5549. $hidden;
  5550. }
  5551. public function redirect(array $assoc = array(), $message="")
  5552. {
  5553. if($message!="")
  5554. {
  5555. $_SESSION[COOKIENAME.'messages'][md5($message)] = $message;
  5556. $url = $this->getURL(array_merge($assoc, array('message'=>md5($message))), false);
  5557. }
  5558. else
  5559. $url = $this->getURL($assoc, false);
  5560. $protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http');
  5561. header("Location: ".$protocol."://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$url, true, 302);
  5562. exit;
  5563. }
  5564. }// class MicroTimer (issue #146)
  5565. // wraps calls to microtime(), calculating the elapsed time and rounding output
  5566. //
  5567. class MicroTimer {
  5568. private $startTime, $stopTime;
  5569. // creates and starts a timer
  5570. function __construct()
  5571. {
  5572. $this->startTime = microtime(true);
  5573. }
  5574. // stops a timer
  5575. public function stop()
  5576. {
  5577. $this->stopTime = microtime(true);
  5578. }
  5579. // returns the number of seconds from the timer's creation, or elapsed
  5580. // between creation and call to ->stop()
  5581. public function elapsed()
  5582. {
  5583. if ($this->stopTime)
  5584. return round($this->stopTime - $this->startTime, 4);
  5585. return round(microtime(true) - $this->startTime, 4);
  5586. }
  5587. // called when using a MicroTimer object as a string
  5588. public function __toString()
  5589. {
  5590. return (string) $this->elapsed();
  5591. }
  5592. }
  5593. // class Resources (issue #157)
  5594. // outputs secondary files, such as css and javascript
  5595. // data is stored gzipped (gzencode) and encoded (base64_encode)
  5596. //
  5597. class Resources {
  5598. // set this to the file containing getInternalResource;
  5599. // currently unused in split mode; set to __FILE__ for built PLA.
  5600. public static $embedding_file = __FILE__;
  5601. private static $_resources = array(
  5602. 'css' => array(
  5603. 'mime' => 'text/css',
  5604. 'data' => 'resources/phpliteadmin.css',
  5605. ),
  5606. 'javascript' => array(
  5607. 'mime' => 'text/javascript',
  5608. 'data' => 'resources/phpliteadmin.js',
  5609. ),
  5610. 'favicon' => array(
  5611. 'mime' => 'image/x-icon',
  5612. 'data' => 'resources/favicon.ico',
  5613. 'base64' => 'true',
  5614. ),
  5615. );
  5616. // outputs the specified resource, if defined in this class.
  5617. // the main script should do no further output after calling this function.
  5618. public static function output($resource)
  5619. {
  5620. if (isset(self::$_resources[$resource])) {
  5621. $res =& self::$_resources[$resource];
  5622. if (function_exists('getInternalResource') && $data = getInternalResource($res['data'])) {
  5623. $filename = self::$embedding_file;
  5624. } else {
  5625. $filename = $res['data'];
  5626. }
  5627. // use last-modified time as etag; etag must be quoted
  5628. $etag = '"' . filemtime($filename) . '"';
  5629. // check headers for matching etag; if etag hasn't changed, use the cached version
  5630. if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
  5631. header('HTTP/1.0 304 Not Modified');
  5632. return;
  5633. }
  5634. header('Etag: ' . $etag);
  5635. // cache file for at most 30 days
  5636. header('Cache-control: max-age=2592000');
  5637. // output resource
  5638. header('Content-type: ' . $res['mime']);
  5639. if (isset($data)) {
  5640. if (isset($res['base64'])) {
  5641. echo base64_decode($data);
  5642. } else {
  5643. echo $data;
  5644. }
  5645. } else {
  5646. readfile($filename);
  5647. }
  5648. }
  5649. }
  5650. }
  5651. // returns data from internal resources, available in single-file mode
  5652. function getInternalResource($res) {
  5653. $resources = array('resources/phpliteadmin.css'=>array(0=>0,1=>4059,),'resources/phpliteadmin.js'=>array(0=>4059,1=>4542,),'resources/favicon.ico'=>array(0=>8601,1=>1448,),);
  5654. if (isset($resources[$res]) && $f = fopen(__FILE__, 'r')) {
  5655. fseek($f, __COMPILER_HALT_OFFSET__ + $resources[$res][0]);
  5656. $data = fread($f, $resources[$res][1]);
  5657. fclose($f);
  5658. return $data;
  5659. }
  5660. return false;
  5661. }
  5662. // resources embedded below, do not edit!
  5663. __halt_compiler() ?>body{margin:0px;padding:0px;font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#000;background-color:#e0ebf6;overflow:auto}.body_tbl td{padding:9px 2px 9px 9px}.left_td{width:100px}a{color:#03F;text-decoration:none;cursor:pointer}a:hover{color:#06F}hr{height:1px;border:0;color:#bbb;background-color:#bbb;width:100%}h1{margin:0px;padding:5px;font-size:24px;background-color:#f3cece;text-align:center;color:#000;border-top-left-radius:5px;border-top-right-radius:5px;-moz-border-radius-topleft:5px;-moz-border-radius-topright:5px}#headerlinks{text-align:center;margin-bottom:10px;padding:5px 15px;border-color:#03F;border-width:1px;border-style:solid;border-left-style:none;border-right-style:none;font-size:12px;background-color:#e0ebf6;font-weight:bold}h1 #version{color:#000;font-size:16px}h1 #logo{color:#000}h2{margin:0px;padding:0px;font-size:14px;margin-bottom:20px}input,select,textarea,.CodeMirror{font-family:Arial,Helvetica,sans-serif;background-color:#eaeaea;color:#03F;border-color:#03F;border-style:solid;border-width:1px;margin:5px;border-radius:5px;-moz-border-radius:5px;padding:3px}input.btn{cursor:pointer}input.btn:hover{background-color:#ccc}fieldset label{min-width:200px;display:block;float:left}fieldset{padding:15px;border-color:#03F;border-width:1px;border-style:solid;border-radius:5px;-moz-border-radius:5px;background-color:#f9f9f9}#container{padding:10px}#leftNav{min-width:250px;padding:0px;border-color:#03F;border-width:1px;border-style:solid;background-color:#FFF;padding-bottom:15px;border-radius:5px;-moz-border-radius:5px}.databaseList select{max-width:200px}.viewTable tr td{padding:1px}#loginBox{width:500px;margin-left:auto;margin-right:auto;margin-top:50px;border-color:#03F;border-width:1px;border-style:solid;background-color:#FFF;border-radius:5px;-moz-border-radius:5px}#main{border-color:#03F;border-width:1px;border-style:solid;padding:15px;background-color:#FFF;border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top-right-radius:5px;-moz-border-radius-bottomleft:5px;-moz-border-radius-bottomright:5px;-moz-border-radius-topright:5px}.td1{background-color:#f9e3e3;text-align:right;font-size:12px;padding-left:10px;padding-right:10px}.td2{background-color:#f3cece;text-align:right;font-size:12px;padding-left:10px;padding-right:10px}.tdheader{border-color:#03F;border-width:1px;border-style:solid;font-weight:bold;font-size:12px;padding-left:10px;padding-right:10px;background-color:#e0ebf6;border-radius:5px;-moz-border-radius:5px}.confirm{border-color:#03F;border-width:1px;border-style:dashed;padding:15px;background-color:#e0ebf6}.tab{display:block;padding:5px;padding-right:8px;padding-left:8px;border-color:#03F;border-width:1px;border-style:solid;margin-right:5px;float:left;border-bottom-style:none;position:relative;top:1px;padding-bottom:4px;background-color:#eaeaea;border-top-left-radius:5px;border-top-right-radius:5px;-moz-border-radius-topleft:5px;-moz-border-radius-topright:5px}.tab_pressed{display:block;padding:5px;padding-right:8px;padding-left:8px;border-color:#03F;border-width:1px;border-style:solid;margin-right:5px;float:left;border-bottom-style:none;position:relative;top:1px;background-color:#FFF;cursor:default;border-top-left-radius:5px;border-top-right-radius:5px;-moz-border-radius-topleft:5px;-moz-border-radius-topright:5px}.helpq{font-size:11px;font-weight:normal}#help_container{padding:0px;font-size:12px;margin-left:auto;margin-right:auto;background-color:#fff}.help_outer{background-color:#FFF;padding:0px;height:300px;position:relative}.help_list{padding:10px;height:auto}.headd{font-size:14px;font-weight:bold;display:block;padding:10px;background-color:#e0ebf6;border-color:#03F;border-width:1px;border-style:solid;border-left-style:none;border-right-style:none}.help_inner{padding:10px}.help_top{display:block;position:absolute;right:10px;bottom:10px}.warning,.delete,.empty,.drop,.delete_db{color:red}.sidebar_table{font-size:11px}.active_table,.active_db{text-decoration:underline}.null{color:#888}.found{background:#FF0;text-decoration:none}
  5664. function initAutoincrement()
  5665. {var i=0;while(document.getElementById('i'+i+'_autoincrement')!=undefined)
  5666. {document.getElementById('i'+i+'_autoincrement').disabled=true;i++;}}
  5667. function toggleAutoincrement(i)
  5668. {var type=document.getElementById('i'+i+'_type');var primarykey=document.getElementById('i'+i+'_primarykey');var autoincrement=document.getElementById('i'+i+'_autoincrement');if(!autoincrement)return false;if(type.value=='INTEGER'&&primarykey.checked)
  5669. autoincrement.disabled=false;else
  5670. {autoincrement.disabled=true;autoincrement.checked=false;}}
  5671. function toggleNull(i)
  5672. {var pk=document.getElementById('i'+i+'_primarykey');var notnull=document.getElementById('i'+i+'_notnull');if(pk.checked)
  5673. {notnull.disabled=true;notnull.checked=true;}
  5674. else
  5675. {notnull.disabled=false;}}
  5676. function checkAll(field)
  5677. {var i=0;while(document.getElementById('check_'+i)!=undefined)
  5678. {document.getElementById('check_'+i).checked=true;i++;}}
  5679. function uncheckAll(field)
  5680. {var i=0;while(document.getElementById('check_'+i)!=undefined)
  5681. {document.getElementById('check_'+i).checked=false;i++;}}
  5682. function changeIgnore(area,e,u)
  5683. {if(area.value!="")
  5684. {if(document.getElementById(e)!=undefined)
  5685. document.getElementById(e).checked=false;if(document.getElementById(u)!=undefined)
  5686. document.getElementById(u).checked=false;}}
  5687. function moveFields()
  5688. {var fields=document.getElementById("fieldcontainer");var selected=[];for(var i=0;i<fields.options.length;i++)
  5689. if(fields.options[i].selected)
  5690. selected.push(fields.options[i].value);for(var i=0;i<selected.length;i++)
  5691. {var val='"'+selected[i].replace(/"/g,'""')+'"';if(i<selected.length-1)
  5692. val+=', ';sqleditorInsertValue(val);}}
  5693. function notNull(checker)
  5694. {document.getElementById(checker).checked=false;}
  5695. function disableText(checker,textie)
  5696. {if(checker.checked)
  5697. {document.getElementById(textie).value="";document.getElementById(textie).disabled=true;}
  5698. else
  5699. {document.getElementById(textie).disabled=false;}}
  5700. function toggleExports(val)
  5701. {document.getElementById("exportoptions_sql").style.display="none";document.getElementById("exportoptions_csv").style.display="none";document.getElementById("exportoptions_"+val).style.display="block";}
  5702. function toggleImports(val)
  5703. {document.getElementById("importoptions_sql").style.display="none";document.getElementById("importoptions_csv").style.display="none";document.getElementById("importoptions_"+val).style.display="block";}
  5704. function openHelp(section)
  5705. {PopupCenter('?help=1#'+section,"Help Section");}
  5706. var helpsec=false;function PopupCenter(pageURL,title)
  5707. {helpsec=window.open(pageURL,title,"toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=400,height=300");}
  5708. function checkLike(srchField,selOpt)
  5709. {if(selOpt=="LIKE%"){var textArea=document.getElementById(srchField);textArea.value="%"+textArea.value+"%";}}
  5710. function createCORSRequest(method,url)
  5711. {var xhr=new XMLHttpRequest();if("withCredentials"in xhr)
  5712. {xhr.open(method,url,true);}
  5713. else if(typeof XDomainRequest!="undefined")
  5714. {xhr=new XDomainRequest();xhr.open(method,url);}
  5715. else
  5716. {xhr=null;}
  5717. return xhr;}
  5718. function checkVersion(installed,url)
  5719. {var xhr=createCORSRequest('GET',url);if(!xhr)
  5720. return false;xhr.onload=function()
  5721. {if(xhr.responseText.split("\n").indexOf(installed)==-1)
  5722. {document.getElementById('oldVersion').style.display='inline';}};xhr.send();}
  5723. var codeEditor;function sqleditor(textarea,tableDefinitions,tableDefault)
  5724. {codeEditor=CodeMirror.fromTextArea(textarea,{lineNumbers:true,matchBrackets:true,indentUnit:4,lineWrapping:true,mode:"text/x-sqlite",extraKeys:{"Ctrl-Space":"autocomplete"},hint:CodeMirror.hint.sql,hintOptions:{completeSingle:false,completeOnSingleClick:true,defaultTable:tableDefault,tables:tableDefinitions}});codeEditor.on("inputRead",codemirrorAutocompleteOnInputRead);}
  5725. function sqleditorSetValue(text)
  5726. {codeEditor.doc.setValue(text);}
  5727. function sqleditorInsertValue(text)
  5728. {codeEditor.doc.replaceRange(text,codeEditor.doc.getCursor("from"),codeEditor.doc.getCursor("to"));}
  5729. function codemirrorAutocompleteOnInputRead(instance){if(instance.state.completionActive){return;}
  5730. var cur=instance.getCursor();var token=instance.getTokenAt(cur);var string='';if(token.string.match(/^[.`"\w@]\w*$/))
  5731. {string=token.string;}
  5732. if(string.length>0){CodeMirror.commands.autocomplete(instance);}}
  5733. function checkFileSize(input)
  5734. {if(input.files&&input.files.length==1)
  5735. {if(input.files[0].size>fileUploadMaxSize)
  5736. {alert(fileUploadMaxSizeErrorMsg+": "+(fileUploadMaxSize/1024/1024)+" MiB");return false;}}
  5737. return true;}AAABAAEAEBAAAAEAIAAoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwoKZQAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEMDJMAAAAdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASDg7BAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAETDw9CCQkJ1QUFBb4AAABjAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgsLVgAAAO8YExP/AAAA7QAAALEAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQNDUsAAADJGBMT/xgTE/8AAAD/AAAAuAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZERE8DQoKwhgTE/8QDQ2sGBMT/xgTE/8AAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwICHkAAAD/EQwMzQAAAMIAAAD/AAAA7gAAAGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOCwtWAAAA8RgTE/8IBQW1AAAA/wAAAP8AAADlAAAAHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0KCsEAAAD/EQ8PzAAAAMkAAAD/AAAA/wAAAHoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDAAAA/xgTE/8TDw/FAAAA8gAAAP8AAADqAAAAJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAALUAAAD/GBMT/wAAALkAAAD/AAAA/wAAAIkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfAAAA4wAAAP8GBgbFAAAA2QAAAP8AAADGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF4AAAD5AAAA/RgTE/8AAAD/AAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQAAAOIAAAD/AAAA/wAAAHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjAAAArgAAAG4AAAAAAAAAAAAAAAAAAAAA