server_privileges.lib.php 143 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * set of functions with the Privileges section in pma
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. * Get Html for User Group Dialog
  13. *
  14. * @param string $username username
  15. * @param bool $is_menuswork Is menuswork set in configuration
  16. *
  17. * @return string html
  18. */
  19. function PMA_getHtmlForUserGroupDialog($username, $is_menuswork)
  20. {
  21. $html = '';
  22. if (! empty($_REQUEST['edit_user_group_dialog']) && $is_menuswork) {
  23. $dialog = PMA_getHtmlToChooseUserGroup($username);
  24. $response = PMA_Response::getInstance();
  25. if ($GLOBALS['is_ajax_request']) {
  26. $response->addJSON('message', $dialog);
  27. exit;
  28. } else {
  29. $html .= $dialog;
  30. }
  31. }
  32. return $html;
  33. }
  34. /**
  35. * Escapes wildcard in a database+table specification
  36. * before using it in a GRANT statement.
  37. *
  38. * Escaping a wildcard character in a GRANT is only accepted at the global
  39. * or database level, not at table level; this is why I remove
  40. * the escaping character. Internally, in mysql.tables_priv.Db there are
  41. * no escaping (for example test_db) but in mysql.db you'll see test\_db
  42. * for a db-specific privilege.
  43. *
  44. * @param string $dbname Database name
  45. * @param string $tablename Table name
  46. *
  47. * @return string the escaped (if necessary) database.table
  48. */
  49. function PMA_wildcardEscapeForGrant($dbname, $tablename)
  50. {
  51. if (! strlen($dbname)) {
  52. $db_and_table = '*.*';
  53. } else {
  54. if (strlen($tablename)) {
  55. $db_and_table = PMA_Util::backquote(
  56. PMA_Util::unescapeMysqlWildcards($dbname)
  57. )
  58. . '.' . PMA_Util::backquote($tablename);
  59. } else {
  60. $db_and_table = PMA_Util::backquote($dbname) . '.*';
  61. }
  62. }
  63. return $db_and_table;
  64. }
  65. /**
  66. * Generates a condition on the user name
  67. *
  68. * @param string $initial the user's initial
  69. *
  70. * @return string the generated condition
  71. */
  72. function PMA_rangeOfUsers($initial = '')
  73. {
  74. // strtolower() is used because the User field
  75. // might be BINARY, so LIKE would be case sensitive
  76. if (! empty($initial)) {
  77. $ret = " WHERE `User` LIKE '"
  78. . PMA_Util::sqlAddSlashes($initial, true) . "%'"
  79. . " OR `User` LIKE '"
  80. . PMA_Util::sqlAddSlashes(strtolower($initial), true) . "%'";
  81. } else {
  82. $ret = '';
  83. }
  84. return $ret;
  85. } // end function
  86. /**
  87. * Extracts the privilege information of a priv table row
  88. *
  89. * @param array $row the row
  90. * @param boolean $enableHTML add <dfn> tag with tooltips
  91. * @param boolean $tablePrivs whether row contains table privileges
  92. *
  93. * @global resource $user_link the database connection
  94. *
  95. * @return array
  96. */
  97. function PMA_extractPrivInfo($row = '', $enableHTML = false, $tablePrivs = false)
  98. {
  99. if ($tablePrivs) {
  100. $grants = PMA_getTableGrantsArray();
  101. } else {
  102. $grants = PMA_getGrantsArray();
  103. }
  104. if (! empty($row) && isset($row['Table_priv'])) {
  105. $row1 = $GLOBALS['dbi']->fetchSingleRow(
  106. 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
  107. 'ASSOC', $GLOBALS['userlink']
  108. );
  109. $av_grants = explode(
  110. '\',\'',
  111. substr($row1['Type'], 5, strlen($row1['Type']) - 7)
  112. );
  113. unset($row1);
  114. $users_grants = explode(',', $row['Table_priv']);
  115. foreach ($av_grants as $current_grant) {
  116. $row[$current_grant . '_priv']
  117. = in_array($current_grant, $users_grants) ? 'Y' : 'N';
  118. }
  119. unset($current_grant);
  120. }
  121. $privs = array();
  122. $allPrivileges = true;
  123. foreach ($grants as $current_grant) {
  124. if ((! empty($row) && isset($row[$current_grant[0]]))
  125. || (empty($row) && isset($GLOBALS[$current_grant[0]]))
  126. ) {
  127. if ((! empty($row) && $row[$current_grant[0]] == 'Y')
  128. || (empty($row)
  129. && ($GLOBALS[$current_grant[0]] == 'Y'
  130. || (is_array($GLOBALS[$current_grant[0]])
  131. && count($GLOBALS[$current_grant[0]]) == $_REQUEST['column_count']
  132. && empty($GLOBALS[$current_grant[0] . '_none']))))
  133. ) {
  134. if ($enableHTML) {
  135. $privs[] = '<dfn title="' . $current_grant[2] . '">'
  136. . $current_grant[1] . '</dfn>';
  137. } else {
  138. $privs[] = $current_grant[1];
  139. }
  140. } elseif (! empty($GLOBALS[$current_grant[0]])
  141. && is_array($GLOBALS[$current_grant[0]])
  142. && empty($GLOBALS[$current_grant[0] . '_none'])
  143. ) {
  144. if ($enableHTML) {
  145. $priv_string = '<dfn title="' . $current_grant[2] . '">'
  146. . $current_grant[1] . '</dfn>';
  147. } else {
  148. $priv_string = $current_grant[1];
  149. }
  150. $privs[] = $priv_string . ' (`'
  151. . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
  152. } else {
  153. $allPrivileges = false;
  154. }
  155. }
  156. }
  157. if (empty($privs)) {
  158. if ($enableHTML) {
  159. $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
  160. } else {
  161. $privs[] = 'USAGE';
  162. }
  163. } elseif ($allPrivileges
  164. && (! isset($_POST['grant_count']) || count($privs) == $_POST['grant_count'])
  165. ) {
  166. if ($enableHTML) {
  167. $privs = array('<dfn title="'
  168. . __('Includes all privileges except GRANT.')
  169. . '">ALL PRIVILEGES</dfn>'
  170. );
  171. } else {
  172. $privs = array('ALL PRIVILEGES');
  173. }
  174. }
  175. return $privs;
  176. } // end of the 'PMA_extractPrivInfo()' function
  177. /**
  178. * Returns an array of table grants and their descriptions
  179. *
  180. * @return array array of table grants
  181. */
  182. function PMA_getTableGrantsArray()
  183. {
  184. return array(
  185. array(
  186. 'Delete',
  187. 'DELETE',
  188. $GLOBALS['strPrivDescDelete']
  189. ),
  190. array(
  191. 'Create',
  192. 'CREATE',
  193. $GLOBALS['strPrivDescCreateTbl']
  194. ),
  195. array(
  196. 'Drop',
  197. 'DROP',
  198. $GLOBALS['strPrivDescDropTbl']
  199. ),
  200. array(
  201. 'Index',
  202. 'INDEX',
  203. $GLOBALS['strPrivDescIndex']
  204. ),
  205. array(
  206. 'Alter',
  207. 'ALTER',
  208. $GLOBALS['strPrivDescAlter']
  209. ),
  210. array(
  211. 'Create View',
  212. 'CREATE_VIEW',
  213. $GLOBALS['strPrivDescCreateView']
  214. ),
  215. array(
  216. 'Show view',
  217. 'SHOW_VIEW',
  218. $GLOBALS['strPrivDescShowView']
  219. ),
  220. array(
  221. 'Trigger',
  222. 'TRIGGER',
  223. $GLOBALS['strPrivDescTrigger']
  224. ),
  225. );
  226. }
  227. /**
  228. * Get the grants array which contains all the privilege types
  229. * and relevent grant messages
  230. *
  231. * @return array
  232. */
  233. function PMA_getGrantsArray()
  234. {
  235. return array(
  236. array(
  237. 'Select_priv',
  238. 'SELECT',
  239. __('Allows reading data.')
  240. ),
  241. array(
  242. 'Insert_priv',
  243. 'INSERT',
  244. __('Allows inserting and replacing data.')
  245. ),
  246. array(
  247. 'Update_priv',
  248. 'UPDATE',
  249. __('Allows changing data.')
  250. ),
  251. array(
  252. 'Delete_priv',
  253. 'DELETE',
  254. __('Allows deleting data.')
  255. ),
  256. array(
  257. 'Create_priv',
  258. 'CREATE',
  259. __('Allows creating new databases and tables.')
  260. ),
  261. array(
  262. 'Drop_priv',
  263. 'DROP',
  264. __('Allows dropping databases and tables.')
  265. ),
  266. array(
  267. 'Reload_priv',
  268. 'RELOAD',
  269. __('Allows reloading server settings and flushing the server\'s caches.')
  270. ),
  271. array(
  272. 'Shutdown_priv',
  273. 'SHUTDOWN',
  274. __('Allows shutting down the server.')
  275. ),
  276. array(
  277. 'Process_priv',
  278. 'PROCESS',
  279. __('Allows viewing processes of all users.')
  280. ),
  281. array(
  282. 'File_priv',
  283. 'FILE',
  284. __('Allows importing data from and exporting data into files.')
  285. ),
  286. array(
  287. 'References_priv',
  288. 'REFERENCES',
  289. __('Has no effect in this MySQL version.')
  290. ),
  291. array(
  292. 'Index_priv',
  293. 'INDEX',
  294. __('Allows creating and dropping indexes.')
  295. ),
  296. array(
  297. 'Alter_priv',
  298. 'ALTER',
  299. __('Allows altering the structure of existing tables.')
  300. ),
  301. array(
  302. 'Show_db_priv',
  303. 'SHOW DATABASES',
  304. __('Gives access to the complete list of databases.')
  305. ),
  306. array(
  307. 'Super_priv',
  308. 'SUPER',
  309. __(
  310. 'Allows connecting, even if maximum number of connections '
  311. . 'is reached; required for most administrative operations '
  312. . 'like setting global variables or killing threads of other users.'
  313. )
  314. ),
  315. array(
  316. 'Create_tmp_table_priv',
  317. 'CREATE TEMPORARY TABLES',
  318. __('Allows creating temporary tables.')
  319. ),
  320. array(
  321. 'Lock_tables_priv',
  322. 'LOCK TABLES',
  323. __('Allows locking tables for the current thread.')
  324. ),
  325. array(
  326. 'Repl_slave_priv',
  327. 'REPLICATION SLAVE',
  328. __('Needed for the replication slaves.')
  329. ),
  330. array(
  331. 'Repl_client_priv',
  332. 'REPLICATION CLIENT',
  333. __('Allows the user to ask where the slaves / masters are.')
  334. ),
  335. array(
  336. 'Create_view_priv',
  337. 'CREATE VIEW',
  338. __('Allows creating new views.')
  339. ),
  340. array(
  341. 'Event_priv',
  342. 'EVENT',
  343. __('Allows to set up events for the event scheduler.')
  344. ),
  345. array(
  346. 'Trigger_priv',
  347. 'TRIGGER',
  348. __('Allows creating and dropping triggers.')
  349. ),
  350. // for table privs:
  351. array(
  352. 'Create View_priv',
  353. 'CREATE VIEW',
  354. __('Allows creating new views.')
  355. ),
  356. array(
  357. 'Show_view_priv',
  358. 'SHOW VIEW',
  359. __('Allows performing SHOW CREATE VIEW queries.')
  360. ),
  361. // for table privs:
  362. array(
  363. 'Show view_priv',
  364. 'SHOW VIEW',
  365. __('Allows performing SHOW CREATE VIEW queries.')
  366. ),
  367. array(
  368. 'Create_routine_priv',
  369. 'CREATE ROUTINE',
  370. __('Allows creating stored routines.')
  371. ),
  372. array(
  373. 'Alter_routine_priv',
  374. 'ALTER ROUTINE',
  375. __('Allows altering and dropping stored routines.')
  376. ),
  377. array(
  378. 'Create_user_priv',
  379. 'CREATE USER',
  380. __('Allows creating, dropping and renaming user accounts.')
  381. ),
  382. array(
  383. 'Execute_priv',
  384. 'EXECUTE',
  385. __('Allows executing stored routines.')
  386. ),
  387. );
  388. }
  389. /**
  390. * Displays on which column(s) a table-specific privilege is granted
  391. *
  392. * @param array $columns columns array
  393. * @param array $row first row from result or boolean false
  394. * @param string $name_for_select privilege types - Select_priv, Insert_priv
  395. * Update_priv, References_priv
  396. * @param string $priv_for_header privilege for header
  397. * @param string $name privilege name: insert, select, update, references
  398. * @param string $name_for_dfn name for dfn
  399. * @param string $name_for_current name for current
  400. *
  401. * @return string $html_output html snippet
  402. */
  403. function PMA_getHtmlForColumnPrivileges($columns, $row, $name_for_select,
  404. $priv_for_header, $name, $name_for_dfn, $name_for_current
  405. ) {
  406. $html_output = '<div class="item" id="div_item_' . $name . '">' . "\n"
  407. . '<label for="select_' . $name . '_priv">' . "\n"
  408. . '<code><dfn title="' . $name_for_dfn . '">'
  409. . $priv_for_header . '</dfn></code>' . "\n"
  410. . '</label><br />' . "\n"
  411. . '<select id="select_' . $name . '_priv" name="'
  412. . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
  413. foreach ($columns as $currCol => $currColPrivs) {
  414. $html_output .= '<option '
  415. . 'value="' . htmlspecialchars($currCol) . '"';
  416. if ($row[$name_for_select] == 'Y'
  417. || $currColPrivs[$name_for_current]
  418. ) {
  419. $html_output .= ' selected="selected"';
  420. }
  421. $html_output .= '>'
  422. . htmlspecialchars($currCol) . '</option>' . "\n";
  423. }
  424. $html_output .= '</select>' . "\n"
  425. . '<i>' . __('Or') . '</i>' . "\n"
  426. . '<label for="checkbox_' . $name_for_select
  427. . '_none"><input type="checkbox"'
  428. . ' name="' . $name_for_select . '_none" id="checkbox_'
  429. . $name_for_select . '_none" title="'
  430. . _pgettext('None privileges', 'None') . '" />'
  431. . _pgettext('None privileges', 'None') . '</label>' . "\n"
  432. . '</div>' . "\n";
  433. return $html_output;
  434. } // end function
  435. /**
  436. * Get sql query for display privileges table
  437. *
  438. * @param string $db the database
  439. * @param string $table the table
  440. * @param string $username username for database connection
  441. * @param string $hostname hostname for database connection
  442. *
  443. * @return string sql query
  444. */
  445. function PMA_getSqlQueryForDisplayPrivTable($db, $table, $username, $hostname)
  446. {
  447. if ($db == '*') {
  448. return "SELECT * FROM `mysql`.`user`"
  449. . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  450. . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
  451. } elseif ($table == '*') {
  452. return "SELECT * FROM `mysql`.`db`"
  453. . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  454. . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "'"
  455. . " AND '" . PMA_Util::unescapeMysqlWildcards($db) . "'"
  456. . " LIKE `Db`;";
  457. }
  458. return "SELECT `Table_priv`"
  459. . " FROM `mysql`.`tables_priv`"
  460. . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  461. . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "'"
  462. . " AND `Db` = '" . PMA_Util::unescapeMysqlWildcards($db) . "'"
  463. . " AND `Table_name` = '" . PMA_Util::sqlAddSlashes($table) . "';";
  464. }
  465. /**
  466. * Displays a dropdown to select the user group
  467. * with menu items configured to each of them.
  468. *
  469. * @param string $username username
  470. *
  471. * @return string html to select the user group
  472. */
  473. function PMA_getHtmlToChooseUserGroup($username)
  474. {
  475. $html_output = '<form class="ajax" id="changeUserGroupForm"'
  476. . ' action="server_privileges.php" method="post">';
  477. $params = array('username' => $username);
  478. $html_output .= PMA_URL_getHiddenInputs($params);
  479. $html_output .= '<fieldset id="fieldset_user_group_selection">';
  480. $html_output .= '<legend>' . __('User group') . '</legend>';
  481. $groupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
  482. . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']);
  483. $userTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
  484. . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']);
  485. $userGroups = array();
  486. $sql_query = "SELECT DISTINCT `usergroup` FROM " . $groupTable;
  487. $result = PMA_queryAsControlUser($sql_query, false);
  488. if ($result) {
  489. while ($row = $GLOBALS['dbi']->fetchRow($result)) {
  490. $userGroups[] = $row[0];
  491. }
  492. }
  493. $GLOBALS['dbi']->freeResult($result);
  494. $userGroup = '';
  495. if (isset($GLOBALS['username'])) {
  496. $sql_query = "SELECT `usergroup` FROM " . $userTable
  497. . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
  498. $userGroup = $GLOBALS['dbi']->fetchValue(
  499. $sql_query, 0, 0, $GLOBALS['controllink']
  500. );
  501. }
  502. $html_output .= __('User group') . ': ';
  503. $html_output .= '<select name="userGroup">';
  504. $html_output .= '<option value=""></option>';
  505. foreach ($userGroups as $oneUserGroup) {
  506. $html_output .= '<option value="' . htmlspecialchars($oneUserGroup) . '"'
  507. . ($oneUserGroup == $userGroup ? ' selected="selected"' : '')
  508. . '>'
  509. . htmlspecialchars($oneUserGroup)
  510. . '</option>';
  511. }
  512. $html_output .= '</select>';
  513. $html_output .= '<input type="hidden" name="changeUserGroup" value="1">';
  514. $html_output .= '</fieldset>';
  515. $html_output .= '</form>';
  516. return $html_output;
  517. }
  518. /**
  519. * Sets the user group from request values
  520. *
  521. * @param string $username username
  522. * @param string $userGroup user group to set
  523. *
  524. * @return void
  525. */
  526. function PMA_setUserGroup($username, $userGroup)
  527. {
  528. $userTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
  529. . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']);
  530. $sql_query = "SELECT `usergroup` FROM " . $userTable
  531. . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
  532. $oldUserGroup = $GLOBALS['dbi']->fetchValue(
  533. $sql_query, 0, 0, $GLOBALS['controllink']
  534. );
  535. if ($oldUserGroup === false) {
  536. $upd_query = "INSERT INTO " . $userTable . "(`username`, `usergroup`)"
  537. . " VALUES ('" . PMA_Util::sqlAddSlashes($username) . "', "
  538. . "'" . PMA_Util::sqlAddSlashes($userGroup) . "')";
  539. } else {
  540. if (empty($userGroup)) {
  541. $upd_query = "DELETE FROM " . $userTable
  542. . " WHERE `username`='" . PMA_Util::sqlAddSlashes($username) . "'";
  543. } elseif ($oldUserGroup != $userGroup) {
  544. $upd_query = "UPDATE " . $userTable
  545. . " SET `usergroup`='" . PMA_Util::sqlAddSlashes($userGroup) . "'"
  546. . " WHERE `username`='" . PMA_Util::sqlAddSlashes($username) . "'";
  547. }
  548. }
  549. if (isset($upd_query)) {
  550. PMA_queryAsControlUser($upd_query);
  551. }
  552. }
  553. /**
  554. * Displays the privileges form table
  555. *
  556. * @param string $db the database
  557. * @param string $table the table
  558. * @param boolean $submit whether to display the submit button or not
  559. *
  560. * @global array $cfg the phpMyAdmin configuration
  561. * @global ressource $user_link the database connection
  562. *
  563. * @return string html snippet
  564. */
  565. function PMA_getHtmlToDisplayPrivilegesTable($db = '*',
  566. $table = '*', $submit = true
  567. ) {
  568. $html_output = '';
  569. if ($db == '*') {
  570. $table = '*';
  571. }
  572. if (isset($GLOBALS['username'])) {
  573. $username = $GLOBALS['username'];
  574. $hostname = $GLOBALS['hostname'];
  575. $sql_query = PMA_getSqlQueryForDisplayPrivTable(
  576. $db, $table, $username, $hostname
  577. );
  578. $row = $GLOBALS['dbi']->fetchSingleRow($sql_query);
  579. }
  580. if (empty($row)) {
  581. if ($table == '*') {
  582. if ($db == '*') {
  583. $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
  584. } elseif ($table == '*') {
  585. $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
  586. }
  587. $res = $GLOBALS['dbi']->query($sql_query);
  588. while ($row1 = $GLOBALS['dbi']->fetchRow($res)) {
  589. if (substr($row1[0], 0, 4) == 'max_') {
  590. $row[$row1[0]] = 0;
  591. } else {
  592. $row[$row1[0]] = 'N';
  593. }
  594. }
  595. $GLOBALS['dbi']->freeResult($res);
  596. } else {
  597. $row = array('Table_priv' => '');
  598. }
  599. }
  600. if (isset($row['Table_priv'])) {
  601. $row1 = $GLOBALS['dbi']->fetchSingleRow(
  602. 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
  603. 'ASSOC', $GLOBALS['userlink']
  604. );
  605. // note: in MySQL 5.0.3 we get "Create View', 'Show view';
  606. // the View for Create is spelled with uppercase V
  607. // the view for Show is spelled with lowercase v
  608. // and there is a space between the words
  609. $av_grants = explode(
  610. '\',\'',
  611. substr(
  612. $row1['Type'],
  613. strpos($row1['Type'], '(') + 2,
  614. strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3
  615. )
  616. );
  617. unset($row1);
  618. $users_grants = explode(',', $row['Table_priv']);
  619. foreach ($av_grants as $current_grant) {
  620. $row[$current_grant . '_priv']
  621. = in_array($current_grant, $users_grants) ? 'Y' : 'N';
  622. }
  623. unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
  624. // get columns
  625. $res = $GLOBALS['dbi']->tryQuery(
  626. 'SHOW COLUMNS FROM '
  627. . PMA_Util::backquote(
  628. PMA_Util::unescapeMysqlWildcards($db)
  629. )
  630. . '.' . PMA_Util::backquote($table) . ';'
  631. );
  632. $columns = array();
  633. if ($res) {
  634. while ($row1 = $GLOBALS['dbi']->fetchRow($res)) {
  635. $columns[$row1[0]] = array(
  636. 'Select' => false,
  637. 'Insert' => false,
  638. 'Update' => false,
  639. 'References' => false
  640. );
  641. }
  642. $GLOBALS['dbi']->freeResult($res);
  643. }
  644. unset($res, $row1);
  645. }
  646. // table-specific privileges
  647. if (! empty($columns)) {
  648. $html_output .= PMA_getHtmlForTableSpecificPrivileges(
  649. $username, $hostname, $db, $table, $columns, $row
  650. );
  651. } else {
  652. // global or db-specific
  653. $html_output .= PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row);
  654. }
  655. $html_output .= '</fieldset>' . "\n";
  656. if ($submit) {
  657. $html_output .= '<fieldset id="fieldset_user_privtable_footer" '
  658. . 'class="tblFooters">' . "\n"
  659. . '<input type="submit" name="update_privs" '
  660. . 'value="' . __('Go') . '" />' . "\n"
  661. . '</fieldset>' . "\n";
  662. }
  663. return $html_output;
  664. } // end of the 'PMA_displayPrivTable()' function
  665. /**
  666. * Get HTML for "Resource limits"
  667. *
  668. * @param array $row first row from result or boolean false
  669. *
  670. * @return string html snippet
  671. */
  672. function PMA_getHtmlForResourceLimits($row)
  673. {
  674. $html_output = '<fieldset>' . "\n"
  675. . '<legend>' . __('Resource limits') . '</legend>' . "\n"
  676. . '<p><small>'
  677. . '<i>' . __('Note: Setting these options to 0 (zero) removes the limit.')
  678. . '</i></small></p>' . "\n";
  679. $html_output .= '<div class="item">' . "\n"
  680. . '<label for="text_max_questions">'
  681. . '<code><dfn title="'
  682. . __(
  683. 'Limits the number of queries the user may send to the server per hour.'
  684. )
  685. . '">'
  686. . 'MAX QUERIES PER HOUR'
  687. . '</dfn></code></label>' . "\n"
  688. . '<input type="number" name="max_questions" id="text_max_questions" '
  689. . 'value="' . $row['max_questions'] . '" min="0" '
  690. . 'title="'
  691. . __(
  692. 'Limits the number of queries the user may send to the server per hour.'
  693. )
  694. . '" />' . "\n"
  695. . '</div>' . "\n";
  696. $html_output .= '<div class="item">' . "\n"
  697. . '<label for="text_max_updates">'
  698. . '<code><dfn title="'
  699. . __(
  700. 'Limits the number of commands that change any table '
  701. . 'or database the user may execute per hour.'
  702. ) . '">'
  703. . 'MAX UPDATES PER HOUR'
  704. . '</dfn></code></label>' . "\n"
  705. . '<input type="number" name="max_updates" id="text_max_updates" '
  706. . 'value="' . $row['max_updates'] . '" min="0" '
  707. . 'title="'
  708. . __(
  709. 'Limits the number of commands that change any table '
  710. . 'or database the user may execute per hour.'
  711. )
  712. . '" />' . "\n"
  713. . '</div>' . "\n";
  714. $html_output .= '<div class="item">' . "\n"
  715. . '<label for="text_max_connections">'
  716. . '<code><dfn title="'
  717. . __(
  718. 'Limits the number of new connections the user may open per hour.'
  719. ) . '">'
  720. . 'MAX CONNECTIONS PER HOUR'
  721. . '</dfn></code></label>' . "\n"
  722. . '<input type="number" name="max_connections" id="text_max_connections" '
  723. . 'value="' . $row['max_connections'] . '" min="0" '
  724. . 'title="' . __(
  725. 'Limits the number of new connections the user may open per hour.'
  726. )
  727. . '" />' . "\n"
  728. . '</div>' . "\n";
  729. $html_output .= '<div class="item">' . "\n"
  730. . '<label for="text_max_user_connections">'
  731. . '<code><dfn title="'
  732. . __('Limits the number of simultaneous connections the user may have.')
  733. . '">'
  734. . 'MAX USER_CONNECTIONS'
  735. . '</dfn></code></label>' . "\n"
  736. . '<input type="number" name="max_user_connections" '
  737. . 'id="text_max_user_connections" '
  738. . 'value="' . $row['max_user_connections'] . '" '
  739. . 'title="'
  740. . __('Limits the number of simultaneous connections the user may have.')
  741. . '" />' . "\n"
  742. . '</div>' . "\n";
  743. $html_output .= '</fieldset>' . "\n";
  744. return $html_output;
  745. }
  746. /**
  747. * Get the HTML snippet for table specific privileges
  748. *
  749. * @param string $username username for database connection
  750. * @param string $hostname hostname for database connection
  751. * @param string $db the database
  752. * @param string $table the table
  753. * @param boolean $columns columns array
  754. * @param array $row current privileges row
  755. *
  756. * @return string $html_output
  757. */
  758. function PMA_getHtmlForTableSpecificPrivileges(
  759. $username, $hostname, $db, $table, $columns, $row
  760. ) {
  761. $res = $GLOBALS['dbi']->query(
  762. 'SELECT `Column_name`, `Column_priv`'
  763. . ' FROM `mysql`.`columns_priv`'
  764. . ' WHERE `User`'
  765. . ' = \'' . PMA_Util::sqlAddSlashes($username) . "'"
  766. . ' AND `Host`'
  767. . ' = \'' . PMA_Util::sqlAddSlashes($hostname) . "'"
  768. . ' AND `Db`'
  769. . ' = \'' . PMA_Util::sqlAddSlashes(
  770. PMA_Util::unescapeMysqlWildcards($db)
  771. ) . "'"
  772. . ' AND `Table_name`'
  773. . ' = \'' . PMA_Util::sqlAddSlashes($table) . '\';'
  774. );
  775. while ($row1 = $GLOBALS['dbi']->fetchRow($res)) {
  776. $row1[1] = explode(',', $row1[1]);
  777. foreach ($row1[1] as $current) {
  778. $columns[$row1[0]][$current] = true;
  779. }
  780. }
  781. $GLOBALS['dbi']->freeResult($res);
  782. unset($res, $row1, $current);
  783. $html_output = '<input type="hidden" name="grant_count" '
  784. . 'value="' . count($row) . '" />' . "\n"
  785. . '<input type="hidden" name="column_count" '
  786. . 'value="' . count($columns) . '" />' . "\n"
  787. . '<fieldset id="fieldset_user_priv">' . "\n"
  788. . '<legend data-submenu-label="Table">' . __('Table-specific privileges')
  789. . PMA_Util::showHint(
  790. __('Note: MySQL privilege names are expressed in English.')
  791. )
  792. . '</legend>' . "\n";
  793. // privs that are attached to a specific column
  794. $html_output .= PMA_getHtmlForAttachedPrivilegesToTableSpecificColumn(
  795. $columns, $row
  796. );
  797. // privs that are not attached to a specific column
  798. $html_output .= '<div class="item">' . "\n"
  799. . PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
  800. . '</div>' . "\n";
  801. // for Safari 2.0.2
  802. $html_output .= '<div class="clearfloat"></div>' . "\n";
  803. return $html_output;
  804. }
  805. /**
  806. * Get HTML snippet for privileges that are attached to a specific column
  807. *
  808. * @param string $columns olumns array
  809. * @param array $row first row from result or boolean false
  810. *
  811. * @return string $html_output
  812. */
  813. function PMA_getHtmlForAttachedPrivilegesToTableSpecificColumn($columns, $row)
  814. {
  815. $html_output = PMA_getHtmlForColumnPrivileges(
  816. $columns, $row, 'Select_priv', 'SELECT',
  817. 'select', __('Allows reading data.'), 'Select'
  818. );
  819. $html_output .= PMA_getHtmlForColumnPrivileges(
  820. $columns, $row, 'Insert_priv', 'INSERT',
  821. 'insert', __('Allows inserting and replacing data.'), 'Insert'
  822. );
  823. $html_output .= PMA_getHtmlForColumnPrivileges(
  824. $columns, $row, 'Update_priv', 'UPDATE',
  825. 'update', __('Allows changing data.'), 'Update'
  826. );
  827. $html_output .= PMA_getHtmlForColumnPrivileges(
  828. $columns, $row, 'References_priv', 'REFERENCES', 'references',
  829. __('Has no effect in this MySQL version.'), 'References'
  830. );
  831. return $html_output;
  832. }
  833. /**
  834. * Get HTML for privileges that are not attached to a specific column
  835. *
  836. * @param array $row first row from result or boolean false
  837. *
  838. * @return string $html_output
  839. */
  840. function PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
  841. {
  842. $html_output = '';
  843. foreach ($row as $current_grant => $current_grant_value) {
  844. $grant_type = substr($current_grant, 0, (strlen($current_grant) - 5));
  845. if (in_array($grant_type, array('Select', 'Insert', 'Update', 'References'))
  846. ) {
  847. continue;
  848. }
  849. // make a substitution to match the messages variables;
  850. // also we must substitute the grant we get, because we can't generate
  851. // a form variable containing blanks (those would get changed to
  852. // an underscore when receiving the POST)
  853. if ($current_grant == 'Create View_priv') {
  854. $tmp_current_grant = 'CreateView_priv';
  855. $current_grant = 'Create_view_priv';
  856. } elseif ($current_grant == 'Show view_priv') {
  857. $tmp_current_grant = 'ShowView_priv';
  858. $current_grant = 'Show_view_priv';
  859. } else {
  860. $tmp_current_grant = $current_grant;
  861. }
  862. $html_output .= '<div class="item">' . "\n"
  863. . '<input type="checkbox"'
  864. . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
  865. . '" value="Y" '
  866. . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
  867. . 'title="';
  868. $html_output .= (isset($GLOBALS[
  869. 'strPrivDesc' . substr(
  870. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  871. )
  872. ] )
  873. ? $GLOBALS[
  874. 'strPrivDesc' . substr(
  875. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  876. )
  877. ]
  878. : $GLOBALS[
  879. 'strPrivDesc' . substr(
  880. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  881. ) . 'Tbl'
  882. ]
  883. )
  884. . '"/>' . "\n";
  885. $html_output .= '<label for="checkbox_' . $current_grant
  886. . '"><code><dfn title="'
  887. . (isset($GLOBALS[
  888. 'strPrivDesc' . substr(
  889. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  890. )
  891. ])
  892. ? $GLOBALS[
  893. 'strPrivDesc' . substr(
  894. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  895. )
  896. ]
  897. : $GLOBALS[
  898. 'strPrivDesc' . substr(
  899. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  900. ) . 'Tbl'
  901. ]
  902. )
  903. . '">'
  904. . strtoupper(
  905. substr($current_grant, 0, strlen($current_grant) - 5)
  906. )
  907. . '</dfn></code></label>' . "\n"
  908. . '</div>' . "\n";
  909. } // end foreach ()
  910. return $html_output;
  911. }
  912. /**
  913. * Get HTML for global or database specific privileges
  914. *
  915. * @param string $db the database
  916. * @param string $table the table
  917. * @param string $row first row from result or boolean false
  918. *
  919. * @return string $html_output
  920. */
  921. function PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row)
  922. {
  923. $privTable_names = array(0 => __('Data'),
  924. 1 => __('Structure'),
  925. 2 => __('Administration')
  926. );
  927. $privTable = array();
  928. // d a t a
  929. $privTable[0] = PMA_getDataPrivilegeTable($db);
  930. // s t r u c t u r e
  931. $privTable[1] = PMA_getStructurePrivilegeTable($table, $row);
  932. // a d m i n i s t r a t i o n
  933. $privTable[2] = PMA_getAdministrationPrivilegeTable($db);
  934. $html_output = '<input type="hidden" name="grant_count" value="'
  935. . (count($privTable[0])
  936. + count($privTable[1])
  937. + count($privTable[2])
  938. - (isset($row['Grant_priv']) ? 1 : 0)
  939. )
  940. . '" />';
  941. $legend = $menu_label = '';
  942. if ($db == '*') {
  943. $legend = __('Global privileges');
  944. $menu_label = __('Global');
  945. } else if ($table == '*') {
  946. $legend = __('Database-specific privileges');
  947. $menu_label = __('Database');
  948. } else {
  949. $legend = __('Table-specific privileges');
  950. $menu_label = __('Table');
  951. }
  952. $html_output .= '<fieldset id="fieldset_user_global_rights">'
  953. . '<legend data-submenu-label="' . $menu_label . '">' . $legend
  954. . '<input type="checkbox" id="addUsersForm_checkall" '
  955. . 'class="checkall_box" title="' . __('Check All') . '" /> '
  956. . '<label for="addUsersForm_checkall">' . __('Check All') . '</label> '
  957. . '</legend>'
  958. . '<p><small><i>'
  959. . __('Note: MySQL privilege names are expressed in English.')
  960. . '</i></small></p>';
  961. // Output the Global privilege tables with checkboxes
  962. $html_output .= PMA_getHtmlForGlobalPrivTableWithCheckboxes(
  963. $privTable, $privTable_names, $row
  964. );
  965. // The "Resource limits" box is not displayed for db-specific privs
  966. if ($db == '*') {
  967. $html_output .= PMA_getHtmlForResourceLimits($row);
  968. }
  969. // for Safari 2.0.2
  970. $html_output .= '<div class="clearfloat"></div>';
  971. return $html_output;
  972. }
  973. /**
  974. * Get data privilege table as an array
  975. *
  976. * @param string $db the database
  977. *
  978. * @return string data privilege table
  979. */
  980. function PMA_getDataPrivilegeTable($db)
  981. {
  982. $data_privTable = array(
  983. array('Select', 'SELECT', __('Allows reading data.')),
  984. array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
  985. array('Update', 'UPDATE', __('Allows changing data.')),
  986. array('Delete', 'DELETE', __('Allows deleting data.'))
  987. );
  988. if ($db == '*') {
  989. $data_privTable[]
  990. = array('File',
  991. 'FILE',
  992. __('Allows importing data from and exporting data into files.')
  993. );
  994. }
  995. return $data_privTable;
  996. }
  997. /**
  998. * Get structure privilege table as an array
  999. *
  1000. * @param string $table the table
  1001. * @param array $row first row from result or boolean false
  1002. *
  1003. * @return string structure privilege table
  1004. */
  1005. function PMA_getStructurePrivilegeTable($table, $row)
  1006. {
  1007. $structure_privTable = array(
  1008. array('Create',
  1009. 'CREATE',
  1010. ($table == '*'
  1011. ? __('Allows creating new databases and tables.')
  1012. : __('Allows creating new tables.')
  1013. )
  1014. ),
  1015. array('Alter',
  1016. 'ALTER',
  1017. __('Allows altering the structure of existing tables.')
  1018. ),
  1019. array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
  1020. array('Drop',
  1021. 'DROP',
  1022. ($table == '*'
  1023. ? __('Allows dropping databases and tables.')
  1024. : __('Allows dropping tables.')
  1025. )
  1026. ),
  1027. array('Create_tmp_table',
  1028. 'CREATE TEMPORARY TABLES',
  1029. __('Allows creating temporary tables.')
  1030. ),
  1031. array('Show_view',
  1032. 'SHOW VIEW',
  1033. __('Allows performing SHOW CREATE VIEW queries.')
  1034. ),
  1035. array('Create_routine',
  1036. 'CREATE ROUTINE',
  1037. __('Allows creating stored routines.')
  1038. ),
  1039. array('Alter_routine',
  1040. 'ALTER ROUTINE',
  1041. __('Allows altering and dropping stored routines.')
  1042. ),
  1043. array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
  1044. );
  1045. // this one is for a db-specific priv: Create_view_priv
  1046. if (isset($row['Create_view_priv'])) {
  1047. $structure_privTable[] = array('Create_view',
  1048. 'CREATE VIEW',
  1049. __('Allows creating new views.')
  1050. );
  1051. }
  1052. // this one is for a table-specific priv: Create View_priv
  1053. if (isset($row['Create View_priv'])) {
  1054. $structure_privTable[] = array('Create View',
  1055. 'CREATE VIEW',
  1056. __('Allows creating new views.')
  1057. );
  1058. }
  1059. if (isset($row['Event_priv'])) {
  1060. // MySQL 5.1.6
  1061. $structure_privTable[] = array('Event',
  1062. 'EVENT',
  1063. __('Allows to set up events for the event scheduler.')
  1064. );
  1065. $structure_privTable[] = array('Trigger',
  1066. 'TRIGGER',
  1067. __('Allows creating and dropping triggers.')
  1068. );
  1069. }
  1070. return $structure_privTable;
  1071. }
  1072. /**
  1073. * Get administration privilege table as an array
  1074. *
  1075. * @param string $db the table
  1076. *
  1077. * @return string administration privilege table
  1078. */
  1079. function PMA_getAdministrationPrivilegeTable($db)
  1080. {
  1081. $adminPrivTable = array(
  1082. array('Grant',
  1083. 'GRANT',
  1084. __(
  1085. 'Allows adding users and privileges '
  1086. . 'without reloading the privilege tables.'
  1087. )
  1088. ),
  1089. );
  1090. if ($db == '*') {
  1091. $adminPrivTable[] = array('Super',
  1092. 'SUPER',
  1093. __(
  1094. 'Allows connecting, even if maximum number '
  1095. . 'of connections is reached; required for '
  1096. . 'most administrative operations like '
  1097. . 'setting global variables or killing threads of other users.'
  1098. )
  1099. );
  1100. $adminPrivTable[] = array('Process',
  1101. 'PROCESS',
  1102. __('Allows viewing processes of all users.')
  1103. );
  1104. $adminPrivTable[] = array('Reload',
  1105. 'RELOAD',
  1106. __('Allows reloading server settings and flushing the server\'s caches.')
  1107. );
  1108. $adminPrivTable[] = array('Shutdown',
  1109. 'SHUTDOWN',
  1110. __('Allows shutting down the server.')
  1111. );
  1112. $adminPrivTable[] = array('Show_db',
  1113. 'SHOW DATABASES',
  1114. __('Gives access to the complete list of databases.')
  1115. );
  1116. }
  1117. $adminPrivTable[] = array('Lock_tables',
  1118. 'LOCK TABLES',
  1119. __('Allows locking tables for the current thread.')
  1120. );
  1121. $adminPrivTable[] = array('References',
  1122. 'REFERENCES',
  1123. __('Has no effect in this MySQL version.')
  1124. );
  1125. if ($db == '*') {
  1126. $adminPrivTable[] = array('Repl_client',
  1127. 'REPLICATION CLIENT',
  1128. __('Allows the user to ask where the slaves / masters are.')
  1129. );
  1130. $adminPrivTable[] = array('Repl_slave',
  1131. 'REPLICATION SLAVE',
  1132. __('Needed for the replication slaves.')
  1133. );
  1134. $adminPrivTable[] = array('Create_user',
  1135. 'CREATE USER',
  1136. __('Allows creating, dropping and renaming user accounts.')
  1137. );
  1138. }
  1139. return $adminPrivTable;
  1140. }
  1141. /**
  1142. * Get HTML snippet for global privileges table with check boxes
  1143. *
  1144. * @param array $privTable privileges table array
  1145. * @param array $privTable_names names of the privilege tables
  1146. * (Data, Structure, Administration)
  1147. * @param array $row first row from result or boolean false
  1148. *
  1149. * @return string $html_output
  1150. */
  1151. function PMA_getHtmlForGlobalPrivTableWithCheckboxes(
  1152. $privTable, $privTable_names, $row
  1153. ) {
  1154. $html_output = '';
  1155. foreach ($privTable as $i => $table) {
  1156. $html_output .= '<fieldset>' . "\n"
  1157. . '<legend>' . $privTable_names[$i] . '</legend>' . "\n";
  1158. foreach ($table as $priv) {
  1159. $html_output .= '<div class="item">' . "\n"
  1160. . '<input type="checkbox" class="checkall"'
  1161. . ' name="' . $priv[0] . '_priv" '
  1162. . 'id="checkbox_' . $priv[0] . '_priv"'
  1163. . ' value="Y" title="' . $priv[2] . '"'
  1164. . (($row[$priv[0] . '_priv'] == 'Y')
  1165. ? ' checked="checked"'
  1166. : ''
  1167. )
  1168. . '/>' . "\n"
  1169. . '<label for="checkbox_' . $priv[0] . '_priv">'
  1170. . '<code><dfn title="' . $priv[2] . '">'
  1171. . $priv[1] . '</dfn></code></label>' . "\n"
  1172. . '</div>' . "\n";
  1173. }
  1174. $html_output .= '</fieldset>' . "\n";
  1175. }
  1176. return $html_output;
  1177. }
  1178. /**
  1179. * Displays the fields used by the "new user" form as well as the
  1180. * "change login information / copy user" form.
  1181. *
  1182. * @param string $mode are we creating a new user or are we just
  1183. * changing one? (allowed values: 'new', 'change')
  1184. *
  1185. * @global array $cfg the phpMyAdmin configuration
  1186. * @global ressource $user_link the database connection
  1187. *
  1188. * @return string $html_output a HTML snippet
  1189. */
  1190. function PMA_getHtmlForLoginInformationFields($mode = 'new')
  1191. {
  1192. list($username_length, $hostname_length) = PMA_getUsernameAndHostnameLength();
  1193. if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
  1194. $GLOBALS['pred_username'] = 'any';
  1195. }
  1196. $html_output = '<fieldset id="fieldset_add_user_login">' . "\n"
  1197. . '<legend>' . __('Login Information') . '</legend>' . "\n"
  1198. . '<div class="item">' . "\n"
  1199. . '<label for="select_pred_username">' . "\n"
  1200. . ' ' . __('User name:') . "\n"
  1201. . '</label>' . "\n"
  1202. . '<span class="options">' . "\n";
  1203. $html_output .= '<select name="pred_username" id="select_pred_username" '
  1204. . 'title="' . __('User name') . '"' . "\n";
  1205. $html_output .= ' onchange="'
  1206. . 'if (this.value == \'any\') {'
  1207. . ' username.value = \'\'; '
  1208. . ' user_exists_warning.style.display = \'none\'; '
  1209. . ' username.required = false; '
  1210. . '} else if (this.value == \'userdefined\') {'
  1211. . ' username.focus(); username.select(); '
  1212. . ' username.required = true; '
  1213. . '}">' . "\n";
  1214. $html_output .= '<option value="any"'
  1215. . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any')
  1216. ? ' selected="selected"'
  1217. : '') . '>'
  1218. . __('Any user')
  1219. . '</option>' . "\n";
  1220. $html_output .= '<option value="userdefined"'
  1221. . ((! isset($GLOBALS['pred_username'])
  1222. || $GLOBALS['pred_username'] == 'userdefined'
  1223. )
  1224. ? ' selected="selected"'
  1225. : '') . '>'
  1226. . __('Use text field')
  1227. . ':</option>' . "\n";
  1228. $html_output .= '</select>' . "\n"
  1229. . '</span>' . "\n";
  1230. $html_output .= '<input type="text" name="username" class="autofocus"'
  1231. . ' maxlength="' . $username_length . '" title="' . __('User name') . '"'
  1232. . (empty($GLOBALS['username'])
  1233. ? ''
  1234. : ' value="' . htmlspecialchars(
  1235. isset($GLOBALS['new_username'])
  1236. ? $GLOBALS['new_username']
  1237. : $GLOBALS['username']
  1238. ) . '"'
  1239. )
  1240. . ' onchange="pred_username.value = \'userdefined\'; this.required = true;" '
  1241. . ((! isset($GLOBALS['pred_username'])
  1242. || $GLOBALS['pred_username'] == 'userdefined'
  1243. )
  1244. ? 'required="required"'
  1245. : '') . ' />' . "\n";
  1246. $html_output .= '<div id="user_exists_warning"'
  1247. . ' name="user_exists_warning" style="display:none;">'
  1248. . PMA_Message::notice(
  1249. __(
  1250. 'An account already exists with the same username '
  1251. . 'but possibly a different hostname.'
  1252. )
  1253. )->getDisplay()
  1254. . '</div>';
  1255. $html_output .= '</div>';
  1256. $html_output .= '<div class="item">' . "\n"
  1257. . '<label for="select_pred_hostname">' . "\n"
  1258. . ' ' . __('Host:') . "\n"
  1259. . '</label>' . "\n";
  1260. $html_output .= '<span class="options">' . "\n"
  1261. . ' <select name="pred_hostname" id="select_pred_hostname" '
  1262. . 'title="' . __('Host') . '"' . "\n";
  1263. $_current_user = $GLOBALS['dbi']->fetchValue('SELECT USER();');
  1264. if (! empty($_current_user)) {
  1265. $thishost = str_replace(
  1266. "'",
  1267. '',
  1268. substr($_current_user, (strrpos($_current_user, '@') + 1))
  1269. );
  1270. if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
  1271. unset($thishost);
  1272. }
  1273. }
  1274. $html_output .= ' onchange="'
  1275. . 'if (this.value == \'any\') { '
  1276. . ' hostname.value = \'%\'; '
  1277. . '} else if (this.value == \'localhost\') { '
  1278. . ' hostname.value = \'localhost\'; '
  1279. . '} '
  1280. . (empty($thishost)
  1281. ? ''
  1282. : 'else if (this.value == \'thishost\') { '
  1283. . ' hostname.value = \'' . addslashes(htmlspecialchars($thishost))
  1284. . '\'; '
  1285. . '} '
  1286. )
  1287. . 'else if (this.value == \'hosttable\') { '
  1288. . ' hostname.value = \'\'; '
  1289. . ' hostname.required = false; '
  1290. . '} else if (this.value == \'userdefined\') {'
  1291. . ' hostname.focus(); hostname.select(); '
  1292. . ' hostname.required = true; '
  1293. . '}">' . "\n";
  1294. unset($_current_user);
  1295. // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
  1296. if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
  1297. switch (strtolower($GLOBALS['hostname'])) {
  1298. case 'localhost':
  1299. case '127.0.0.1':
  1300. $GLOBALS['pred_hostname'] = 'localhost';
  1301. break;
  1302. case '%':
  1303. $GLOBALS['pred_hostname'] = 'any';
  1304. break;
  1305. default:
  1306. $GLOBALS['pred_hostname'] = 'userdefined';
  1307. break;
  1308. }
  1309. }
  1310. $html_output .= '<option value="any"'
  1311. . ((isset($GLOBALS['pred_hostname'])
  1312. && $GLOBALS['pred_hostname'] == 'any'
  1313. )
  1314. ? ' selected="selected"'
  1315. : '') . '>'
  1316. . __('Any host')
  1317. . '</option>' . "\n"
  1318. . '<option value="localhost"'
  1319. . ((isset($GLOBALS['pred_hostname'])
  1320. && $GLOBALS['pred_hostname'] == 'localhost'
  1321. )
  1322. ? ' selected="selected"'
  1323. : '') . '>'
  1324. . __('Local')
  1325. . '</option>' . "\n";
  1326. if (! empty($thishost)) {
  1327. $html_output .= '<option value="thishost"'
  1328. . ((isset($GLOBALS['pred_hostname'])
  1329. && $GLOBALS['pred_hostname'] == 'thishost'
  1330. )
  1331. ? ' selected="selected"'
  1332. : '') . '>'
  1333. . __('This Host')
  1334. . '</option>' . "\n";
  1335. }
  1336. unset($thishost);
  1337. $html_output .= '<option value="hosttable"'
  1338. . ((isset($GLOBALS['pred_hostname'])
  1339. && $GLOBALS['pred_hostname'] == 'hosttable'
  1340. )
  1341. ? ' selected="selected"'
  1342. : '') . '>'
  1343. . __('Use Host Table')
  1344. . '</option>' . "\n";
  1345. $html_output .= '<option value="userdefined"'
  1346. . ((isset($GLOBALS['pred_hostname'])
  1347. && $GLOBALS['pred_hostname'] == 'userdefined'
  1348. )
  1349. ? ' selected="selected"'
  1350. : '') . '>'
  1351. . __('Use text field:') . '</option>' . "\n"
  1352. . '</select>' . "\n"
  1353. . '</span>' . "\n";
  1354. $html_output .= '<input type="text" name="hostname" maxlength="'
  1355. . $hostname_length . '" value="'
  1356. // use default value of '%' to match with the default 'Any host'
  1357. . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '%')
  1358. . '" title="' . __('Host')
  1359. . '" onchange="pred_hostname.value = \'userdefined\'; this.required = true;" '
  1360. . ((isset($GLOBALS['pred_hostname'])
  1361. && $GLOBALS['pred_hostname'] == 'userdefined'
  1362. )
  1363. ? 'required="required"'
  1364. : '')
  1365. . ' />' . "\n"
  1366. . PMA_Util::showHint(
  1367. __(
  1368. 'When Host table is used, this field is ignored '
  1369. . 'and values stored in Host table are used instead.'
  1370. )
  1371. )
  1372. . '</div>' . "\n";
  1373. $html_output .= '<div class="item">' . "\n"
  1374. . '<label for="select_pred_password">' . "\n"
  1375. . ' ' . __('Password:') . "\n"
  1376. . '</label>' . "\n"
  1377. . '<span class="options">' . "\n"
  1378. . '<select name="pred_password" id="select_pred_password" title="'
  1379. . __('Password') . '"' . "\n";
  1380. $html_output .= ' onchange="'
  1381. . 'if (this.value == \'none\') { '
  1382. . ' pma_pw.value = \'\'; pma_pw2.value = \'\'; '
  1383. . ' pma_pw.required = false; pma_pw2.required = false; '
  1384. . '} else if (this.value == \'userdefined\') { '
  1385. . ' pma_pw.focus(); pma_pw.select(); '
  1386. . ' pma_pw.required = true; pma_pw2.required = true; '
  1387. . '} else { '
  1388. . ' pma_pw.required = false; pma_pw2.required = false; '
  1389. . '}">' . "\n"
  1390. . ($mode == 'change' ? '<option value="keep" selected="selected">'
  1391. . __('Do not change the password')
  1392. . '</option>' . "\n" : '')
  1393. . '<option value="none"';
  1394. if (isset($GLOBALS['username']) && $mode != 'change') {
  1395. $html_output .= ' selected="selected"';
  1396. }
  1397. $html_output .= '>' . __('No Password') . '</option>' . "\n"
  1398. . '<option value="userdefined"'
  1399. . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>'
  1400. . __('Use text field')
  1401. . ':</option>' . "\n"
  1402. . '</select>' . "\n"
  1403. . '</span>' . "\n"
  1404. . '<input type="password" id="text_pma_pw" name="pma_pw" '
  1405. . 'title="' . __('Password') . '" '
  1406. . 'onchange="pred_password.value = \'userdefined\'; this.required = true; pma_pw2.required = true;" '
  1407. . (isset($GLOBALS['username']) ? '' : 'required="required"')
  1408. . '/>' . "\n"
  1409. . '</div>' . "\n";
  1410. $html_output .= '<div class="item" '
  1411. . 'id="div_element_before_generate_password">' . "\n"
  1412. . '<label for="text_pma_pw2">' . "\n"
  1413. . ' ' . __('Re-type:') . "\n"
  1414. . '</label>' . "\n"
  1415. . '<span class="options">&nbsp;</span>' . "\n"
  1416. . '<input type="password" name="pma_pw2" id="text_pma_pw2" '
  1417. . 'title="' . __('Re-type') . '" '
  1418. . 'onchange="pred_password.value = \'userdefined\'; this.required = true; pma_pw.required = true;" '
  1419. . (isset($GLOBALS['username']) ? '' : 'required="required"')
  1420. . '/>' . "\n"
  1421. . '</div>' . "\n"
  1422. // Generate password added here via jQuery
  1423. . '</fieldset>' . "\n";
  1424. return $html_output;
  1425. } // end of the 'PMA_displayUserAndHostFields()' function
  1426. /**
  1427. * Get username and hostname length
  1428. *
  1429. * @return array username length and hostname length
  1430. */
  1431. function PMA_getUsernameAndHostnameLength()
  1432. {
  1433. /* Fallback values */
  1434. $username_length = 16;
  1435. $hostname_length = 41;
  1436. /* Try to get real lengths from the database */
  1437. $fields_info = $GLOBALS['dbi']->fetchResult(
  1438. 'SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH '
  1439. . 'FROM information_schema.columns '
  1440. . "WHERE table_schema = 'mysql' AND table_name = 'user' "
  1441. . "AND COLUMN_NAME IN ('User', 'Host')"
  1442. );
  1443. foreach ($fields_info as $val) {
  1444. if ($val['COLUMN_NAME'] == 'User') {
  1445. $username_length = $val['CHARACTER_MAXIMUM_LENGTH'];
  1446. } elseif ($val['COLUMN_NAME'] == 'Host') {
  1447. $hostname_length = $val['CHARACTER_MAXIMUM_LENGTH'];
  1448. }
  1449. }
  1450. return array($username_length, $hostname_length);
  1451. }
  1452. /**
  1453. * Returns all the grants for a certain user on a certain host
  1454. * Used in the export privileges for all users section
  1455. *
  1456. * @param string $user User name
  1457. * @param string $host Host name
  1458. *
  1459. * @return string containing all the grants text
  1460. */
  1461. function PMA_getGrants($user, $host)
  1462. {
  1463. $grants = $GLOBALS['dbi']->fetchResult(
  1464. "SHOW GRANTS FOR '"
  1465. . PMA_Util::sqlAddSlashes($user) . "'@'"
  1466. . PMA_Util::sqlAddSlashes($host) . "'"
  1467. );
  1468. $response = '';
  1469. foreach ($grants as $one_grant) {
  1470. $response .= $one_grant . ";\n\n";
  1471. }
  1472. return $response;
  1473. } // end of the 'PMA_getGrants()' function
  1474. /**
  1475. * Update password and get message for password updating
  1476. *
  1477. * @param string $err_url error url
  1478. * @param string $username username
  1479. * @param string $hostname hostname
  1480. *
  1481. * @return string $message success or error message after updating password
  1482. */
  1483. function PMA_updatePassword($err_url, $username, $hostname)
  1484. {
  1485. // similar logic in user_password.php
  1486. $message = '';
  1487. if (empty($_REQUEST['nopass'])
  1488. && isset($_POST['pma_pw'])
  1489. && isset($_POST['pma_pw2'])
  1490. ) {
  1491. if ($_POST['pma_pw'] != $_POST['pma_pw2']) {
  1492. $message = PMA_Message::error(__('The passwords aren\'t the same!'));
  1493. } elseif (empty($_POST['pma_pw']) || empty($_POST['pma_pw2'])) {
  1494. $message = PMA_Message::error(__('The password is empty!'));
  1495. }
  1496. }
  1497. // here $nopass could be == 1
  1498. if (empty($message)) {
  1499. $hashing_function
  1500. = (! empty($_REQUEST['pw_hash']) && $_REQUEST['pw_hash'] == 'old'
  1501. ? 'OLD_'
  1502. : ''
  1503. )
  1504. . 'PASSWORD';
  1505. // in $sql_query which will be displayed, hide the password
  1506. $sql_query = 'SET PASSWORD FOR \''
  1507. . PMA_Util::sqlAddSlashes($username)
  1508. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\' = '
  1509. . (($_POST['pma_pw'] == '')
  1510. ? '\'\''
  1511. : $hashing_function . '(\''
  1512. . preg_replace('@.@s', '*', $_POST['pma_pw']) . '\')');
  1513. $local_query = 'SET PASSWORD FOR \''
  1514. . PMA_Util::sqlAddSlashes($username)
  1515. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\' = '
  1516. . (($_POST['pma_pw'] == '') ? '\'\'' : $hashing_function
  1517. . '(\'' . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\')');
  1518. $GLOBALS['dbi']->tryQuery($local_query)
  1519. or PMA_Util::mysqlDie(
  1520. $GLOBALS['dbi']->getError(), $sql_query, false, $err_url
  1521. );
  1522. $message = PMA_Message::success(
  1523. __('The password for %s was changed successfully.')
  1524. );
  1525. $message->addParam(
  1526. '\'' . htmlspecialchars($username)
  1527. . '\'@\'' . htmlspecialchars($hostname) . '\''
  1528. );
  1529. }
  1530. return $message;
  1531. }
  1532. /**
  1533. * Revokes privileges and get message and SQL query for privileges revokes
  1534. *
  1535. * @param string $db_and_table wildcard Escaped database+table specification
  1536. * @param string $dbname database name
  1537. * @param string $tablename table name
  1538. * @param string $username username
  1539. * @param string $hostname host name
  1540. *
  1541. * @return array ($message, $sql_query)
  1542. */
  1543. function PMA_getMessageAndSqlQueryForPrivilegesRevoke($db_and_table, $dbname,
  1544. $tablename, $username, $hostname
  1545. ) {
  1546. $db_and_table = PMA_wildcardEscapeForGrant($dbname, $tablename);
  1547. $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
  1548. . ' FROM \''
  1549. . PMA_Util::sqlAddSlashes($username) . '\'@\''
  1550. . PMA_Util::sqlAddSlashes($hostname) . '\';';
  1551. $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
  1552. . ' FROM \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
  1553. . PMA_Util::sqlAddSlashes($hostname) . '\';';
  1554. $GLOBALS['dbi']->query($sql_query0);
  1555. if (! $GLOBALS['dbi']->tryQuery($sql_query1)) {
  1556. // this one may fail, too...
  1557. $sql_query1 = '';
  1558. }
  1559. $sql_query = $sql_query0 . ' ' . $sql_query1;
  1560. $message = PMA_Message::success(
  1561. __('You have revoked the privileges for %s.')
  1562. );
  1563. $message->addParam(
  1564. '\'' . htmlspecialchars($username)
  1565. . '\'@\'' . htmlspecialchars($hostname) . '\''
  1566. );
  1567. return array($message, $sql_query);
  1568. }
  1569. /**
  1570. * Get a WITH clause for 'update privileges' and 'add user'
  1571. *
  1572. * @return string $sql_query
  1573. */
  1574. function PMA_getWithClauseForAddUserAndUpdatePrivs()
  1575. {
  1576. $sql_query = '';
  1577. if (isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y') {
  1578. $sql_query .= ' GRANT OPTION';
  1579. }
  1580. if (isset($_POST['max_questions'])) {
  1581. $max_questions = max(0, (int)$_POST['max_questions']);
  1582. $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
  1583. }
  1584. if (isset($_POST['max_connections'])) {
  1585. $max_connections = max(0, (int)$_POST['max_connections']);
  1586. $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
  1587. }
  1588. if (isset($_POST['max_updates'])) {
  1589. $max_updates = max(0, (int)$_POST['max_updates']);
  1590. $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
  1591. }
  1592. if (isset($_POST['max_user_connections'])) {
  1593. $max_user_connections = max(0, (int)$_POST['max_user_connections']);
  1594. $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
  1595. }
  1596. return ((!empty($sql_query)) ? 'WITH' . $sql_query : '');
  1597. }
  1598. /**
  1599. * Get HTML for addUsersForm, This function call if isset($_REQUEST['adduser'])
  1600. *
  1601. * @param string $dbname database name
  1602. *
  1603. * @return string HTML for addUserForm
  1604. */
  1605. function PMA_getHtmlForAddUser($dbname)
  1606. {
  1607. $html_output = '<h2>' . "\n"
  1608. . PMA_Util::getIcon('b_usradd.png') . __('Add user') . "\n"
  1609. . '</h2>' . "\n"
  1610. . '<form name="usersForm" class="ajax" id="addUsersForm"'
  1611. . ' action="server_privileges.php" method="post" autocomplete="off" >' . "\n"
  1612. . PMA_URL_getHiddenInputs('', '')
  1613. . PMA_getHtmlForLoginInformationFields('new');
  1614. $html_output .= '<fieldset id="fieldset_add_user_database">' . "\n"
  1615. . '<legend>' . __('Database for user') . '</legend>' . "\n";
  1616. $html_output .= PMA_Util::getCheckbox(
  1617. 'createdb-1',
  1618. __('Create database with same name and grant all privileges.'),
  1619. false, false
  1620. );
  1621. $html_output .= '<br />' . "\n";
  1622. $html_output .= PMA_Util::getCheckbox(
  1623. 'createdb-2',
  1624. __('Grant all privileges on wildcard name (username\\_%).'),
  1625. false, false
  1626. );
  1627. $html_output .= '<br />' . "\n";
  1628. if (! empty($dbname) ) {
  1629. $html_output .= PMA_Util::getCheckbox(
  1630. 'createdb-3',
  1631. sprintf(
  1632. __('Grant all privileges on database "%s".'),
  1633. htmlspecialchars($dbname)
  1634. ),
  1635. true,
  1636. false
  1637. );
  1638. $html_output .= '<input type="hidden" name="dbname" value="'
  1639. . htmlspecialchars($dbname) . '" />' . "\n";
  1640. $html_output .= '<br />' . "\n";
  1641. }
  1642. $html_output .= '</fieldset>' . "\n";
  1643. $html_output .= PMA_getHtmlToDisplayPrivilegesTable('*', '*', false);
  1644. $html_output .= '<fieldset id="fieldset_add_user_footer" class="tblFooters">'
  1645. . "\n"
  1646. . '<input type="submit" name="adduser_submit" '
  1647. . 'value="' . __('Go') . '" />' . "\n"
  1648. . '</fieldset>' . "\n"
  1649. . '</form>' . "\n";
  1650. return $html_output;
  1651. }
  1652. /**
  1653. * Get the list of privileges and list of compared privileges as strings
  1654. * and return a array that contains both strings
  1655. *
  1656. * @return array $list_of_privileges, $list_of_compared_privileges
  1657. */
  1658. function PMA_getListOfPrivilegesAndComparedPrivileges()
  1659. {
  1660. $list_of_privileges
  1661. = '`User`, '
  1662. . '`Host`, '
  1663. . '`Select_priv`, '
  1664. . '`Insert_priv`, '
  1665. . '`Update_priv`, '
  1666. . '`Delete_priv`, '
  1667. . '`Create_priv`, '
  1668. . '`Drop_priv`, '
  1669. . '`Grant_priv`, '
  1670. . '`Index_priv`, '
  1671. . '`Alter_priv`, '
  1672. . '`References_priv`, '
  1673. . '`Create_tmp_table_priv`, '
  1674. . '`Lock_tables_priv`, '
  1675. . '`Create_view_priv`, '
  1676. . '`Show_view_priv`, '
  1677. . '`Create_routine_priv`, '
  1678. . '`Alter_routine_priv`, '
  1679. . '`Execute_priv`';
  1680. $listOfComparedPrivs
  1681. = '`Select_priv` = \'N\''
  1682. . ' AND `Insert_priv` = \'N\''
  1683. . ' AND `Update_priv` = \'N\''
  1684. . ' AND `Delete_priv` = \'N\''
  1685. . ' AND `Create_priv` = \'N\''
  1686. . ' AND `Drop_priv` = \'N\''
  1687. . ' AND `Grant_priv` = \'N\''
  1688. . ' AND `References_priv` = \'N\''
  1689. . ' AND `Create_tmp_table_priv` = \'N\''
  1690. . ' AND `Lock_tables_priv` = \'N\''
  1691. . ' AND `Create_view_priv` = \'N\''
  1692. . ' AND `Show_view_priv` = \'N\''
  1693. . ' AND `Create_routine_priv` = \'N\''
  1694. . ' AND `Alter_routine_priv` = \'N\''
  1695. . ' AND `Execute_priv` = \'N\'';
  1696. if (PMA_MYSQL_INT_VERSION >= 50106) {
  1697. $list_of_privileges .=
  1698. ', `Event_priv`, '
  1699. . '`Trigger_priv`';
  1700. $listOfComparedPrivs .=
  1701. ' AND `Event_priv` = \'N\''
  1702. . ' AND `Trigger_priv` = \'N\'';
  1703. }
  1704. return array($list_of_privileges, $listOfComparedPrivs);
  1705. }
  1706. /**
  1707. * Get the HTML for user form and check the privileges for a particular database.
  1708. *
  1709. * @param string $db database name
  1710. *
  1711. * @return string $html_output
  1712. */
  1713. function PMA_getHtmlForSpecificDbPrivileges($db)
  1714. {
  1715. // check the privileges for a particular database.
  1716. $html_output = '<form id="usersForm" action="server_privileges.php">'
  1717. . '<fieldset>' . "\n";
  1718. $html_output .= '<legend>' . "\n"
  1719. . PMA_Util::getIcon('b_usrcheck.png')
  1720. . ' '
  1721. . sprintf(
  1722. __('Users having access to "%s"'),
  1723. '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
  1724. . PMA_URL_getCommon($db) . '">'
  1725. . htmlspecialchars($db)
  1726. . '</a>'
  1727. )
  1728. . "\n"
  1729. . '</legend>' . "\n";
  1730. $html_output .= '<table id="dbspecificuserrights" class="data">' . "\n"
  1731. . '<thead>' . "\n"
  1732. . '<tr><th>' . __('User') . '</th>' . "\n"
  1733. . '<th>' . __('Host') . '</th>' . "\n"
  1734. . '<th>' . __('Type') . '</th>' . "\n"
  1735. . '<th>' . __('Privileges') . '</th>' . "\n"
  1736. . '<th>' . __('Grant') . '</th>' . "\n"
  1737. . '<th>' . __('Action') . '</th>' . "\n"
  1738. . '</tr>' . "\n"
  1739. . '</thead>' . "\n";
  1740. // now, we build the table...
  1741. list($listOfPrivs, $listOfComparedPrivs)
  1742. = PMA_getListOfPrivilegesAndComparedPrivileges();
  1743. $sql_query = '(SELECT ' . $listOfPrivs . ', `Db`, \'d\' AS `Type`'
  1744. . ' FROM `mysql`.`db`'
  1745. . ' WHERE \'' . PMA_Util::sqlAddSlashes($db)
  1746. . "'"
  1747. . ' LIKE `Db`'
  1748. . ' AND NOT (' . $listOfComparedPrivs . ')) '
  1749. . 'UNION '
  1750. . '(SELECT ' . $listOfPrivs . ', \'*\' AS `Db`, \'g\' AS `Type`'
  1751. . ' FROM `mysql`.`user` '
  1752. . ' WHERE NOT (' . $listOfComparedPrivs . ')) '
  1753. . ' ORDER BY `User` ASC,'
  1754. . ' `Host` ASC,'
  1755. . ' `Db` ASC;';
  1756. $res = $GLOBALS['dbi']->query($sql_query);
  1757. $privMap = array();
  1758. while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
  1759. $user = $row['User'];
  1760. $host = $row['Host'];
  1761. if (! isset($privMap[$user])) {
  1762. $privMap[$user] = array();
  1763. }
  1764. if (! isset($privMap[$user][$host])) {
  1765. $privMap[$user][$host] = array();
  1766. }
  1767. $privMap[$user][$host][] = $row;
  1768. }
  1769. $html_output .= PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db);
  1770. $html_output .= '</table>'
  1771. . '</fieldset>'
  1772. . '</form>' . "\n";
  1773. if ($GLOBALS['is_ajax_request'] == true
  1774. && empty($_REQUEST['ajax_page_request'])
  1775. ) {
  1776. $message = PMA_Message::success(__('User has been added.'));
  1777. $response = PMA_Response::getInstance();
  1778. $response->addJSON('message', $message);
  1779. $response->addJSON('user_form', $html_output);
  1780. exit;
  1781. } else {
  1782. // Offer to create a new user for the current database
  1783. $html_output .= '<fieldset id="fieldset_add_user">' . "\n"
  1784. . '<legend>' . _pgettext('Create new user', 'New') . '</legend>' . "\n";
  1785. $html_output .= '<a href="server_privileges.php'
  1786. . PMA_URL_getCommon(
  1787. array(
  1788. 'adduser' => 1,
  1789. 'dbname' => $db,
  1790. )
  1791. )
  1792. . '" rel="'
  1793. . PMA_URL_getCommon(array('checkprivsdb' => $db))
  1794. . '" class="ajax" name="db_specific">' . "\n"
  1795. . PMA_Util::getIcon('b_usradd.png')
  1796. . ' ' . __('Add user') . '</a>' . "\n";
  1797. $html_output .= '</fieldset>' . "\n";
  1798. }
  1799. return $html_output;
  1800. }
  1801. /**
  1802. * Get the HTML for user form and check the privileges for a particular table.
  1803. *
  1804. * @param string $db database name
  1805. * @param string $table table name
  1806. *
  1807. * @return string $html_output
  1808. */
  1809. function PMA_getHtmlForSpecificTablePrivileges($db, $table)
  1810. {
  1811. // check the privileges for a particular table.
  1812. $html_output = '<form id="usersForm" action="server_privileges.php">';
  1813. $html_output .= '<fieldset>';
  1814. $html_output .= '<legend>'
  1815. . PMA_Util::getIcon('b_usrcheck.png')
  1816. . sprintf(
  1817. __('Users having access to "%s"'),
  1818. '<a href="' . $GLOBALS['cfg']['DefaultTabTable']
  1819. . PMA_URL_getCommon(
  1820. array(
  1821. 'db' => $db,
  1822. 'table' => $table,
  1823. )
  1824. ) . '">'
  1825. . htmlspecialchars($db) . '.' . htmlspecialchars($table)
  1826. . '</a>'
  1827. )
  1828. . '</legend>';
  1829. $html_output .= '<table id="tablespecificuserrights" class="data">';
  1830. $html_output .= '<thead>'
  1831. . '<tr><th>' . __('User') . '</th>'
  1832. . '<th>' . __('Host') . '</th>'
  1833. . '<th>' . __('Type') . '</th>'
  1834. . '<th>' . __('Privileges') . '</th>'
  1835. . '<th>' . __('Grant') . '</th>'
  1836. . '<th>' . __('Action') . '</th>'
  1837. . '</tr>'
  1838. . '</thead>';
  1839. list($listOfPrivs, $listOfComparedPrivs)
  1840. = PMA_getListOfPrivilegesAndComparedPrivileges();
  1841. $sql_query
  1842. = "("
  1843. . " SELECT " . $listOfPrivs . ", '*' AS `Db`, 'g' AS `Type`"
  1844. . " FROM `mysql`.`user`"
  1845. . " WHERE NOT (" . $listOfComparedPrivs . ")"
  1846. . ")"
  1847. . " UNION "
  1848. . "("
  1849. . " SELECT " . $listOfPrivs . ", `Db`, 'd' AS `Type`"
  1850. . " FROM `mysql`.`db`"
  1851. . " WHERE '" . PMA_Util::sqlAddSlashes($db) . "' LIKE `Db`"
  1852. . " AND NOT (" . $listOfComparedPrivs . ")"
  1853. . ")"
  1854. . " ORDER BY `User` ASC, `Host` ASC, `Db` ASC;";
  1855. $res = $GLOBALS['dbi']->query($sql_query);
  1856. $privMap = array();
  1857. while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
  1858. $user = $row['User'];
  1859. $host = $row['Host'];
  1860. if (! isset($privMap[$user])) {
  1861. $privMap[$user] = array();
  1862. }
  1863. if (! isset($privMap[$user][$host])) {
  1864. $privMap[$user][$host] = array();
  1865. }
  1866. $privMap[$user][$host][] = $row;
  1867. }
  1868. $sql_query = "SELECT `User`, `Host`, `Db`,"
  1869. . " 't' AS `Type`, `Table_name`, `Table_priv`"
  1870. . " FROM `mysql`.`tables_priv`"
  1871. . " WHERE '" . PMA_Util::sqlAddSlashes($db) . "' LIKE `Db`"
  1872. . " AND '" . PMA_Util::sqlAddSlashes($table) . "' LIKE `Table_name`"
  1873. . " AND NOT (`Table_priv` = '' AND Column_priv = '')"
  1874. . " ORDER BY `User` ASC, `Host` ASC, `Db` ASC, `Table_priv` ASC;";
  1875. $res = $GLOBALS['dbi']->query($sql_query);
  1876. while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
  1877. $user = $row['User'];
  1878. $host = $row['Host'];
  1879. if (! isset($privMap[$user])) {
  1880. $privMap[$user] = array();
  1881. }
  1882. if (! isset($privMap[$user][$host])) {
  1883. $privMap[$user][$host] = array();
  1884. }
  1885. $privMap[$user][$host][] = $row;
  1886. }
  1887. $html_output .= PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db);
  1888. $html_output .= '</table>';
  1889. $html_output .= '</fieldset>';
  1890. $html_output .= '</form>';
  1891. // Offer to create a new user for the current database
  1892. $html_output .= '<fieldset id="fieldset_add_user">'
  1893. . '<legend>' . _pgettext('Create new user', 'New') . '</legend>';
  1894. $html_output .= '<a href="server_privileges.php'
  1895. . PMA_URL_getCommon(
  1896. array(
  1897. 'adduser' => 1,
  1898. 'dbname' => $db,
  1899. 'tablename' => $table
  1900. )
  1901. )
  1902. . '" rel="' . PMA_URL_getCommon(
  1903. array('checkprivsdb' => $db, 'checkprivstable' => $table)
  1904. )
  1905. . '" class="ajax" name="table_specific">'
  1906. . PMA_Util::getIcon('b_usradd.png') . __('Add user') . '</a>';
  1907. $html_output .= '</fieldset>';
  1908. return $html_output;
  1909. }
  1910. /**
  1911. * Get HTML snippet for table body of specific database or table privileges
  1912. *
  1913. * @param array $privMap priviledge map
  1914. * @param boolean $db database
  1915. *
  1916. * @return string $html_output
  1917. */
  1918. function PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db)
  1919. {
  1920. $html_output = '<tbody>';
  1921. $odd_row = true;
  1922. if (empty($privMap)) {
  1923. $html_output .= '<tr class="odd">'
  1924. . '<td colspan="6">'
  1925. . __('No user found.')
  1926. . '</td>'
  1927. . '</tr>'
  1928. . '</tbody>';
  1929. return $html_output;
  1930. }
  1931. foreach ($privMap as $current_user => $val) {
  1932. foreach ($val as $current_host => $current_privileges) {
  1933. $nbPrivileges = count($current_privileges);
  1934. $html_output .= '<tr class="noclick '
  1935. . ($odd_row ? 'odd' : 'even') . '">';
  1936. // user
  1937. $html_output .= '<td';
  1938. if ($nbPrivileges > 1) {
  1939. $html_output .= ' rowspan="' . $nbPrivileges . '"';
  1940. }
  1941. $html_output .= '>';
  1942. if (empty($current_user)) {
  1943. $html_output .= '<span style="color: #FF0000">'
  1944. . __('Any') . '</span>';
  1945. } else {
  1946. $html_output .= htmlspecialchars($current_user);
  1947. }
  1948. $html_output .= '</td>';
  1949. // host
  1950. $html_output .= '<td';
  1951. if ($nbPrivileges > 1) {
  1952. $html_output .= ' rowspan="' . $nbPrivileges . '"';
  1953. }
  1954. $html_output .= '>';
  1955. $html_output .= htmlspecialchars($current_host);
  1956. $html_output .= '</td>';
  1957. $html_output .= PMA_getHtmlListOfPrivs(
  1958. $db, $current_privileges, $current_user,
  1959. $current_host, $odd_row
  1960. );
  1961. $odd_row = ! $odd_row;
  1962. }
  1963. }
  1964. $html_output .= '</tbody>';
  1965. return $html_output;
  1966. }
  1967. /**
  1968. * Get HTML to display privileges
  1969. *
  1970. * @param string $db Database name
  1971. * @param array $current_privileges List of privileges
  1972. * @param string $current_user Current user
  1973. * @param string $current_host Current host
  1974. * @param boolean $odd_row Current row is odd
  1975. *
  1976. * @return string HTML to display privileges
  1977. */
  1978. function PMA_getHtmlListOfPrivs(
  1979. $db, $current_privileges, $current_user,
  1980. $current_host, $odd_row
  1981. ) {
  1982. $nbPrivileges = count($current_privileges);
  1983. $html_output = null;
  1984. for ($i = 0; $i < $nbPrivileges; $i++) {
  1985. $current = $current_privileges[$i];
  1986. // type
  1987. $html_output .= '<td>';
  1988. if ($current['Type'] == 'g') {
  1989. $html_output .= __('global');
  1990. } elseif ($current['Type'] == 'd') {
  1991. if ($current['Db'] == PMA_Util::escapeMysqlWildcards($db)) {
  1992. $html_output .= __('database-specific');
  1993. } else {
  1994. $html_output .= __('wildcard') . ': '
  1995. . '<code>'
  1996. . htmlspecialchars($current['Db'])
  1997. . '</code>';
  1998. }
  1999. } elseif ($current['Type'] == 't') {
  2000. $html_output .= __('table-specific');
  2001. }
  2002. $html_output .= '</td>';
  2003. // privileges
  2004. $html_output .= '<td>';
  2005. if (isset($current['Table_name'])) {
  2006. $privList = explode(',', $current['Table_priv']);
  2007. $privs = array();
  2008. $grantsArr = PMA_getTableGrantsArray();
  2009. foreach ($grantsArr as $grant) {
  2010. $privs[$grant[0]] = 'N';
  2011. foreach ($privList as $priv) {
  2012. if ($grant[0] == $priv) {
  2013. $privs[$grant[0]] = 'Y';
  2014. }
  2015. }
  2016. }
  2017. $html_output .= '<code>'
  2018. . join(
  2019. ',',
  2020. PMA_extractPrivInfo($privs, true, true)
  2021. )
  2022. . '</code>';
  2023. } else {
  2024. $html_output .= '<code>'
  2025. . join(
  2026. ',',
  2027. PMA_extractPrivInfo($current, true, false)
  2028. )
  2029. . '</code>';
  2030. }
  2031. $html_output .= '</td>';
  2032. // grant
  2033. $html_output .= '<td>';
  2034. $containsGrant = false;
  2035. if (isset($current['Table_name'])) {
  2036. $privList = explode(',', $current['Table_priv']);
  2037. foreach ($privList as $priv) {
  2038. if ($priv == 'Grant') {
  2039. $containsGrant = true;
  2040. }
  2041. }
  2042. } else {
  2043. $containsGrant = $current['Grant_priv'] == 'Y';
  2044. }
  2045. $html_output .= ($containsGrant ? __('Yes') : __('No'));
  2046. $html_output .= '</td>';
  2047. // action
  2048. $html_output .= '<td>';
  2049. $specific_db = (isset($current['Db']) && $current['Db'] != '*')
  2050. ? $current['Db'] : '';
  2051. $specific_table = (isset($current['Table_name'])
  2052. && $current['Table_name'] != '*')
  2053. ? $current['Table_name'] : '';
  2054. $html_output .= PMA_getUserEditLink(
  2055. $current_user,
  2056. $current_host,
  2057. $specific_db,
  2058. $specific_table
  2059. );
  2060. $html_output .= '</td>';
  2061. $html_output .= '</tr>';
  2062. if (($i + 1) < $nbPrivileges) {
  2063. $html_output .= '<tr class="noclick '
  2064. . ($odd_row ? 'odd' : 'even') . '">';
  2065. }
  2066. }
  2067. return $html_output;
  2068. }
  2069. /**
  2070. * Returns edit link for a user.
  2071. *
  2072. * @param string $username User name
  2073. * @param string $hostname Host name
  2074. * @param string $dbname Database name
  2075. * @param string $tablename Table name
  2076. *
  2077. * @return string HTML code with link
  2078. */
  2079. function PMA_getUserEditLink($username, $hostname, $dbname = '', $tablename = '')
  2080. {
  2081. return '<a class="edit_user_anchor ajax"'
  2082. . ' href="server_privileges.php'
  2083. . PMA_URL_getCommon(
  2084. array(
  2085. 'username' => $username,
  2086. 'hostname' => $hostname,
  2087. 'dbname' => $dbname,
  2088. 'tablename' => $tablename,
  2089. )
  2090. )
  2091. . '">'
  2092. . PMA_Util::getIcon('b_usredit.png', __('Edit Privileges'))
  2093. . '</a>';
  2094. }
  2095. /**
  2096. * Returns revoke link for a user.
  2097. *
  2098. * @param string $username User name
  2099. * @param string $hostname Host name
  2100. * @param string $dbname Database name
  2101. * @param string $tablename Table name
  2102. *
  2103. * @return string HTML code with link
  2104. */
  2105. function PMA_getUserRevokeLink($username, $hostname, $dbname = '', $tablename = '')
  2106. {
  2107. return '<a href="server_privileges.php'
  2108. . PMA_URL_getCommon(
  2109. array(
  2110. 'username' => $username,
  2111. 'hostname' => $hostname,
  2112. 'dbname' => $dbname,
  2113. 'tablename' => $tablename,
  2114. 'revokeall' => 1,
  2115. )
  2116. )
  2117. . '">'
  2118. . PMA_Util::getIcon('b_usrdrop.png', __('Revoke'))
  2119. . '</a>';
  2120. }
  2121. /**
  2122. * Returns export link for a user.
  2123. *
  2124. * @param string $username User name
  2125. * @param string $hostname Host name
  2126. * @param string $initial Initial value
  2127. *
  2128. * @return HTML code with link
  2129. */
  2130. function PMA_getUserExportLink($username, $hostname, $initial = '')
  2131. {
  2132. return '<a class="export_user_anchor ajax"'
  2133. . ' href="server_privileges.php'
  2134. . PMA_URL_getCommon(
  2135. array(
  2136. 'username' => $username,
  2137. 'hostname' => $hostname,
  2138. 'initial' => $initial,
  2139. 'export' => 1,
  2140. )
  2141. )
  2142. . '">'
  2143. . PMA_Util::getIcon('b_tblexport.png', __('Export'))
  2144. . '</a>';
  2145. }
  2146. /**
  2147. * Returns user group edit link
  2148. *
  2149. * @param string $username User name
  2150. *
  2151. * @return HTML code with link
  2152. */
  2153. function PMA_getUserGroupEditLink($username)
  2154. {
  2155. return '<a class="edit_user_group_anchor ajax"'
  2156. . ' href="server_privileges.php'
  2157. . PMA_URL_getCommon(array('username' => $username))
  2158. . '">'
  2159. . PMA_Util::getIcon('b_usrlist.png', __('Edit user group'))
  2160. . '</a>';
  2161. }
  2162. /**
  2163. * Returns number of defined user groups
  2164. *
  2165. * @return integer $user_group_count
  2166. */
  2167. function PMA_getUserGroupCount()
  2168. {
  2169. $user_group_table = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
  2170. . '.' . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']);
  2171. $sql_query = 'SELECT COUNT(*) FROM ' . $user_group_table;
  2172. $user_group_count = $GLOBALS['dbi']->fetchValue(
  2173. $sql_query, 0, 0, $GLOBALS['controllink']
  2174. );
  2175. return $user_group_count;
  2176. }
  2177. /**
  2178. * This function return the extra data array for the ajax behavior
  2179. *
  2180. * @param string $password password
  2181. * @param string $sql_query sql query
  2182. * @param string $hostname hostname
  2183. * @param string $username username
  2184. *
  2185. * @return array $extra_data
  2186. */
  2187. function PMA_getExtraDataForAjaxBehavior(
  2188. $password, $sql_query, $hostname, $username
  2189. ) {
  2190. if (isset($GLOBALS['dbname'])) {
  2191. //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
  2192. if (preg_match('/(?<!\\\\)(?:_|%)/i', $GLOBALS['dbname'])) {
  2193. $dbname_is_wildcard = true;
  2194. } else {
  2195. $dbname_is_wildcard = false;
  2196. }
  2197. }
  2198. $user_group_count = 0;
  2199. if ($GLOBALS['cfgRelation']['menuswork']) {
  2200. $user_group_count = PMA_getUserGroupCount();
  2201. }
  2202. $extra_data = array();
  2203. if (strlen($sql_query)) {
  2204. $extra_data['sql_query']
  2205. = PMA_Util::getMessage(null, $sql_query);
  2206. }
  2207. if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
  2208. /**
  2209. * generate html on the fly for the new user that was just created.
  2210. */
  2211. $new_user_string = '<tr>' . "\n"
  2212. . '<td> <input type="checkbox" name="selected_usr[]" '
  2213. . 'id="checkbox_sel_users_"'
  2214. . 'value="'
  2215. . htmlspecialchars($username)
  2216. . '&amp;#27;' . htmlspecialchars($hostname) . '" />'
  2217. . '</td>' . "\n"
  2218. . '<td><label for="checkbox_sel_users_">'
  2219. . (empty($_REQUEST['username'])
  2220. ? '<span style="color: #FF0000">' . __('Any') . '</span>'
  2221. : htmlspecialchars($username) ) . '</label></td>' . "\n"
  2222. . '<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
  2223. $new_user_string .= '<td>';
  2224. if (! empty($password) || isset($_POST['pma_pw'])) {
  2225. $new_user_string .= __('Yes');
  2226. } else {
  2227. $new_user_string .= '<span style="color: #FF0000">'
  2228. . __('No')
  2229. . '</span>';
  2230. };
  2231. $new_user_string .= '</td>' . "\n";
  2232. $new_user_string .= '<td>'
  2233. . '<code>' . join(', ', PMA_extractPrivInfo('', true)) . '</code>'
  2234. . '</td>'; //Fill in privileges here
  2235. // if $cfg['Servers'][$i]['users'] and $cfg['Servers'][$i]['usergroups'] are
  2236. // enabled
  2237. $cfgRelation = PMA_getRelationsParam();
  2238. if (isset($cfgRelation['users']) && isset($cfgRelation['usergroups'])) {
  2239. $new_user_string .= '<td class="usrGroup"></td>';
  2240. }
  2241. $new_user_string .= '<td>';
  2242. if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')) {
  2243. $new_user_string .= __('Yes');
  2244. } else {
  2245. $new_user_string .= __('No');
  2246. }
  2247. $new_user_string .='</td>';
  2248. $new_user_string .= '<td>'
  2249. . PMA_getUserEditLink($username, $hostname)
  2250. . '</td>' . "\n";
  2251. if (isset($cfgRelation['menuswork']) && $user_group_count > 0) {
  2252. $new_user_string .= '<td>'
  2253. . PMA_getUserGroupEditLink($username)
  2254. . '</td>' . "\n";
  2255. }
  2256. $new_user_string .= '<td>'
  2257. . PMA_getUserExportLink(
  2258. $username,
  2259. $hostname,
  2260. isset($_GET['initial']) ? $_GET['initial'] : ''
  2261. )
  2262. . '</td>' . "\n";
  2263. $new_user_string .= '</tr>';
  2264. $extra_data['new_user_string'] = $new_user_string;
  2265. /**
  2266. * Generate the string for this alphabet's initial, to update the user
  2267. * pagination
  2268. */
  2269. $new_user_initial = strtoupper(substr($username, 0, 1));
  2270. $newUserInitialString = '<a href="server_privileges.php'
  2271. . PMA_URL_getCommon(array('initial' => $new_user_initial)) . '">'
  2272. . $new_user_initial . '</a>';
  2273. $extra_data['new_user_initial'] = $new_user_initial;
  2274. $extra_data['new_user_initial_string'] = $newUserInitialString;
  2275. }
  2276. if (isset($_POST['update_privs'])) {
  2277. $extra_data['db_specific_privs'] = false;
  2278. $extra_data['db_wildcard_privs'] = false;
  2279. if (isset($dbname_is_wildcard)) {
  2280. $extra_data['db_specific_privs'] = ! $dbname_is_wildcard;
  2281. $extra_data['db_wildcard_privs'] = $dbname_is_wildcard;
  2282. }
  2283. $new_privileges = join(', ', PMA_extractPrivInfo('', true));
  2284. $extra_data['new_privileges'] = $new_privileges;
  2285. }
  2286. if (isset($_REQUEST['validate_username'])) {
  2287. $sql_query = "SELECT * FROM `mysql`.`user` WHERE `User` = '"
  2288. . $_REQUEST['username'] . "';";
  2289. $res = $GLOBALS['dbi']->query($sql_query);
  2290. $row = $GLOBALS['dbi']->fetchRow($res);
  2291. if (empty($row)) {
  2292. $extra_data['user_exists'] = false;
  2293. } else {
  2294. $extra_data['user_exists'] = true;
  2295. }
  2296. }
  2297. return $extra_data;
  2298. }
  2299. /**
  2300. * Get the HTML snippet for change user login information
  2301. *
  2302. * @param string $username username
  2303. * @param string $hostname host name
  2304. *
  2305. * @return string HTML snippet
  2306. */
  2307. function PMA_getChangeLoginInformationHtmlForm($username, $hostname)
  2308. {
  2309. $choices = array(
  2310. '4' => __('… keep the old one.'),
  2311. '1' => __('… delete the old one from the user tables.'),
  2312. '2' => __(
  2313. '… revoke all active privileges from '
  2314. . 'the old one and delete it afterwards.'
  2315. ),
  2316. '3' => __(
  2317. '… delete the old one from the user tables '
  2318. . 'and reload the privileges afterwards.'
  2319. )
  2320. );
  2321. $html_output = '<form action="server_privileges.php" '
  2322. . 'method="post" class="copyUserForm ajax submenu-item">' . "\n"
  2323. . PMA_URL_getHiddenInputs('', '')
  2324. . '<input type="hidden" name="old_username" '
  2325. . 'value="' . htmlspecialchars($username) . '" />' . "\n"
  2326. . '<input type="hidden" name="old_hostname" '
  2327. . 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
  2328. . '<fieldset id="fieldset_change_copy_user">' . "\n"
  2329. . '<legend data-submenu-label="' . __('Login Information') . '">' . "\n"
  2330. . __('Change Login Information / Copy User')
  2331. . '</legend>' . "\n"
  2332. . PMA_getHtmlForLoginInformationFields('change');
  2333. $html_output .= '<fieldset id="fieldset_mode">' . "\n"
  2334. . ' <legend>'
  2335. . __('Create a new user with the same privileges and …')
  2336. . '</legend>' . "\n";
  2337. $html_output .= PMA_Util::getRadioFields(
  2338. 'mode', $choices, '4', true
  2339. );
  2340. $html_output .= '</fieldset>' . "\n"
  2341. . '</fieldset>' . "\n";
  2342. $html_output .= '<fieldset id="fieldset_change_copy_user_footer" '
  2343. . 'class="tblFooters">' . "\n"
  2344. . '<input type="submit" name="change_copy" '
  2345. . 'value="' . __('Go') . '" />' . "\n"
  2346. . '</fieldset>' . "\n"
  2347. . '</form>' . "\n";
  2348. return $html_output;
  2349. }
  2350. /**
  2351. * Provide a line with links to the relevant database and table
  2352. *
  2353. * @param string $url_dbname url database name that urlencode() string
  2354. * @param string $dbname database name
  2355. * @param string $tablename table name
  2356. *
  2357. * @return string HTML snippet
  2358. */
  2359. function PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename)
  2360. {
  2361. $html_output = '[ ' . __('Database')
  2362. . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase']
  2363. . PMA_URL_getCommon(
  2364. array(
  2365. 'db' => $url_dbname,
  2366. 'reload' => 1
  2367. )
  2368. )
  2369. . '">'
  2370. . htmlspecialchars($dbname) . ': '
  2371. . PMA_Util::getTitleForTarget(
  2372. $GLOBALS['cfg']['DefaultTabDatabase']
  2373. )
  2374. . "</a> ]\n";
  2375. if (strlen($tablename)) {
  2376. $html_output .= ' [ ' . __('Table') . ' <a href="'
  2377. . $GLOBALS['cfg']['DefaultTabTable']
  2378. . PMA_URL_getCommon(
  2379. array(
  2380. 'db' => $url_dbname,
  2381. 'table' => $tablename,
  2382. 'reload' => 1,
  2383. )
  2384. )
  2385. . '">' . htmlspecialchars($tablename) . ': '
  2386. . PMA_Util::getTitleForTarget(
  2387. $GLOBALS['cfg']['DefaultTabTable']
  2388. )
  2389. . "</a> ]\n";
  2390. }
  2391. return $html_output;
  2392. }
  2393. /**
  2394. * no db name given, so we want all privs for the given user
  2395. * db name was given, so we want all user specific rights for this db
  2396. * So this function returns user rights as an array
  2397. *
  2398. * @param array $tables tables
  2399. * @param string $user_host_condition a where clause that containd user's host
  2400. * condition
  2401. * @param string $dbname database name
  2402. *
  2403. * @return array $db_rights database rights
  2404. */
  2405. function PMA_getUserSpecificRights($tables, $user_host_condition, $dbname)
  2406. {
  2407. if (! strlen($dbname)) {
  2408. $tables_to_search_for_users = array(
  2409. 'tables_priv', 'columns_priv',
  2410. );
  2411. $dbOrTableName = 'Db';
  2412. } else {
  2413. $user_host_condition .=
  2414. ' AND `Db`'
  2415. . ' LIKE \''
  2416. . PMA_Util::sqlAddSlashes($dbname, true) . "'";
  2417. $tables_to_search_for_users = array('columns_priv',);
  2418. $dbOrTableName = 'Table_name';
  2419. }
  2420. $db_rights_sqls = array();
  2421. foreach ($tables_to_search_for_users as $table_search_in) {
  2422. if (in_array($table_search_in, $tables)) {
  2423. $db_rights_sqls[] = '
  2424. SELECT DISTINCT `' . $dbOrTableName . '`
  2425. FROM `mysql`.' . PMA_Util::backquote($table_search_in)
  2426. . $user_host_condition;
  2427. }
  2428. }
  2429. $user_defaults = array(
  2430. $dbOrTableName => '',
  2431. 'Grant_priv' => 'N',
  2432. 'privs' => array('USAGE'),
  2433. 'Column_priv' => true,
  2434. );
  2435. // for the rights
  2436. $db_rights = array();
  2437. $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
  2438. . ' ORDER BY `' . $dbOrTableName . '` ASC';
  2439. $db_rights_result = $GLOBALS['dbi']->query($db_rights_sql);
  2440. while ($db_rights_row = $GLOBALS['dbi']->fetchAssoc($db_rights_result)) {
  2441. $db_rights_row = array_merge($user_defaults, $db_rights_row);
  2442. if (! strlen($dbname)) {
  2443. // only Db names in the table `mysql`.`db` uses wildcards
  2444. // as we are in the db specific rights display we want
  2445. // all db names escaped, also from other sources
  2446. $db_rights_row['Db'] = PMA_Util::escapeMysqlWildcards(
  2447. $db_rights_row['Db']
  2448. );
  2449. }
  2450. $db_rights[$db_rights_row[$dbOrTableName]] = $db_rights_row;
  2451. }
  2452. $GLOBALS['dbi']->freeResult($db_rights_result);
  2453. if (! strlen($dbname)) {
  2454. $sql_query = 'SELECT * FROM `mysql`.`db`'
  2455. . $user_host_condition . ' ORDER BY `Db` ASC';
  2456. } else {
  2457. $sql_query = 'SELECT `Table_name`,'
  2458. . ' `Table_priv`,'
  2459. . ' IF(`Column_priv` = _latin1 \'\', 0, 1)'
  2460. . ' AS \'Column_priv\''
  2461. . ' FROM `mysql`.`tables_priv`'
  2462. . $user_host_condition
  2463. . ' ORDER BY `Table_name` ASC;';
  2464. }
  2465. $result = $GLOBALS['dbi']->query($sql_query);
  2466. $sql_query = '';
  2467. while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
  2468. if (isset($db_rights[$row[$dbOrTableName]])) {
  2469. $db_rights[$row[$dbOrTableName]]
  2470. = array_merge($db_rights[$row[$dbOrTableName]], $row);
  2471. } else {
  2472. $db_rights[$row[$dbOrTableName]] = $row;
  2473. }
  2474. if (! strlen($dbname)) {
  2475. // there are db specific rights for this user
  2476. // so we can drop this db rights
  2477. $db_rights[$row['Db']]['can_delete'] = true;
  2478. }
  2479. }
  2480. $GLOBALS['dbi']->freeResult($result);
  2481. return $db_rights;
  2482. }
  2483. /**
  2484. * Display user rights in table rows(Table specific or database specific privs)
  2485. *
  2486. * @param array $db_rights user's database rights array
  2487. * @param string $dbname database name
  2488. * @param string $hostname host name
  2489. * @param string $username username
  2490. *
  2491. * @return array $found_rows, $html_output
  2492. */
  2493. function PMA_getHtmlForUserRights($db_rights, $dbname,
  2494. $hostname, $username
  2495. ) {
  2496. $html_output = '';
  2497. $found_rows = array();
  2498. // display rows
  2499. if (count($db_rights) < 1) {
  2500. $html_output .= '<tr class="odd">' . "\n"
  2501. . '<td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
  2502. . '</tr>' . "\n";
  2503. } else {
  2504. $odd_row = true;
  2505. //while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
  2506. foreach ($db_rights as $row) {
  2507. $found_rows[] = (! strlen($dbname)) ? $row['Db'] : $row['Table_name'];
  2508. $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
  2509. . '<td>'
  2510. . htmlspecialchars(
  2511. (! strlen($dbname)) ? $row['Db'] : $row['Table_name']
  2512. )
  2513. . '</td>' . "\n"
  2514. . '<td><code>' . "\n"
  2515. . ' '
  2516. . join(
  2517. ',' . "\n" . ' ',
  2518. PMA_extractPrivInfo($row, true)
  2519. ) . "\n"
  2520. . '</code></td>' . "\n"
  2521. . '<td>'
  2522. . ((((! strlen($dbname)) && $row['Grant_priv'] == 'Y')
  2523. || (strlen($dbname)
  2524. && in_array('Grant', explode(',', $row['Table_priv']))))
  2525. ? __('Yes')
  2526. : __('No'))
  2527. . '</td>' . "\n"
  2528. . '<td>';
  2529. if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
  2530. $html_output .= __('Yes');
  2531. } else {
  2532. $html_output .= __('No');
  2533. }
  2534. $html_output .= '</td>' . "\n"
  2535. . '<td>';
  2536. $html_output .= PMA_getUserEditLink(
  2537. $username,
  2538. $hostname,
  2539. (! strlen($dbname)) ? $row['Db'] : $dbname,
  2540. (! strlen($dbname)) ? '' : $row['Table_name']
  2541. );
  2542. $html_output .= '</td>' . "\n"
  2543. . ' <td>';
  2544. if (! empty($row['can_delete'])
  2545. || isset($row['Table_name'])
  2546. && strlen($row['Table_name'])
  2547. ) {
  2548. $html_output .= PMA_getUserRevokeLink(
  2549. $username,
  2550. $hostname,
  2551. (! strlen($dbname)) ? $row['Db'] : $dbname,
  2552. (! strlen($dbname)) ? '' : $row['Table_name']
  2553. );
  2554. }
  2555. $html_output .= '</td>' . "\n"
  2556. . '</tr>' . "\n";
  2557. $odd_row = ! $odd_row;
  2558. } // end while
  2559. } //end if
  2560. return array($found_rows, $html_output);
  2561. }
  2562. /**
  2563. * Get a HTML table for display user's tabel specific or database specific rights
  2564. *
  2565. * @param string $username username
  2566. * @param string $hostname host name
  2567. * @param string $dbname database name
  2568. *
  2569. * @return array $html_output, $found_rows
  2570. */
  2571. function PMA_getHtmlForAllTableSpecificRights(
  2572. $username, $hostname, $dbname
  2573. ) {
  2574. // table header
  2575. $html_output = PMA_URL_getHiddenInputs('', '')
  2576. . '<input type="hidden" name="username" '
  2577. . 'value="' . htmlspecialchars($username) . '" />' . "\n"
  2578. . '<input type="hidden" name="hostname" '
  2579. . 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
  2580. . '<fieldset>' . "\n"
  2581. . '<legend data-submenu-label="'
  2582. . (! strlen($dbname)
  2583. ? __('Database')
  2584. : __('Table')
  2585. )
  2586. . '">'
  2587. . (! strlen($dbname)
  2588. ? __('Database-specific privileges')
  2589. : __('Table-specific privileges')
  2590. )
  2591. . '</legend>' . "\n"
  2592. . '<table class="data">' . "\n"
  2593. . '<thead>' . "\n"
  2594. . '<tr><th>'
  2595. . (! strlen($dbname) ? __('Database') : __('Table'))
  2596. . '</th>' . "\n"
  2597. . '<th>' . __('Privileges') . '</th>' . "\n"
  2598. . '<th>' . __('Grant') . '</th>' . "\n"
  2599. . '<th>'
  2600. . (! strlen($dbname)
  2601. ? __('Table-specific privileges')
  2602. : __('Column-specific privileges')
  2603. )
  2604. . '</th>' . "\n"
  2605. . '<th colspan="2">' . __('Action') . '</th>' . "\n"
  2606. . '</tr>' . "\n"
  2607. . '</thead>' . "\n";
  2608. $user_host_condition = ' WHERE `User`'
  2609. . ' = \'' . PMA_Util::sqlAddSlashes($username) . "'"
  2610. . ' AND `Host`'
  2611. . ' = \'' . PMA_Util::sqlAddSlashes($hostname) . "'";
  2612. // table body
  2613. // get data
  2614. // we also want privielgs for this user not in table `db` but in other table
  2615. $tables = $GLOBALS['dbi']->fetchResult('SHOW TABLES FROM `mysql`;');
  2616. /**
  2617. * no db name given, so we want all privs for the given user
  2618. * db name was given, so we want all user specific rights for this db
  2619. */
  2620. $db_rights = PMA_getUserSpecificRights($tables, $user_host_condition, $dbname);
  2621. ksort($db_rights);
  2622. $html_output .= '<tbody>' . "\n";
  2623. // display rows
  2624. list ($found_rows, $html_out) = PMA_getHtmlForUserRights(
  2625. $db_rights, $dbname, $hostname, $username
  2626. );
  2627. $html_output .= $html_out;
  2628. $html_output .= '</tbody>' . "\n";
  2629. $html_output .='</table>' . "\n";
  2630. return array($html_output, $found_rows);
  2631. }
  2632. /**
  2633. * Get HTML for display select db
  2634. *
  2635. * @param array $found_rows isset($dbname)) ? $row['Db'] : $row['Table_name']
  2636. *
  2637. * @return string HTML snippet
  2638. */
  2639. function PMA_getHtmlForSelectDbInEditPrivs($found_rows)
  2640. {
  2641. // we already have the list of databases from libraries/common.inc.php
  2642. // via $pma = new PMA;
  2643. $pred_db_array = $GLOBALS['pma']->databases;
  2644. $databases_to_skip = array('information_schema', 'performance_schema');
  2645. $html_output = '<label for="text_dbname">'
  2646. . __('Add privileges on the following database:') . '</label>' . "\n";
  2647. if (! empty($pred_db_array)) {
  2648. $html_output .= '<select name="pred_dbname" class="autosubmit">' . "\n"
  2649. . '<option value="" selected="selected">'
  2650. . __('Use text field:') . '</option>' . "\n";
  2651. foreach ($pred_db_array as $current_db) {
  2652. if (in_array($current_db, $databases_to_skip)) {
  2653. continue;
  2654. }
  2655. $current_db_show = $current_db;
  2656. $current_db = PMA_Util::escapeMysqlWildcards($current_db);
  2657. // cannot use array_diff() once, outside of the loop,
  2658. // because the list of databases has special characters
  2659. // already escaped in $found_rows,
  2660. // contrary to the output of SHOW DATABASES
  2661. if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
  2662. $html_output .= '<option value="'
  2663. . htmlspecialchars($current_db) . '">'
  2664. . htmlspecialchars($current_db_show) . '</option>' . "\n";
  2665. }
  2666. }
  2667. $html_output .= '</select>' . "\n";
  2668. }
  2669. $html_output .= '<input type="text" id="text_dbname" name="dbname" '
  2670. . 'required="required" />'
  2671. . "\n"
  2672. . PMA_Util::showHint(
  2673. __('Wildcards % and _ should be escaped with a \ to use them literally.')
  2674. );
  2675. return $html_output;
  2676. }
  2677. /**
  2678. * Get HTML for display table in edit privilege
  2679. *
  2680. * @param string $dbname database naame
  2681. * @param array $found_rows isset($dbname)) ? $row['Db'] : $row['Table_name']
  2682. *
  2683. * @return string HTML snippet
  2684. */
  2685. function PMA_displayTablesInEditPrivs($dbname, $found_rows)
  2686. {
  2687. $html_output = '<input type="hidden" name="dbname"
  2688. ' . 'value="' . htmlspecialchars($dbname) . '"/>' . "\n";
  2689. $html_output .= '<label for="text_tablename">'
  2690. . __('Add privileges on the following table:') . '</label>' . "\n";
  2691. $result = @$GLOBALS['dbi']->tryQuery(
  2692. 'SHOW TABLES FROM ' . PMA_Util::backquote(
  2693. PMA_Util::unescapeMysqlWildcards($dbname)
  2694. ) . ';',
  2695. null,
  2696. PMA_DatabaseInterface::QUERY_STORE
  2697. );
  2698. if ($result) {
  2699. $pred_tbl_array = array();
  2700. while ($row = $GLOBALS['dbi']->fetchRow($result)) {
  2701. if (! isset($found_rows) || ! in_array($row[0], $found_rows)) {
  2702. $pred_tbl_array[] = $row[0];
  2703. }
  2704. }
  2705. $GLOBALS['dbi']->freeResult($result);
  2706. if (! empty($pred_tbl_array)) {
  2707. $html_output .= '<select name="pred_tablename" '
  2708. . 'class="autosubmit">' . "\n"
  2709. . '<option value="" selected="selected">' . __('Use text field')
  2710. . ':</option>' . "\n";
  2711. foreach ($pred_tbl_array as $current_table) {
  2712. $html_output .= '<option '
  2713. . 'value="' . htmlspecialchars($current_table) . '">'
  2714. . htmlspecialchars($current_table)
  2715. . '</option>' . "\n";
  2716. }
  2717. $html_output .= '</select>' . "\n";
  2718. }
  2719. }
  2720. $html_output .= '<input type="text" id="text_tablename" name="tablename" />'
  2721. . "\n";
  2722. return $html_output;
  2723. }
  2724. /**
  2725. * Get HTML for display the users overview
  2726. * (if less than 50 users, display them immediately)
  2727. *
  2728. * @param array $result ran sql query
  2729. * @param array $db_rights user's database rights array
  2730. * @param string $pmaThemeImage a image source link
  2731. * @param string $text_dir text directory
  2732. *
  2733. * @return string HTML snippet
  2734. */
  2735. function PMA_getUsersOverview($result, $db_rights, $pmaThemeImage, $text_dir)
  2736. {
  2737. while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
  2738. $row['privs'] = PMA_extractPrivInfo($row, true);
  2739. $db_rights[$row['User']][$row['Host']] = $row;
  2740. }
  2741. @$GLOBALS['dbi']->freeResult($result);
  2742. $user_group_count = 0;
  2743. if ($GLOBALS['cfgRelation']['menuswork']) {
  2744. $user_group_count = PMA_getUserGroupCount();
  2745. }
  2746. $html_output
  2747. = '<form name="usersForm" id="usersForm" action="server_privileges.php" '
  2748. . 'method="post">' . "\n"
  2749. . PMA_URL_getHiddenInputs('', '')
  2750. . '<table id="tableuserrights" class="data">' . "\n"
  2751. . '<thead>' . "\n"
  2752. . '<tr><th></th>' . "\n"
  2753. . '<th>' . __('User') . '</th>' . "\n"
  2754. . '<th>' . __('Host') . '</th>' . "\n"
  2755. . '<th>' . __('Password') . '</th>' . "\n"
  2756. . '<th>' . __('Global privileges') . ' '
  2757. . PMA_Util::showHint(
  2758. __('Note: MySQL privilege names are expressed in English.')
  2759. )
  2760. . '</th>' . "\n";
  2761. if ($GLOBALS['cfgRelation']['menuswork']) {
  2762. $html_output .= '<th>' . __('User group') . '</th>' . "\n";
  2763. }
  2764. $html_output .= '<th>' . __('Grant') . '</th>' . "\n"
  2765. . '<th colspan="' . ($user_group_count > 0 ? '3' : '2') . '">'
  2766. . __('Action') . '</th>' . "\n"
  2767. . '</tr>' . "\n"
  2768. . '</thead>' . "\n";
  2769. $html_output .= '<tbody>' . "\n";
  2770. $html_output .= PMA_getHtmlTableBodyForUserRights($db_rights);
  2771. $html_output .= '</tbody>'
  2772. . '</table>' . "\n";
  2773. $html_output .= '<div style="float:left;">'
  2774. . '<img class="selectallarrow"'
  2775. . ' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
  2776. . ' width="38" height="22"'
  2777. . ' alt="' . __('With selected:') . '" />' . "\n"
  2778. . '<input type="checkbox" id="usersForm_checkall" class="checkall_box" '
  2779. . 'title="' . __('Check All') . '" /> '
  2780. . '<label for="usersForm_checkall">' . __('Check All') . '</label> '
  2781. . '<i style="margin-left: 2em">' . __('With selected:') . '</i>' . "\n";
  2782. $html_output .= PMA_Util::getButtonOrImage(
  2783. 'submit_mult', 'mult_submit', 'submit_mult_export',
  2784. __('Export'), 'b_tblexport.png', 'export'
  2785. );
  2786. $html_output .= '<input type="hidden" name="initial" '
  2787. . 'value="' . (isset($_GET['initial']) ? $_GET['initial'] : '') . '" />';
  2788. $html_output .= '</div>'
  2789. . '<div class="clear_both" style="clear:both"></div>';
  2790. // add/delete user fieldset
  2791. $html_output .= PMA_getFieldsetForAddDeleteUser();
  2792. $html_output .= '</form>' . "\n";
  2793. return $html_output;
  2794. }
  2795. /**
  2796. * Get table body for 'tableuserrights' table in userform
  2797. *
  2798. * @param array $db_rights user's database rights array
  2799. *
  2800. * @return string HTML snippet
  2801. */
  2802. function PMA_getHtmlTableBodyForUserRights($db_rights)
  2803. {
  2804. if ($GLOBALS['cfgRelation']['menuswork']) {
  2805. $users_table = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
  2806. . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']);
  2807. $sql_query = 'SELECT * FROM ' . $users_table;
  2808. $result = PMA_queryAsControlUser($sql_query, false);
  2809. $group_assignment = array();
  2810. if ($result) {
  2811. while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
  2812. $group_assignment[$row['username']] = $row['usergroup'];
  2813. }
  2814. }
  2815. $GLOBALS['dbi']->freeResult($result);
  2816. $user_group_count = PMA_getUserGroupCount();
  2817. }
  2818. $odd_row = true;
  2819. $index_checkbox = 0;
  2820. $html_output = '';
  2821. foreach ($db_rights as $user) {
  2822. ksort($user);
  2823. foreach ($user as $host) {
  2824. $index_checkbox++;
  2825. $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">'
  2826. . "\n";
  2827. $html_output .= '<td>'
  2828. . '<input type="checkbox" class="checkall" name="selected_usr[]" '
  2829. . 'id="checkbox_sel_users_'
  2830. . $index_checkbox . '" value="'
  2831. . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
  2832. . '"'
  2833. . ' /></td>' . "\n";
  2834. $html_output .= '<td><label '
  2835. . 'for="checkbox_sel_users_' . $index_checkbox . '">'
  2836. . (empty($host['User'])
  2837. ? '<span style="color: #FF0000">' . __('Any') . '</span>'
  2838. : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
  2839. . '<td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
  2840. $html_output .= '<td>';
  2841. switch ($host['Password']) {
  2842. case 'Y':
  2843. $html_output .= __('Yes');
  2844. break;
  2845. case 'N':
  2846. $html_output .= '<span style="color: #FF0000">' . __('No')
  2847. . '</span>';
  2848. break;
  2849. // this happens if this is a definition not coming from mysql.user
  2850. default:
  2851. $html_output .= '--'; // in future version, replace by "not present"
  2852. break;
  2853. } // end switch
  2854. $html_output .= '</td>' . "\n";
  2855. $html_output .= '<td><code>' . "\n"
  2856. . '' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
  2857. . '</code></td>' . "\n";
  2858. if ($GLOBALS['cfgRelation']['menuswork']) {
  2859. $html_output .= '<td class="usrGroup">' . "\n"
  2860. . (isset($group_assignment[$host['User']])
  2861. ? $group_assignment[$host['User']]
  2862. : ''
  2863. )
  2864. . '</td>' . "\n";
  2865. }
  2866. $html_output .= '<td>'
  2867. . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No'))
  2868. . '</td>' . "\n";
  2869. $html_output .= '<td class="center">'
  2870. . PMA_getUserEditLink(
  2871. $host['User'],
  2872. $host['Host']
  2873. )
  2874. . '</td>';
  2875. if ($GLOBALS['cfgRelation']['menuswork'] && $user_group_count > 0) {
  2876. if (empty($host['User'])) {
  2877. $html_output .= '<td class="center"></td>';
  2878. } else {
  2879. $html_output .= '<td class="center">'
  2880. . PMA_getUserGroupEditLink($host['User'])
  2881. . '</td>';
  2882. }
  2883. }
  2884. $html_output .= '<td class="center">'
  2885. . PMA_getUserExportLink(
  2886. $host['User'],
  2887. $host['Host'],
  2888. isset($_GET['initial']) ? $_GET['initial'] : ''
  2889. )
  2890. . '</td>';
  2891. $html_output .= '</tr>';
  2892. $odd_row = ! $odd_row;
  2893. }
  2894. }
  2895. return $html_output;
  2896. }
  2897. /**
  2898. * Get HTML fieldset for Add/Delete user
  2899. *
  2900. * @return string HTML snippet
  2901. */
  2902. function PMA_getFieldsetForAddDeleteUser()
  2903. {
  2904. $html_output = '<fieldset id="fieldset_add_user">' . "\n";
  2905. $html_output .= '<a href="server_privileges.php'
  2906. . PMA_URL_getCommon(array('adduser' => 1))
  2907. . '" class="ajax">' . "\n"
  2908. . PMA_Util::getIcon('b_usradd.png')
  2909. . ' ' . __('Add user') . '</a>' . "\n";
  2910. $html_output .= '</fieldset>' . "\n";
  2911. $html_output .= '<fieldset id="fieldset_delete_user">'
  2912. . '<legend>' . "\n"
  2913. . PMA_Util::getIcon('b_usrdrop.png')
  2914. . ' ' . __('Remove selected users') . '' . "\n"
  2915. . '</legend>' . "\n";
  2916. $html_output .= '<input type="hidden" name="mode" value="2" />' . "\n"
  2917. . '('
  2918. . __(
  2919. 'Revoke all active privileges from the users '
  2920. . 'and delete them afterwards.'
  2921. )
  2922. . ')'
  2923. . '<br />' . "\n";
  2924. $html_output .= '<input type="checkbox" '
  2925. . 'title="'
  2926. . __('Drop the databases that have the same names as the users.')
  2927. . '" '
  2928. . 'name="drop_users_db" id="checkbox_drop_users_db" />' . "\n";
  2929. $html_output .= '<label for="checkbox_drop_users_db" '
  2930. . 'title="'
  2931. . __('Drop the databases that have the same names as the users.')
  2932. . '">' . "\n"
  2933. . ' '
  2934. . __('Drop the databases that have the same names as the users.')
  2935. . "\n"
  2936. . '</label>' . "\n"
  2937. . '</fieldset>' . "\n";
  2938. $html_output .= '<fieldset id="fieldset_delete_user_footer" class="tblFooters">'
  2939. . "\n";
  2940. $html_output .= '<input type="submit" name="delete" '
  2941. . 'value="' . __('Go') . '" id="buttonGo" '
  2942. . 'class="ajax"/>' . "\n";
  2943. $html_output .= '</fieldset>' . "\n";
  2944. return $html_output;
  2945. }
  2946. /**
  2947. * Get HTML for Displays the initials
  2948. *
  2949. * @param array $array_initials array for all initials, even non A-Z
  2950. *
  2951. * @return string HTML snippet
  2952. */
  2953. function PMA_getHtmlForInitials($array_initials)
  2954. {
  2955. // initialize to false the letters A-Z
  2956. for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
  2957. if (! isset($array_initials[chr($letter_counter + 64)])) {
  2958. $array_initials[chr($letter_counter + 64)] = false;
  2959. }
  2960. }
  2961. $initials = $GLOBALS['dbi']->tryQuery(
  2962. 'SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC',
  2963. null,
  2964. PMA_DatabaseInterface::QUERY_STORE
  2965. );
  2966. while (list($tmp_initial) = $GLOBALS['dbi']->fetchRow($initials)) {
  2967. $array_initials[$tmp_initial] = true;
  2968. }
  2969. // Display the initials, which can be any characters, not
  2970. // just letters. For letters A-Z, we add the non-used letters
  2971. // as greyed out.
  2972. uksort($array_initials, "strnatcasecmp");
  2973. $html_output = '<table id="initials_table" cellspacing="5">'
  2974. . '<tr>';
  2975. foreach ($array_initials as $tmp_initial => $initial_was_found) {
  2976. if (! empty($tmp_initial)) {
  2977. if ($initial_was_found) {
  2978. $html_output .= '<td>'
  2979. . '<a class="ajax'
  2980. . ((isset($_REQUEST['initial'])
  2981. && $_REQUEST['initial'] === $tmp_initial
  2982. ) ? ' active' : '')
  2983. . '" href="server_privileges.php'
  2984. . PMA_URL_getCommon(array('initial' => $tmp_initial))
  2985. . '">' . $tmp_initial
  2986. . '</a>'
  2987. . '</td>' . "\n";
  2988. } else {
  2989. $html_output .= '<td>' . $tmp_initial . '</td>';
  2990. }
  2991. }
  2992. }
  2993. $html_output .= '<td>'
  2994. . '<a href="server_privileges.php'
  2995. . PMA_URL_getCommon(array('showall' => 1))
  2996. . '" class="nowrap">' . __('Show all') . '</a></td>' . "\n";
  2997. $html_output .= '</tr></table>';
  2998. return $html_output;
  2999. }
  3000. /**
  3001. * Get the database rigths array for Display user overview
  3002. *
  3003. * @return array $db_rights database rights array
  3004. */
  3005. function PMA_getDbRightsForUserOverview()
  3006. {
  3007. // we also want users not in table `user` but in other table
  3008. $tables = $GLOBALS['dbi']->fetchResult('SHOW TABLES FROM `mysql`;');
  3009. $tablesSearchForUsers = array(
  3010. 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
  3011. );
  3012. $db_rights_sqls = array();
  3013. foreach ($tablesSearchForUsers as $table_search_in) {
  3014. if (in_array($table_search_in, $tables)) {
  3015. $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`'
  3016. . $table_search_in . '` '
  3017. . (isset($_GET['initial'])
  3018. ? PMA_rangeOfUsers($_GET['initial'])
  3019. : '');
  3020. }
  3021. }
  3022. $user_defaults = array(
  3023. 'User' => '',
  3024. 'Host' => '%',
  3025. 'Password' => '?',
  3026. 'Grant_priv' => 'N',
  3027. 'privs' => array('USAGE'),
  3028. );
  3029. // for the rights
  3030. $db_rights = array();
  3031. $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
  3032. . ' ORDER BY `User` ASC, `Host` ASC';
  3033. $db_rights_result = $GLOBALS['dbi']->query($db_rights_sql);
  3034. while ($db_rights_row = $GLOBALS['dbi']->fetchAssoc($db_rights_result)) {
  3035. $db_rights_row = array_merge($user_defaults, $db_rights_row);
  3036. $db_rights[$db_rights_row['User']][$db_rights_row['Host']]
  3037. = $db_rights_row;
  3038. }
  3039. $GLOBALS['dbi']->freeResult($db_rights_result);
  3040. ksort($db_rights);
  3041. return $db_rights;
  3042. }
  3043. /**
  3044. * Delete user and get message and sql query for delete user in privileges
  3045. *
  3046. * @param string $queries queries
  3047. *
  3048. * @return PMA_message
  3049. */
  3050. function PMA_deleteUser($queries)
  3051. {
  3052. if (empty($queries)) {
  3053. $message = PMA_Message::error(__('No users selected for deleting!'));
  3054. } else {
  3055. if ($_REQUEST['mode'] == 3) {
  3056. $queries[] = '# ' . __('Reloading the privileges') . ' …';
  3057. $queries[] = 'FLUSH PRIVILEGES;';
  3058. }
  3059. $drop_user_error = '';
  3060. foreach ($queries as $sql_query) {
  3061. if ($sql_query{0} != '#') {
  3062. if (! $GLOBALS['dbi']->tryQuery($sql_query, $GLOBALS['userlink'])) {
  3063. $drop_user_error .= $GLOBALS['dbi']->getError() . "\n";
  3064. }
  3065. }
  3066. }
  3067. // tracking sets this, causing the deleted db to be shown in navi
  3068. unset($GLOBALS['db']);
  3069. $sql_query = join("\n", $queries);
  3070. if (! empty($drop_user_error)) {
  3071. $message = PMA_Message::rawError($drop_user_error);
  3072. } else {
  3073. $message = PMA_Message::success(
  3074. __('The selected users have been deleted successfully.')
  3075. );
  3076. }
  3077. }
  3078. return array($sql_query, $message);
  3079. }
  3080. /**
  3081. * Update the privileges and return the success or error message
  3082. *
  3083. * @param string $username username
  3084. * @param string $hostname host name
  3085. * @param string $tablename table name
  3086. * @param string $dbname database name
  3087. *
  3088. * @return PMA_message success message or error message for update
  3089. */
  3090. function PMA_updatePrivileges($username, $hostname, $tablename, $dbname)
  3091. {
  3092. $db_and_table = PMA_wildcardEscapeForGrant($dbname, $tablename);
  3093. $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
  3094. . ' FROM \'' . PMA_Util::sqlAddSlashes($username)
  3095. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
  3096. if (! isset($_POST['Grant_priv']) || $_POST['Grant_priv'] != 'Y') {
  3097. $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
  3098. . ' FROM \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
  3099. . PMA_Util::sqlAddSlashes($hostname) . '\';';
  3100. } else {
  3101. $sql_query1 = '';
  3102. }
  3103. // Should not do a GRANT USAGE for a table-specific privilege, it
  3104. // causes problems later (cannot revoke it)
  3105. if (! (strlen($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
  3106. $sql_query2 = 'GRANT ' . join(', ', PMA_extractPrivInfo())
  3107. . ' ON ' . $db_and_table
  3108. . ' TO \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
  3109. . PMA_Util::sqlAddSlashes($hostname) . '\'';
  3110. if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')
  3111. || (! strlen($dbname)
  3112. && (isset($_POST['max_questions']) || isset($_POST['max_connections'])
  3113. || isset($_POST['max_updates'])
  3114. || isset($_POST['max_user_connections'])))
  3115. ) {
  3116. $sql_query2 .= PMA_getWithClauseForAddUserAndUpdatePrivs();
  3117. }
  3118. $sql_query2 .= ';';
  3119. }
  3120. if (! $GLOBALS['dbi']->tryQuery($sql_query0)) {
  3121. // This might fail when the executing user does not have
  3122. // ALL PRIVILEGES himself.
  3123. // See https://sourceforge.net/p/phpmyadmin/bugs/3270/
  3124. $sql_query0 = '';
  3125. }
  3126. if (! empty($sql_query1) && ! $GLOBALS['dbi']->tryQuery($sql_query1)) {
  3127. // this one may fail, too...
  3128. $sql_query1 = '';
  3129. }
  3130. if (! empty($sql_query2)) {
  3131. $GLOBALS['dbi']->query($sql_query2);
  3132. } else {
  3133. $sql_query2 = '';
  3134. }
  3135. $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
  3136. $message = PMA_Message::success(__('You have updated the privileges for %s.'));
  3137. $message->addParam(
  3138. '\'' . htmlspecialchars($username)
  3139. . '\'@\'' . htmlspecialchars($hostname) . '\''
  3140. );
  3141. return array($sql_query, $message);
  3142. }
  3143. /**
  3144. * Get List of information: Changes / copies a user
  3145. *
  3146. * @return array()
  3147. */
  3148. function PMA_getDataForChangeOrCopyUser()
  3149. {
  3150. $row = null;
  3151. $queries = null;
  3152. $password = null;
  3153. if (isset($_REQUEST['change_copy'])) {
  3154. $user_host_condition = ' WHERE `User` = '
  3155. . "'" . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
  3156. . ' AND `Host` = '
  3157. . "'" . PMA_Util::sqlAddSlashes($_REQUEST['old_hostname']) . "';";
  3158. $row = $GLOBALS['dbi']->fetchSingleRow(
  3159. 'SELECT * FROM `mysql`.`user` ' . $user_host_condition
  3160. );
  3161. if (! $row) {
  3162. $response = PMA_Response::getInstance();
  3163. $response->addHTML(
  3164. PMA_Message::notice(__('No user found.'))->getDisplay()
  3165. );
  3166. unset($_REQUEST['change_copy']);
  3167. } else {
  3168. extract($row, EXTR_OVERWRITE);
  3169. // Recent MySQL versions have the field "Password" in mysql.user,
  3170. // so the previous extract creates $Password but this script
  3171. // uses $password
  3172. if (! isset($password) && isset($Password)) {
  3173. $password = $Password;
  3174. }
  3175. $queries = array();
  3176. }
  3177. }
  3178. return array($queries, $password);
  3179. }
  3180. /**
  3181. * Update Data for information: Deletes users
  3182. *
  3183. * @param array $queries queries array
  3184. *
  3185. * @return array
  3186. */
  3187. function PMA_getDataForDeleteUsers($queries)
  3188. {
  3189. if (isset($_REQUEST['change_copy'])) {
  3190. $selected_usr = array(
  3191. $_REQUEST['old_username'] . '&amp;#27;' . $_REQUEST['old_hostname']
  3192. );
  3193. } else {
  3194. $selected_usr = $_REQUEST['selected_usr'];
  3195. $queries = array();
  3196. }
  3197. foreach ($selected_usr as $each_user) {
  3198. list($this_user, $this_host) = explode('&amp;#27;', $each_user);
  3199. $queries[] = '# '
  3200. . sprintf(
  3201. __('Deleting %s'),
  3202. '\'' . $this_user . '\'@\'' . $this_host . '\''
  3203. )
  3204. . ' ...';
  3205. $queries[] = 'DROP USER \''
  3206. . PMA_Util::sqlAddSlashes($this_user)
  3207. . '\'@\'' . PMA_Util::sqlAddSlashes($this_host) . '\';';
  3208. if (isset($_REQUEST['drop_users_db'])) {
  3209. $queries[] = 'DROP DATABASE IF EXISTS '
  3210. . PMA_Util::backquote($this_user) . ';';
  3211. $GLOBALS['reload'] = true;
  3212. }
  3213. }
  3214. return $queries;
  3215. }
  3216. /**
  3217. * update Message For Reload
  3218. *
  3219. * @return array
  3220. */
  3221. function PMA_updateMessageForReload()
  3222. {
  3223. $message = null;
  3224. if (isset($_REQUEST['flush_privileges'])) {
  3225. $sql_query = 'FLUSH PRIVILEGES;';
  3226. $GLOBALS['dbi']->query($sql_query);
  3227. $message = PMA_Message::success(
  3228. __('The privileges were reloaded successfully.')
  3229. );
  3230. }
  3231. if (isset($_REQUEST['validate_username'])) {
  3232. $message = PMA_Message::success();
  3233. }
  3234. return $message;
  3235. }
  3236. /**
  3237. * update Data For Queries from queries_for_display
  3238. *
  3239. * @param array $queries queries array
  3240. * @param array $queries_for_display queries arry for display
  3241. *
  3242. * @return null
  3243. */
  3244. function PMA_getDataForQueries($queries, $queries_for_display)
  3245. {
  3246. $tmp_count = 0;
  3247. foreach ($queries as $sql_query) {
  3248. if ($sql_query{0} != '#') {
  3249. $GLOBALS['dbi']->query($sql_query);
  3250. }
  3251. // when there is a query containing a hidden password, take it
  3252. // instead of the real query sent
  3253. if (isset($queries_for_display[$tmp_count])) {
  3254. $queries[$tmp_count] = $queries_for_display[$tmp_count];
  3255. }
  3256. $tmp_count++;
  3257. }
  3258. return $queries;
  3259. }
  3260. /**
  3261. * update Data for information: Adds a user
  3262. *
  3263. * @param string $dbname db name
  3264. * @param string $username user name
  3265. * @param string $hostname host name
  3266. * @param string $password password
  3267. * @param bool $is_menuwork is_menuwork set?
  3268. *
  3269. * @return array
  3270. */
  3271. function PMA_addUser(
  3272. $dbname, $username, $hostname,
  3273. $password, $is_menuwork
  3274. ) {
  3275. $_add_user_error = false;
  3276. $message = null;
  3277. $queries = null;
  3278. $queries_for_display = null;
  3279. $sql_query = null;
  3280. if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
  3281. $sql_query = '';
  3282. if ($_POST['pred_username'] == 'any') {
  3283. $username = '';
  3284. }
  3285. switch ($_POST['pred_hostname']) {
  3286. case 'any':
  3287. $hostname = '%';
  3288. break;
  3289. case 'localhost':
  3290. $hostname = 'localhost';
  3291. break;
  3292. case 'hosttable':
  3293. $hostname = '';
  3294. break;
  3295. case 'thishost':
  3296. $_user_name = $GLOBALS['dbi']->fetchValue('SELECT USER()');
  3297. $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
  3298. unset($_user_name);
  3299. break;
  3300. }
  3301. $sql = "SELECT '1' FROM `mysql`.`user`"
  3302. . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  3303. . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
  3304. if ($GLOBALS['dbi']->fetchValue($sql) == 1) {
  3305. $message = PMA_Message::error(__('The user %s already exists!'));
  3306. $message->addParam(
  3307. '[em]\'' . $username . '\'@\'' . $hostname . '\'[/em]'
  3308. );
  3309. $_REQUEST['adduser'] = true;
  3310. $_add_user_error = true;
  3311. } else {
  3312. list($create_user_real, $create_user_show, $real_sql_query, $sql_query)
  3313. = PMA_getSqlQueriesForDisplayAndAddUser(
  3314. $username, $hostname, (isset ($password) ? $password : '')
  3315. );
  3316. if (empty($_REQUEST['change_copy'])) {
  3317. $_error = false;
  3318. if (isset($create_user_real)) {
  3319. if (! $GLOBALS['dbi']->tryQuery($create_user_real)) {
  3320. $_error = true;
  3321. }
  3322. $sql_query = $create_user_show . $sql_query;
  3323. }
  3324. list($sql_query, $message) = PMA_addUserAndCreateDatabase(
  3325. $_error, $real_sql_query, $sql_query, $username, $hostname,
  3326. isset($dbname) ? $dbname : null
  3327. );
  3328. if (! empty($_REQUEST['userGroup']) && $is_menuwork) {
  3329. PMA_setUserGroup($GLOBALS['username'], $_REQUEST['userGroup']);
  3330. }
  3331. } else {
  3332. if (isset($create_user_real)) {
  3333. $queries[] = $create_user_real;
  3334. }
  3335. $queries[] = $real_sql_query;
  3336. // we put the query containing the hidden password in
  3337. // $queries_for_display, at the same position occupied
  3338. // by the real query in $queries
  3339. $tmp_count = count($queries);
  3340. if (isset($create_user_real)) {
  3341. $queries_for_display[$tmp_count - 2] = $create_user_show;
  3342. }
  3343. $queries_for_display[$tmp_count - 1] = $sql_query;
  3344. }
  3345. unset($real_sql_query);
  3346. }
  3347. }
  3348. return array(
  3349. $message, $queries, $queries_for_display, $sql_query, $_add_user_error
  3350. );
  3351. }
  3352. /**
  3353. * Update DB information: DB, Table, isWildcard
  3354. *
  3355. * @return array
  3356. */
  3357. function PMA_getDataForDBInfo()
  3358. {
  3359. $username = null;
  3360. $hostname = null;
  3361. $dbname = null;
  3362. $tablename = null;
  3363. $db_and_table = null;
  3364. $dbname_is_wildcard = null;
  3365. if (isset ($_REQUEST['username'])) {
  3366. $username = $_REQUEST['username'];
  3367. }
  3368. if (isset ($_REQUEST['hostname'])) {
  3369. $hostname = $_REQUEST['hostname'];
  3370. }
  3371. /**
  3372. * Checks if a dropdown box has been used for selecting a database / table
  3373. */
  3374. if (PMA_isValid($_REQUEST['pred_tablename'])) {
  3375. $tablename = $_REQUEST['pred_tablename'];
  3376. } elseif (PMA_isValid($_REQUEST['tablename'])) {
  3377. $tablename = $_REQUEST['tablename'];
  3378. } else {
  3379. unset($tablename);
  3380. }
  3381. if (PMA_isValid($_REQUEST['pred_dbname'])) {
  3382. $dbname = $_REQUEST['pred_dbname'];
  3383. } elseif (PMA_isValid($_REQUEST['dbname'])) {
  3384. $dbname = $_REQUEST['dbname'];
  3385. } else {
  3386. unset($dbname);
  3387. unset($tablename);
  3388. }
  3389. if (isset($dbname)) {
  3390. $unescaped_db = PMA_Util::unescapeMysqlWildcards($dbname);
  3391. $db_and_table = PMA_Util::backquote($unescaped_db) . '.';
  3392. if (isset($tablename)) {
  3393. $db_and_table .= PMA_Util::backquote($tablename);
  3394. } else {
  3395. $db_and_table .= '*';
  3396. }
  3397. } else {
  3398. $db_and_table = '*.*';
  3399. }
  3400. // check if given $dbname is a wildcard or not
  3401. if (isset($dbname)) {
  3402. //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
  3403. if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
  3404. $dbname_is_wildcard = true;
  3405. } else {
  3406. $dbname_is_wildcard = false;
  3407. }
  3408. }
  3409. return array(
  3410. $username, $hostname,
  3411. isset($dbname)? $dbname : null,
  3412. isset($tablename)? $tablename : null,
  3413. $db_and_table,
  3414. $dbname_is_wildcard,
  3415. );
  3416. }
  3417. /**
  3418. * Get title and textarea for export user definition in Privileges
  3419. *
  3420. * @param string $username username
  3421. * @param string $hostname host name
  3422. *
  3423. * @return array ($title, $export)
  3424. */
  3425. function PMA_getListForExportUserDefinition($username, $hostname)
  3426. {
  3427. $export = '<textarea class="export" cols="' . $GLOBALS['cfg']['TextareaCols']
  3428. . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
  3429. if (isset($_REQUEST['selected_usr'])) {
  3430. // export privileges for selected users
  3431. $title = __('Privileges');
  3432. foreach ($_REQUEST['selected_usr'] as $export_user) {
  3433. $export_username = substr($export_user, 0, strpos($export_user, '&'));
  3434. $export_hostname = substr($export_user, strrpos($export_user, ';') + 1);
  3435. $export .= '# '
  3436. . sprintf(
  3437. __('Privileges for %s'),
  3438. '`' . htmlspecialchars($export_username)
  3439. . '`@`' . htmlspecialchars($export_hostname) . '`'
  3440. )
  3441. . "\n\n";
  3442. $export .= PMA_getGrants($export_username, $export_hostname) . "\n";
  3443. }
  3444. } else {
  3445. // export privileges for a single user
  3446. $title = __('User') . ' `' . htmlspecialchars($username)
  3447. . '`@`' . htmlspecialchars($hostname) . '`';
  3448. $export .= PMA_getGrants($username, $hostname);
  3449. }
  3450. // remove trailing whitespace
  3451. $export = trim($export);
  3452. $export .= '</textarea>';
  3453. return array($title, $export);
  3454. }
  3455. /**
  3456. * Get HTML for display Add userfieldset
  3457. *
  3458. * @return string html output
  3459. */
  3460. function PMA_getAddUserHtmlFieldset()
  3461. {
  3462. return '<fieldset id="fieldset_add_user">' . "\n"
  3463. . '<a href="server_privileges.php'
  3464. . PMA_URL_getCommon(array('adduser' => 1))
  3465. . '" class="ajax">' . "\n"
  3466. . PMA_Util::getIcon('b_usradd.png')
  3467. . ' ' . __('Add user') . '</a>' . "\n"
  3468. . '</fieldset>' . "\n";
  3469. }
  3470. /**
  3471. * Get HTML header for display User's properties
  3472. *
  3473. * @param boolean $dbname_is_wildcard whether database name is wildcard or not
  3474. * @param string $url_dbname url database name that urlencode() string
  3475. * @param string $dbname database name
  3476. * @param string $username username
  3477. * @param string $hostname host name
  3478. * @param string $tablename table name
  3479. *
  3480. * @return string $html_output
  3481. */
  3482. function PMA_getHtmlHeaderForUserProperties(
  3483. $dbname_is_wildcard, $url_dbname, $dbname, $username, $hostname, $tablename
  3484. ) {
  3485. $html_output = '<h2>' . "\n"
  3486. . PMA_Util::getIcon('b_usredit.png')
  3487. . __('Edit Privileges:') . ' '
  3488. . __('User');
  3489. if (! empty($dbname)) {
  3490. $html_output .= ' <i><a class="edit_user_anchor ajax"'
  3491. . ' href="server_privileges.php'
  3492. . PMA_URL_getCommon(
  3493. array(
  3494. 'username' => $username,
  3495. 'hostname' => $hostname,
  3496. 'dbname' => '',
  3497. 'tablename' => '',
  3498. )
  3499. )
  3500. . '">\'' . htmlspecialchars($username)
  3501. . '\'@\'' . htmlspecialchars($hostname)
  3502. . '\'</a></i>' . "\n";
  3503. $html_output .= ' - ';
  3504. $html_output .= $dbname_is_wildcard ? __('Databases') : __('Database');
  3505. if (! empty($_REQUEST['tablename'])) {
  3506. $html_output .= ' <i><a href="server_privileges.php'
  3507. . PMA_URL_getCommon(
  3508. array(
  3509. 'username' => $username,
  3510. 'hostname' => $hostname,
  3511. 'dbname' => $url_dbname,
  3512. 'tablename' => '',
  3513. )
  3514. )
  3515. . '">' . htmlspecialchars($dbname)
  3516. . '</a></i>';
  3517. $html_output .= ' - ' . __('Table')
  3518. . ' <i>' . htmlspecialchars($tablename) . '</i>';
  3519. } else {
  3520. $html_output .= ' <i>' . htmlspecialchars($dbname) . '</i>';
  3521. }
  3522. } else {
  3523. $html_output .= ' <i>\'' . htmlspecialchars($username)
  3524. . '\'@\'' . htmlspecialchars($hostname)
  3525. . '\'</i>' . "\n";
  3526. }
  3527. $html_output .= '</h2>' . "\n";
  3528. return $html_output;
  3529. }
  3530. /**
  3531. * Get HTML snippet for display user overview page
  3532. *
  3533. * @param string $pmaThemeImage a image source link
  3534. * @param string $text_dir text directory
  3535. *
  3536. * @return string $html_output
  3537. */
  3538. function PMA_getHtmlForUserOverview($pmaThemeImage, $text_dir)
  3539. {
  3540. $html_output = '<h2>' . "\n"
  3541. . PMA_Util::getIcon('b_usrlist.png')
  3542. . __('Users overview') . "\n"
  3543. . '</h2>' . "\n";
  3544. // $sql_query is for the initial-filtered,
  3545. // $sql_query_all is for counting the total no. of users
  3546. $sql_query = $sql_query_all = 'SELECT *,' .
  3547. " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
  3548. ' FROM `mysql`.`user`';
  3549. $sql_query .= (isset($_REQUEST['initial'])
  3550. ? PMA_rangeOfUsers($_REQUEST['initial'])
  3551. : '');
  3552. $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
  3553. $sql_query_all .= ' ;';
  3554. $res = $GLOBALS['dbi']->tryQuery(
  3555. $sql_query, null, PMA_DatabaseInterface::QUERY_STORE
  3556. );
  3557. $res_all = $GLOBALS['dbi']->tryQuery(
  3558. $sql_query_all, null, PMA_DatabaseInterface::QUERY_STORE
  3559. );
  3560. if (! $res) {
  3561. // the query failed! This may have two reasons:
  3562. // - the user does not have enough privileges
  3563. // - the privilege tables use a structure of an earlier version.
  3564. // so let's try a more simple query
  3565. $sql_query = 'SELECT * FROM `mysql`.`user`';
  3566. $res = $GLOBALS['dbi']->tryQuery(
  3567. $sql_query, null, PMA_DatabaseInterface::QUERY_STORE
  3568. );
  3569. if (! $res) {
  3570. $html_output .= PMA_Message::error(__('No Privileges'))->getDisplay();
  3571. $GLOBALS['dbi']->freeResult($res);
  3572. unset($res);
  3573. } else {
  3574. // This message is hardcoded because I will replace it by
  3575. // a automatic repair feature soon.
  3576. $raw = 'Your privilege table structure seems to be older than'
  3577. . ' this MySQL version!<br />'
  3578. . 'Please run the <code>mysql_upgrade</code> command'
  3579. . '(<code>mysql_fix_privilege_tables</code> on older systems)'
  3580. . ' that should be included in your MySQL server distribution'
  3581. . ' to solve this problem!';
  3582. $html_output .= PMA_Message::rawError($raw)->getDisplay();
  3583. }
  3584. } else {
  3585. $db_rights = PMA_getDbRightsForUserOverview();
  3586. // for all initials, even non A-Z
  3587. $array_initials = array();
  3588. /**
  3589. * Displays the initials
  3590. * Also not necessary if there is less than 20 privileges
  3591. */
  3592. if ($GLOBALS['dbi']->numRows($res_all) > 20) {
  3593. $html_output .= PMA_getHtmlForInitials($array_initials);
  3594. }
  3595. /**
  3596. * Display the user overview
  3597. * (if less than 50 users, display them immediately)
  3598. */
  3599. if (isset($_REQUEST['initial'])
  3600. || isset($_REQUEST['showall'])
  3601. || $GLOBALS['dbi']->numRows($res) < 50
  3602. ) {
  3603. $html_output .= PMA_getUsersOverview(
  3604. $res, $db_rights, $pmaThemeImage, $text_dir
  3605. );
  3606. } else {
  3607. $html_output .= PMA_getAddUserHtmlFieldset();
  3608. } // end if (display overview)
  3609. if (! $GLOBALS['is_ajax_request']
  3610. || ! empty($_REQUEST['ajax_page_request'])
  3611. ) {
  3612. $flushnote = new PMA_Message(
  3613. __(
  3614. 'Note: phpMyAdmin gets the users\' privileges directly '
  3615. . 'from MySQL\'s privilege tables. The content of these tables '
  3616. . 'may differ from the privileges the server uses, '
  3617. . 'if they have been changed manually. In this case, '
  3618. . 'you should %sreload the privileges%s before you continue.'
  3619. ),
  3620. PMA_Message::NOTICE
  3621. );
  3622. $flushLink = '<a href="server_privileges.php'
  3623. . PMA_URL_getCommon(array('flush_privileges' => 1))
  3624. . '" id="reload_privileges_anchor">';
  3625. $flushnote->addParam(
  3626. $flushLink,
  3627. false
  3628. );
  3629. $flushnote->addParam('</a>', false);
  3630. $html_output .= $flushnote->getDisplay();
  3631. }
  3632. }
  3633. return $html_output;
  3634. }
  3635. /**
  3636. * Get HTML snippet for display user properties
  3637. *
  3638. * @param boolean $dbname_is_wildcard whether database name is wildcard or not
  3639. * @param string $url_dbname url database name that urlencode() string
  3640. * @param string $username username
  3641. * @param string $hostname host name
  3642. * @param string $dbname database name
  3643. * @param string $tablename table name
  3644. *
  3645. * @return string $html_output
  3646. */
  3647. function PMA_getHtmlForUserProperties($dbname_is_wildcard,$url_dbname,
  3648. $username, $hostname, $dbname, $tablename
  3649. ) {
  3650. $html_output = PMA_getHtmlHeaderForUserProperties(
  3651. $dbname_is_wildcard, $url_dbname, $dbname, $username, $hostname, $tablename
  3652. );
  3653. $sql = "SELECT '1' FROM `mysql`.`user`"
  3654. . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  3655. . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
  3656. $user_does_not_exists = (bool) ! $GLOBALS['dbi']->fetchValue($sql);
  3657. if ($user_does_not_exists) {
  3658. $html_output .= PMA_Message::error(
  3659. __('The selected user was not found in the privilege table.')
  3660. )->getDisplay();
  3661. $html_output .= PMA_getHtmlForLoginInformationFields();
  3662. //exit;
  3663. }
  3664. $_params = array(
  3665. 'username' => $username,
  3666. 'hostname' => $hostname,
  3667. );
  3668. if (strlen($dbname)) {
  3669. $_params['dbname'] = $dbname;
  3670. if (strlen($tablename)) {
  3671. $_params['tablename'] = $tablename;
  3672. }
  3673. }
  3674. $html_output .= '<form class="ajax submenu-item" name="usersForm" '
  3675. . 'id="addUsersForm" action="server_privileges.php" method="post">' . "\n";
  3676. $html_output .= PMA_URL_getHiddenInputs($_params);
  3677. $html_output .= PMA_getHtmlToDisplayPrivilegesTable(
  3678. PMA_ifSetOr($dbname, '*', 'length'),
  3679. PMA_ifSetOr($tablename, '*', 'length')
  3680. );
  3681. $html_output .= '</form>' . "\n";
  3682. if (! strlen($tablename) && empty($dbname_is_wildcard)) {
  3683. // no table name was given, display all table specific rights
  3684. // but only if $dbname contains no wildcards
  3685. $html_output .= '<form class="submenu-item" action="server_privileges.php" '
  3686. . 'id="db_or_table_specific_priv" method="post">' . "\n";
  3687. // unescape wildcards in dbname at table level
  3688. $unescaped_db = PMA_Util::unescapeMysqlWildcards($dbname);
  3689. list($html_rightsTable, $found_rows)
  3690. = PMA_getHtmlForAllTableSpecificRights(
  3691. $username, $hostname, $unescaped_db
  3692. );
  3693. $html_output .= $html_rightsTable;
  3694. if (! strlen($dbname)) {
  3695. // no database name was given, display select db
  3696. $html_output .= PMA_getHtmlForSelectDbInEditPrivs($found_rows);
  3697. } else {
  3698. $html_output .= PMA_displayTablesInEditPrivs($dbname, $found_rows);
  3699. }
  3700. $html_output .= '</fieldset>' . "\n";
  3701. $html_output .= '<fieldset class="tblFooters">' . "\n"
  3702. . ' <input type="submit" value="' . __('Go') . '" />'
  3703. . '</fieldset>' . "\n"
  3704. . '</form>' . "\n";
  3705. }
  3706. // Provide a line with links to the relevant database and table
  3707. if (strlen($dbname) && empty($dbname_is_wildcard)) {
  3708. $html_output .= PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename);
  3709. }
  3710. if (! strlen($dbname) && ! $user_does_not_exists) {
  3711. //change login information
  3712. $html_output .= PMA_getHtmlForChangePassword($username, $hostname);
  3713. $html_output .= PMA_getChangeLoginInformationHtmlForm($username, $hostname);
  3714. }
  3715. return $html_output;
  3716. }
  3717. /**
  3718. * Get queries for Table privileges to change or copy user
  3719. *
  3720. * @param string $user_host_condition user host condition to
  3721. * select relevent table privileges
  3722. * @param array $queries queries array
  3723. * @param string $username username
  3724. * @param string $hostname host name
  3725. *
  3726. * @return array $queries
  3727. */
  3728. function PMA_getTablePrivsQueriesForChangeOrCopyUser($user_host_condition,
  3729. $queries, $username, $hostname
  3730. ) {
  3731. $res = $GLOBALS['dbi']->query(
  3732. 'SELECT `Db`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv`'
  3733. . $user_host_condition,
  3734. $GLOBALS['userlink'],
  3735. PMA_DatabaseInterface::QUERY_STORE
  3736. );
  3737. while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
  3738. $res2 = $GLOBALS['dbi']->query(
  3739. 'SELECT `Column_name`, `Column_priv`'
  3740. . ' FROM `mysql`.`columns_priv`'
  3741. . ' WHERE `User`'
  3742. . ' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
  3743. . ' AND `Host`'
  3744. . ' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . '\''
  3745. . ' AND `Db`'
  3746. . ' = \'' . PMA_Util::sqlAddSlashes($row['Db']) . "'"
  3747. . ' AND `Table_name`'
  3748. . ' = \'' . PMA_Util::sqlAddSlashes($row['Table_name']) . "'"
  3749. . ';',
  3750. null,
  3751. PMA_DatabaseInterface::QUERY_STORE
  3752. );
  3753. $tmp_privs1 = PMA_extractPrivInfo($row);
  3754. $tmp_privs2 = array(
  3755. 'Select' => array(),
  3756. 'Insert' => array(),
  3757. 'Update' => array(),
  3758. 'References' => array()
  3759. );
  3760. while ($row2 = $GLOBALS['dbi']->fetchAssoc($res2)) {
  3761. $tmp_array = explode(',', $row2['Column_priv']);
  3762. if (in_array('Select', $tmp_array)) {
  3763. $tmp_privs2['Select'][] = $row2['Column_name'];
  3764. }
  3765. if (in_array('Insert', $tmp_array)) {
  3766. $tmp_privs2['Insert'][] = $row2['Column_name'];
  3767. }
  3768. if (in_array('Update', $tmp_array)) {
  3769. $tmp_privs2['Update'][] = $row2['Column_name'];
  3770. }
  3771. if (in_array('References', $tmp_array)) {
  3772. $tmp_privs2['References'][] = $row2['Column_name'];
  3773. }
  3774. }
  3775. if (count($tmp_privs2['Select']) > 0 && ! in_array('SELECT', $tmp_privs1)) {
  3776. $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
  3777. }
  3778. if (count($tmp_privs2['Insert']) > 0 && ! in_array('INSERT', $tmp_privs1)) {
  3779. $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
  3780. }
  3781. if (count($tmp_privs2['Update']) > 0 && ! in_array('UPDATE', $tmp_privs1)) {
  3782. $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
  3783. }
  3784. if (count($tmp_privs2['References']) > 0
  3785. && ! in_array('REFERENCES', $tmp_privs1)
  3786. ) {
  3787. $tmp_privs1[]
  3788. = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
  3789. }
  3790. $queries[] = 'GRANT ' . join(', ', $tmp_privs1)
  3791. . ' ON ' . PMA_Util::backquote($row['Db']) . '.'
  3792. . PMA_Util::backquote($row['Table_name'])
  3793. . ' TO \'' . PMA_Util::sqlAddSlashes($username)
  3794. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\''
  3795. . (in_array('Grant', explode(',', $row['Table_priv']))
  3796. ? ' WITH GRANT OPTION;'
  3797. : ';');
  3798. }
  3799. return $queries;
  3800. }
  3801. /**
  3802. * Get queries for database specific privileges for change or copy user
  3803. *
  3804. * @param array $queries queries array with string
  3805. * @param string $username username
  3806. * @param string $hostname host name
  3807. *
  3808. * @return array $queries
  3809. */
  3810. function PMA_getDbSpecificPrivsQueriesForChangeOrCopyUser(
  3811. $queries, $username, $hostname
  3812. ) {
  3813. $user_host_condition = ' WHERE `User`'
  3814. . ' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
  3815. . ' AND `Host`'
  3816. . ' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_hostname']) . '\';';
  3817. $res = $GLOBALS['dbi']->query(
  3818. 'SELECT * FROM `mysql`.`db`' . $user_host_condition
  3819. );
  3820. while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
  3821. $queries[] = 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
  3822. . ' ON ' . PMA_Util::backquote($row['Db']) . '.*'
  3823. . ' TO \'' . PMA_Util::sqlAddSlashes($username)
  3824. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\''
  3825. . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
  3826. }
  3827. $GLOBALS['dbi']->freeResult($res);
  3828. $queries = PMA_getTablePrivsQueriesForChangeOrCopyUser(
  3829. $user_host_condition, $queries, $username, $hostname
  3830. );
  3831. return $queries;
  3832. }
  3833. /**
  3834. * Prepares queries for adding users and
  3835. * also create database and return query and message
  3836. *
  3837. * @param boolean $_error whether user create or not
  3838. * @param string $real_sql_query SQL query for add a user
  3839. * @param string $sql_query SQL query to be displayed
  3840. * @param string $username username
  3841. * @param string $hostname host name
  3842. * @param string $dbname database name
  3843. *
  3844. * @return array $sql_query, $message
  3845. */
  3846. function PMA_addUserAndCreateDatabase($_error, $real_sql_query, $sql_query,
  3847. $username, $hostname, $dbname
  3848. ) {
  3849. if ($_error || ! $GLOBALS['dbi']->tryQuery($real_sql_query)) {
  3850. $_REQUEST['createdb-1'] = $_REQUEST['createdb-2']
  3851. = $_REQUEST['createdb-3'] = false;
  3852. $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
  3853. } else {
  3854. $message = PMA_Message::success(__('You have added a new user.'));
  3855. }
  3856. if (isset($_REQUEST['createdb-1'])) {
  3857. // Create database with same name and grant all privileges
  3858. $q = 'CREATE DATABASE IF NOT EXISTS '
  3859. . PMA_Util::backquote(
  3860. PMA_Util::sqlAddSlashes($username)
  3861. ) . ';';
  3862. $sql_query .= $q;
  3863. if (! $GLOBALS['dbi']->tryQuery($q)) {
  3864. $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
  3865. }
  3866. /**
  3867. * Reload the navigation
  3868. */
  3869. $GLOBALS['reload'] = true;
  3870. $GLOBALS['db'] = $username;
  3871. $q = 'GRANT ALL PRIVILEGES ON '
  3872. . PMA_Util::backquote(
  3873. PMA_Util::escapeMysqlWildcards(
  3874. PMA_Util::sqlAddSlashes($username)
  3875. )
  3876. ) . '.* TO \''
  3877. . PMA_Util::sqlAddSlashes($username)
  3878. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
  3879. $sql_query .= $q;
  3880. if (! $GLOBALS['dbi']->tryQuery($q)) {
  3881. $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
  3882. }
  3883. }
  3884. if (isset($_REQUEST['createdb-2'])) {
  3885. // Grant all privileges on wildcard name (username\_%)
  3886. $q = 'GRANT ALL PRIVILEGES ON '
  3887. . PMA_Util::backquote(
  3888. PMA_Util::sqlAddSlashes($username) . '\_%'
  3889. ) . '.* TO \''
  3890. . PMA_Util::sqlAddSlashes($username)
  3891. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
  3892. $sql_query .= $q;
  3893. if (! $GLOBALS['dbi']->tryQuery($q)) {
  3894. $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
  3895. }
  3896. }
  3897. if (isset($_REQUEST['createdb-3'])) {
  3898. // Grant all privileges on the specified database to the new user
  3899. $q = 'GRANT ALL PRIVILEGES ON '
  3900. . PMA_Util::backquote(
  3901. PMA_Util::sqlAddSlashes($dbname)
  3902. ) . '.* TO \''
  3903. . PMA_Util::sqlAddSlashes($username)
  3904. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
  3905. $sql_query .= $q;
  3906. if (! $GLOBALS['dbi']->tryQuery($q)) {
  3907. $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
  3908. }
  3909. }
  3910. return array($sql_query, $message);
  3911. }
  3912. /**
  3913. * Get SQL queries for Display and Add user
  3914. *
  3915. * @param string $username usernam
  3916. * @param string $hostname host name
  3917. * @param string $password password
  3918. *
  3919. * @return array ($create_user_real, $create_user_show,$real_sql_query, $sql_query)
  3920. */
  3921. function PMA_getSqlQueriesForDisplayAndAddUser($username, $hostname, $password)
  3922. {
  3923. $sql_query = '';
  3924. $create_user_real = 'CREATE USER \''
  3925. . PMA_Util::sqlAddSlashes($username) . '\'@\''
  3926. . PMA_Util::sqlAddSlashes($hostname) . '\'';
  3927. $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
  3928. . PMA_Util::sqlAddSlashes($username) . '\'@\''
  3929. . PMA_Util::sqlAddSlashes($hostname) . '\'';
  3930. if ($_POST['pred_password'] != 'none' && $_POST['pred_password'] != 'keep') {
  3931. $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
  3932. $real_sql_query .= ' IDENTIFIED BY \''
  3933. . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
  3934. if (isset($create_user_real)) {
  3935. $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
  3936. $create_user_real .= ' IDENTIFIED BY \''
  3937. . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
  3938. }
  3939. } else {
  3940. if ($_POST['pred_password'] == 'keep' && ! empty($password)) {
  3941. $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
  3942. if (isset($create_user_real)) {
  3943. $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
  3944. }
  3945. }
  3946. $sql_query = $real_sql_query;
  3947. if (isset($create_user_real)) {
  3948. $create_user_show = $create_user_real;
  3949. }
  3950. }
  3951. if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')
  3952. || (isset($_POST['max_questions']) || isset($_POST['max_connections'])
  3953. || isset($_POST['max_updates']) || isset($_POST['max_user_connections']))
  3954. ) {
  3955. $with_clause = PMA_getWithClauseForAddUserAndUpdatePrivs();
  3956. $real_sql_query .= ' ' . $with_clause;
  3957. $sql_query .= ' ' . $with_clause;
  3958. }
  3959. if (isset($create_user_real)) {
  3960. $create_user_real .= ';';
  3961. $create_user_show .= ';';
  3962. }
  3963. $real_sql_query .= ';';
  3964. $sql_query .= ';';
  3965. return array($create_user_real,
  3966. $create_user_show,
  3967. $real_sql_query,
  3968. $sql_query
  3969. );
  3970. }
  3971. ?>