server_privileges.lib.php 117 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354
  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. * Escapes wildcard in a database+table specification
  13. * before using it in a GRANT statement.
  14. *
  15. * Escaping a wildcard character in a GRANT is only accepted at the global
  16. * or database level, not at table level; this is why I remove
  17. * the escaping character. Internally, in mysql.tables_priv.Db there are
  18. * no escaping (for example test_db) but in mysql.db you'll see test\_db
  19. * for a db-specific privilege.
  20. *
  21. * @param string $dbname Database name
  22. * @param string $tablename Table name
  23. *
  24. * @return string the escaped (if necessary) database.table
  25. */
  26. function PMA_wildcardEscapeForGrant($dbname, $tablename)
  27. {
  28. if (! strlen($dbname)) {
  29. $db_and_table = '*.*';
  30. } else {
  31. if (strlen($tablename)) {
  32. $db_and_table = PMA_Util::backquote(
  33. PMA_Util::unescapeMysqlWildcards($dbname)
  34. )
  35. . '.' . PMA_Util::backquote($tablename);
  36. } else {
  37. $db_and_table = PMA_Util::backquote($dbname) . '.*';
  38. }
  39. }
  40. return $db_and_table;
  41. }
  42. /**
  43. * Generates a condition on the user name
  44. *
  45. * @param string $initial the user's initial
  46. *
  47. * @return string the generated condition
  48. */
  49. function PMA_rangeOfUsers($initial = '')
  50. {
  51. // strtolower() is used because the User field
  52. // might be BINARY, so LIKE would be case sensitive
  53. if (! empty($initial)) {
  54. $ret = " WHERE `User` LIKE '"
  55. . PMA_Util::sqlAddSlashes($initial, true) . "%'"
  56. . " OR `User` LIKE '"
  57. . PMA_Util::sqlAddSlashes(strtolower($initial), true) . "%'";
  58. } else {
  59. $ret = '';
  60. }
  61. return $ret;
  62. } // end function
  63. /**
  64. * Extracts the privilege information of a priv table row
  65. *
  66. * @param array $row the row
  67. * @param boolean $enableHTML add <dfn> tag with tooltips
  68. *
  69. * @global resource $user_link the database connection
  70. *
  71. * @return array
  72. */
  73. function PMA_extractPrivInfo($row = '', $enableHTML = false)
  74. {
  75. $grants = PMA_getGrantsArray();
  76. if (! empty($row) && isset($row['Table_priv'])) {
  77. $row1 = PMA_DBI_fetch_single_row(
  78. 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
  79. 'ASSOC', $GLOBALS['userlink']
  80. );
  81. $av_grants = explode(
  82. '\',\'',
  83. substr($row1['Type'], 5, strlen($row1['Type']) - 7)
  84. );
  85. unset($row1);
  86. $users_grants = explode(',', $row['Table_priv']);
  87. foreach ($av_grants as $current_grant) {
  88. $row[$current_grant . '_priv']
  89. = in_array($current_grant, $users_grants) ? 'Y' : 'N';
  90. }
  91. unset($current_grant);
  92. }
  93. $privs = array();
  94. $allPrivileges = true;
  95. foreach ($grants as $current_grant) {
  96. if ((! empty($row) && isset($row[$current_grant[0]]))
  97. || (empty($row) && isset($GLOBALS[$current_grant[0]]))
  98. ) {
  99. if ((! empty($row) && $row[$current_grant[0]] == 'Y')
  100. || (empty($row)
  101. && ($GLOBALS[$current_grant[0]] == 'Y'
  102. || (is_array($GLOBALS[$current_grant[0]])
  103. && count($GLOBALS[$current_grant[0]]) == $_REQUEST['column_count']
  104. && empty($GLOBALS[$current_grant[0] . '_none']))))
  105. ) {
  106. if ($enableHTML) {
  107. $privs[] = '<dfn title="' . $current_grant[2] . '">'
  108. . $current_grant[1] . '</dfn>';
  109. } else {
  110. $privs[] = $current_grant[1];
  111. }
  112. } elseif (! empty($GLOBALS[$current_grant[0]])
  113. && is_array($GLOBALS[$current_grant[0]])
  114. && empty($GLOBALS[$current_grant[0] . '_none'])) {
  115. if ($enableHTML) {
  116. $priv_string = '<dfn title="' . $current_grant[2] . '">'
  117. . $current_grant[1] . '</dfn>';
  118. } else {
  119. $priv_string = $current_grant[1];
  120. }
  121. $privs[] = $priv_string . ' (`'
  122. . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
  123. } else {
  124. $allPrivileges = false;
  125. }
  126. }
  127. }
  128. if (empty($privs)) {
  129. if ($enableHTML) {
  130. $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
  131. } else {
  132. $privs[] = 'USAGE';
  133. }
  134. } elseif ($allPrivileges
  135. && (! isset($_POST['grant_count'])
  136. || count($privs) == $_POST['grant_count'])
  137. ) {
  138. if ($enableHTML) {
  139. $privs = array('<dfn title="'
  140. . __('Includes all privileges except GRANT.')
  141. . '">ALL PRIVILEGES</dfn>'
  142. );
  143. } else {
  144. $privs = array('ALL PRIVILEGES');
  145. }
  146. }
  147. return $privs;
  148. } // end of the 'PMA_extractPrivInfo()' function
  149. /**
  150. * Get the grants array which contains all the privilege types
  151. * and relevent grant messages
  152. *
  153. * @return array
  154. */
  155. function PMA_getGrantsArray()
  156. {
  157. return array(
  158. array(
  159. 'Select_priv',
  160. 'SELECT',
  161. __('Allows reading data.')),
  162. array(
  163. 'Insert_priv',
  164. 'INSERT',
  165. __('Allows inserting and replacing data.')),
  166. array(
  167. 'Update_priv',
  168. 'UPDATE',
  169. __('Allows changing data.')),
  170. array(
  171. 'Delete_priv',
  172. 'DELETE',
  173. __('Allows deleting data.')),
  174. array(
  175. 'Create_priv',
  176. 'CREATE',
  177. __('Allows creating new databases and tables.')),
  178. array(
  179. 'Drop_priv',
  180. 'DROP',
  181. __('Allows dropping databases and tables.')),
  182. array(
  183. 'Reload_priv',
  184. 'RELOAD',
  185. __('Allows reloading server settings and flushing the server\'s caches.')),
  186. array(
  187. 'Shutdown_priv',
  188. 'SHUTDOWN',
  189. __('Allows shutting down the server.')),
  190. array(
  191. 'Process_priv',
  192. 'PROCESS',
  193. __('Allows viewing processes of all users')),
  194. array(
  195. 'File_priv',
  196. 'FILE',
  197. __('Allows importing data from and exporting data into files.')),
  198. array(
  199. 'References_priv',
  200. 'REFERENCES',
  201. __('Has no effect in this MySQL version.')),
  202. array(
  203. 'Index_priv',
  204. 'INDEX',
  205. __('Allows creating and dropping indexes.')),
  206. array(
  207. 'Alter_priv',
  208. 'ALTER',
  209. __('Allows altering the structure of existing tables.')),
  210. array(
  211. 'Show_db_priv',
  212. 'SHOW DATABASES',
  213. __('Gives access to the complete list of databases.')),
  214. array(
  215. 'Super_priv',
  216. 'SUPER',
  217. __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.')),
  218. array(
  219. 'Create_tmp_table_priv',
  220. 'CREATE TEMPORARY TABLES',
  221. __('Allows creating temporary tables.')),
  222. array(
  223. 'Lock_tables_priv',
  224. 'LOCK TABLES',
  225. __('Allows locking tables for the current thread.')),
  226. array(
  227. 'Repl_slave_priv',
  228. 'REPLICATION SLAVE',
  229. __('Needed for the replication slaves.')),
  230. array(
  231. 'Repl_client_priv',
  232. 'REPLICATION CLIENT',
  233. __('Allows the user to ask where the slaves / masters are.')),
  234. array(
  235. 'Create_view_priv',
  236. 'CREATE VIEW',
  237. __('Allows creating new views.')),
  238. array(
  239. 'Event_priv',
  240. 'EVENT',
  241. __('Allows to set up events for the event scheduler')),
  242. array(
  243. 'Trigger_priv',
  244. 'TRIGGER',
  245. __('Allows creating and dropping triggers')),
  246. // for table privs:
  247. array(
  248. 'Create View_priv',
  249. 'CREATE VIEW',
  250. __('Allows creating new views.')),
  251. array(
  252. 'Show_view_priv',
  253. 'SHOW VIEW',
  254. __('Allows performing SHOW CREATE VIEW queries.')),
  255. // for table privs:
  256. array(
  257. 'Show view_priv',
  258. 'SHOW VIEW',
  259. __('Allows performing SHOW CREATE VIEW queries.')),
  260. array(
  261. 'Create_routine_priv',
  262. 'CREATE ROUTINE',
  263. __('Allows creating stored routines.')),
  264. array(
  265. 'Alter_routine_priv',
  266. 'ALTER ROUTINE',
  267. __('Allows altering and dropping stored routines.')),
  268. array(
  269. 'Create_user_priv',
  270. 'CREATE USER',
  271. __('Allows creating, dropping and renaming user accounts.')),
  272. array(
  273. 'Execute_priv',
  274. 'EXECUTE',
  275. __('Allows executing stored routines.')),
  276. );
  277. }
  278. /**
  279. * Displays on which column(s) a table-specific privilege is granted
  280. *
  281. * @param array $columns columns array
  282. * @param array $row first row from result or boolean false
  283. * @param string $name_for_select privilege types - Select_priv, Insert_priv
  284. * Update_priv, References_priv
  285. * @param string $priv_for_header privilege for header
  286. * @param string $name privilege name: insert, select, update, references
  287. * @param string $name_for_dfn name for dfn
  288. * @param string $name_for_current name for current
  289. *
  290. * @return $html_output html snippet
  291. */
  292. function PMA_getHtmlForDisplayColumnPrivileges($columns, $row, $name_for_select,
  293. $priv_for_header, $name, $name_for_dfn, $name_for_current
  294. ) {
  295. $html_output = '<div class="item" id="div_item_' . $name . '">' . "\n"
  296. . '<label for="select_' . $name . '_priv">' . "\n"
  297. . '<code><dfn title="' . $name_for_dfn . '">'
  298. . $priv_for_header . '</dfn></code>' . "\n"
  299. . '</label><br />' . "\n"
  300. . '<select id="select_' . $name . '_priv" name="'
  301. . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
  302. foreach ($columns as $current_column => $current_column_privileges) {
  303. $html_output .= '<option '
  304. . 'value="' . htmlspecialchars($current_column) . '"';
  305. if ($row[$name_for_select] == 'Y'
  306. || $current_column_privileges[$name_for_current]
  307. ) {
  308. $html_output .= ' selected="selected"';
  309. }
  310. $html_output .= '>'
  311. . htmlspecialchars($current_column) . '</option>' . "\n";
  312. }
  313. $html_output .= '</select>' . "\n"
  314. . '<i>' . __('Or') . '</i>' . "\n"
  315. . '<label for="checkbox_' . $name_for_select
  316. . '_none"><input type="checkbox"'
  317. . ' name="' . $name_for_select . '_none" id="checkbox_'
  318. . $name_for_select . '_none" title="'
  319. . _pgettext('None privileges', 'None') . '" />'
  320. . _pgettext('None privileges', 'None') . '</label>' . "\n"
  321. . '</div>' . "\n";
  322. return $html_output;
  323. } // end function
  324. /**
  325. * Get sql query for display privileges table
  326. *
  327. * @param string $db the database
  328. * @param string $table the table
  329. * @param string $username username for database connection
  330. * @param string $hostname hostname for database connection
  331. *
  332. * @return string sql query
  333. */
  334. function PMA_getSqlQueryForDisplayPrivTable($db, $table, $username, $hostname)
  335. {
  336. if ($db == '*') {
  337. return "SELECT * FROM `mysql`.`user`"
  338. ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  339. ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
  340. } elseif ($table == '*') {
  341. return "SELECT * FROM `mysql`.`db`"
  342. ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  343. ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "'"
  344. ." AND '" . PMA_Util::unescapeMysqlWildcards($db) . "'"
  345. ." LIKE `Db`;";
  346. }
  347. return "SELECT `Table_priv`"
  348. ." FROM `mysql`.`tables_priv`"
  349. ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  350. ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "'"
  351. ." AND `Db` = '" . PMA_Util::unescapeMysqlWildcards($db) . "'"
  352. ." AND `Table_name` = '" . PMA_Util::sqlAddSlashes($table) . "';";
  353. }
  354. /**
  355. * Displays the privileges form table
  356. *
  357. * @param string $db the database
  358. * @param string $table the table
  359. * @param boolean $submit wheather to display the submit button or not
  360. *
  361. * @global array $cfg the phpMyAdmin configuration
  362. * @global ressource $user_link the database connection
  363. *
  364. * @return string html snippet
  365. */
  366. function PMA_getHtmlToDisplayPrivilegesTable($db = '*',
  367. $table = '*', $submit = true
  368. ) {
  369. $html_output = '';
  370. if ($db == '*') {
  371. $table = '*';
  372. }
  373. if (isset($GLOBALS['username'])) {
  374. $username = $GLOBALS['username'];
  375. $hostname = $GLOBALS['hostname'];
  376. $sql_query = PMA_getSqlQueryForDisplayPrivTable(
  377. $db, $table, $username, $hostname
  378. );
  379. $row = PMA_DBI_fetch_single_row($sql_query);
  380. }
  381. if (empty($row)) {
  382. if ($table == '*') {
  383. if ($db == '*') {
  384. $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
  385. } elseif ($table == '*') {
  386. $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
  387. }
  388. $res = PMA_DBI_query($sql_query);
  389. while ($row1 = PMA_DBI_fetch_row($res)) {
  390. if (substr($row1[0], 0, 4) == 'max_') {
  391. $row[$row1[0]] = 0;
  392. } else {
  393. $row[$row1[0]] = 'N';
  394. }
  395. }
  396. PMA_DBI_free_result($res);
  397. } else {
  398. $row = array('Table_priv' => '');
  399. }
  400. }
  401. if (isset($row['Table_priv'])) {
  402. $row1 = PMA_DBI_fetch_single_row(
  403. 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
  404. 'ASSOC', $GLOBALS['userlink']
  405. );
  406. // note: in MySQL 5.0.3 we get "Create View', 'Show view';
  407. // the View for Create is spelled with uppercase V
  408. // the view for Show is spelled with lowercase v
  409. // and there is a space between the words
  410. $av_grants = explode(
  411. '\',\'',
  412. substr(
  413. $row1['Type'],
  414. strpos($row1['Type'], '(') + 2,
  415. strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3
  416. )
  417. );
  418. unset($row1);
  419. $users_grants = explode(',', $row['Table_priv']);
  420. foreach ($av_grants as $current_grant) {
  421. $row[$current_grant . '_priv']
  422. = in_array($current_grant, $users_grants) ? 'Y' : 'N';
  423. }
  424. unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
  425. // get columns
  426. $res = PMA_DBI_try_query(
  427. 'SHOW COLUMNS FROM '
  428. . PMA_Util::backquote(
  429. PMA_Util::unescapeMysqlWildcards($db)
  430. )
  431. . '.' . PMA_Util::backquote($table) . ';'
  432. );
  433. $columns = array();
  434. if ($res) {
  435. while ($row1 = PMA_DBI_fetch_row($res)) {
  436. $columns[$row1[0]] = array(
  437. 'Select' => false,
  438. 'Insert' => false,
  439. 'Update' => false,
  440. 'References' => false
  441. );
  442. }
  443. PMA_DBI_free_result($res);
  444. }
  445. unset($res, $row1);
  446. }
  447. // t a b l e - s p e c i f i c p r i v i l e g e s
  448. if (! empty($columns)) {
  449. $html_output .= PMA_getHtmlForTableSpecificPrivileges(
  450. $username, $hostname, $db, $table, $columns, $row
  451. );
  452. } else {
  453. // g l o b a l o r d b - s p e c i f i c
  454. $html_output .= PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row);
  455. }
  456. $html_output .= '</fieldset>' . "\n";
  457. if ($submit) {
  458. $html_output .= '<fieldset id="fieldset_user_privtable_footer" '
  459. . 'class="tblFooters">' . "\n"
  460. . '<input type="submit" name="update_privs" '
  461. . 'value="' . __('Go') . '" />' . "\n"
  462. . '</fieldset>' . "\n";
  463. }
  464. return $html_output;
  465. } // end of the 'PMA_displayPrivTable()' function
  466. /**
  467. * Get HTML for "Resource limits"
  468. *
  469. * @param array $row first row from result or boolean false
  470. *
  471. * @return string html snippet
  472. */
  473. function PMA_getHtmlForDisplayResourceLimits($row)
  474. {
  475. $html_output = '<fieldset>' . "\n"
  476. . '<legend>' . __('Resource limits') . '</legend>' . "\n"
  477. . '<p><small>'
  478. . '<i>' . __('Note: Setting these options to 0 (zero) removes the limit.')
  479. . '</i></small></p>' . "\n";
  480. $html_output .= '<div class="item">' . "\n"
  481. . '<label for="text_max_questions">'
  482. . '<code><dfn title="'
  483. . __('Limits the number of queries the user may send to the server per hour.')
  484. . '">'
  485. . 'MAX QUERIES PER HOUR'
  486. . '</dfn></code></label>' . "\n"
  487. . '<input type="text" name="max_questions" id="text_max_questions" '
  488. . 'value="' . $row['max_questions'] . '" '
  489. . 'size="11" maxlength="11" '
  490. . 'title="'
  491. . __('Limits the number of queries the user may send to the server per hour.')
  492. . '" />' . "\n"
  493. . '</div>' . "\n";
  494. $html_output .= '<div class="item">' . "\n"
  495. . '<label for="text_max_updates">'
  496. . '<code><dfn title="'
  497. . __('Limits the number of commands that change any table or database the user may execute per hour.') . '">'
  498. . 'MAX UPDATES PER HOUR'
  499. . '</dfn></code></label>' . "\n"
  500. . '<input type="text" name="max_updates" id="text_max_updates" '
  501. . 'value="' . $row['max_updates'] . '" size="11" maxlength="11" '
  502. . 'title="'
  503. . __('Limits the number of commands that change any table or database the user may execute per hour.')
  504. . '" />' . "\n"
  505. . '</div>' . "\n";
  506. $html_output .= '<div class="item">' . "\n"
  507. . '<label for="text_max_connections">'
  508. . '<code><dfn title="'
  509. . __('Limits the number of new connections the user may open per hour.') . '">'
  510. . 'MAX CONNECTIONS PER HOUR'
  511. . '</dfn></code></label>' . "\n"
  512. . '<input type="text" name="max_connections" id="text_max_connections" '
  513. . 'value="' . $row['max_connections'] . '" size="11" maxlength="11" '
  514. . 'title="' . __('Limits the number of new connections the user may open per hour.')
  515. . '" />' . "\n"
  516. . '</div>' . "\n";
  517. $html_output .= '<div class="item">' . "\n"
  518. . '<label for="text_max_user_connections">'
  519. . '<code><dfn title="'
  520. . __('Limits the number of simultaneous connections the user may have.')
  521. . '">'
  522. . 'MAX USER_CONNECTIONS'
  523. . '</dfn></code></label>' . "\n"
  524. . '<input type="text" name="max_user_connections" '
  525. . 'id="text_max_user_connections" '
  526. . 'value="' . $row['max_user_connections'] . '" size="11" maxlength="11" '
  527. . 'title="'
  528. . __('Limits the number of simultaneous connections the user may have.')
  529. . '" />' . "\n"
  530. . '</div>' . "\n";
  531. $html_output .= '</fieldset>' . "\n";
  532. return $html_output;
  533. }
  534. /**
  535. * Get the HTML snippet for table specific privileges
  536. *
  537. * @param string $username username for database connection
  538. * @param string $hostname hostname for database connection
  539. * @param string $db the database
  540. * @param string $table the table
  541. * @param boolean $columns columns array
  542. * @param $row
  543. *
  544. * @return string $html_output
  545. */
  546. function PMA_getHtmlForTableSpecificPrivileges($username, $hostname, $db,
  547. $table, $columns, $row
  548. ) {
  549. $res = PMA_DBI_query(
  550. 'SELECT `Column_name`, `Column_priv`'
  551. .' FROM `mysql`.`columns_priv`'
  552. .' WHERE `User`'
  553. .' = \'' . PMA_Util::sqlAddSlashes($username) . "'"
  554. .' AND `Host`'
  555. .' = \'' . PMA_Util::sqlAddSlashes($hostname) . "'"
  556. .' AND `Db`'
  557. .' = \'' . PMA_Util::sqlAddSlashes(
  558. PMA_Util::unescapeMysqlWildcards($db)
  559. ) . "'"
  560. .' AND `Table_name`'
  561. .' = \'' . PMA_Util::sqlAddSlashes($table) . '\';'
  562. );
  563. while ($row1 = PMA_DBI_fetch_row($res)) {
  564. $row1[1] = explode(',', $row1[1]);
  565. foreach ($row1[1] as $current) {
  566. $columns[$row1[0]][$current] = true;
  567. }
  568. }
  569. PMA_DBI_free_result($res);
  570. unset($res, $row1, $current);
  571. $html_output = '<input type="hidden" name="grant_count" '
  572. . 'value="' . count($row) . '" />' . "\n"
  573. . '<input type="hidden" name="column_count" '
  574. . 'value="' . count($columns) . '" />' . "\n"
  575. . '<fieldset id="fieldset_user_priv">' . "\n"
  576. . '<legend>' . __('Table-specific privileges')
  577. . PMA_Util::showHint(
  578. __('Note: MySQL privilege names are expressed in English')
  579. )
  580. . '</legend>' . "\n";
  581. // privs that are attached to a specific column
  582. $html_output .= PMA_getHtmlForAttachedPrivilegesToTableSpecificColumn(
  583. $columns, $row
  584. );
  585. // privs that are not attached to a specific column
  586. $html_output .= '<div class="item">' . "\n"
  587. . PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
  588. . '</div>' . "\n";
  589. // for Safari 2.0.2
  590. $html_output .= '<div class="clearfloat"></div>' . "\n";
  591. return $html_output;
  592. }
  593. /**
  594. * Get HTML snippet for privileges that are attached to a specific column
  595. *
  596. * @param string $columns olumns array
  597. * @param array $row first row from result or boolean false
  598. *
  599. * @return string $html_output
  600. */
  601. function PMA_getHtmlForAttachedPrivilegesToTableSpecificColumn($columns, $row)
  602. {
  603. $html_output = PMA_getHtmlForDisplayColumnPrivileges(
  604. $columns, $row, 'Select_priv', 'SELECT',
  605. 'select', __('Allows reading data.'), 'Select'
  606. );
  607. $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
  608. $columns, $row, 'Insert_priv', 'INSERT',
  609. 'insert', __('Allows inserting and replacing data.'), 'Insert'
  610. );
  611. $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
  612. $columns, $row, 'Update_priv', 'UPDATE',
  613. 'update', __('Allows changing data.'), 'Update'
  614. );
  615. $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
  616. $columns, $row, 'References_priv', 'REFERENCES', 'references',
  617. __('Has no effect in this MySQL version.'), 'References'
  618. );
  619. return $html_output;
  620. }
  621. /**
  622. * Get HTML for privileges that are not attached to a specific column
  623. *
  624. * @param array $row first row from result or boolean false
  625. *
  626. * @return string $html_output
  627. */
  628. function PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
  629. {
  630. $html_output = '';
  631. foreach ($row as $current_grant => $current_grant_value) {
  632. $grant_type = substr($current_grant, 0, (strlen($current_grant) - 5));
  633. if (in_array($grant_type, array('Select', 'Insert', 'Update', 'References'))) {
  634. continue;
  635. }
  636. // make a substitution to match the messages variables;
  637. // also we must substitute the grant we get, because we can't generate
  638. // a form variable containing blanks (those would get changed to
  639. // an underscore when receiving the POST)
  640. if ($current_grant == 'Create View_priv') {
  641. $tmp_current_grant = 'CreateView_priv';
  642. $current_grant = 'Create_view_priv';
  643. } elseif ($current_grant == 'Show view_priv') {
  644. $tmp_current_grant = 'ShowView_priv';
  645. $current_grant = 'Show_view_priv';
  646. } else {
  647. $tmp_current_grant = $current_grant;
  648. }
  649. $html_output .= '<div class="item">' . "\n"
  650. . '<input type="checkbox"'
  651. . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
  652. . '" value="Y" '
  653. . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
  654. . 'title="';
  655. $html_output .= (isset($GLOBALS[
  656. 'strPrivDesc' . substr(
  657. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  658. )
  659. ] )
  660. ? $GLOBALS[
  661. 'strPrivDesc' . substr(
  662. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  663. )
  664. ]
  665. : $GLOBALS[
  666. 'strPrivDesc' . substr(
  667. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  668. ) . 'Tbl'
  669. ]
  670. )
  671. . '"/>' . "\n";
  672. $html_output .= '<label for="checkbox_' . $current_grant
  673. . '"><code><dfn title="'
  674. . (isset($GLOBALS[
  675. 'strPrivDesc' . substr(
  676. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  677. )
  678. ])
  679. ? $GLOBALS[
  680. 'strPrivDesc' . substr(
  681. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  682. )
  683. ]
  684. : $GLOBALS[
  685. 'strPrivDesc' . substr(
  686. $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
  687. ) . 'Tbl'
  688. ]
  689. )
  690. . '">'
  691. . strtoupper(
  692. substr($current_grant, 0, strlen($current_grant) - 5)
  693. )
  694. . '</dfn></code></label>' . "\n"
  695. . '</div>' . "\n";
  696. } // end foreach ()
  697. return $html_output;
  698. }
  699. /**
  700. * Get HTML for global or database specific privileges
  701. *
  702. * @param string $db the database
  703. * @param string $table the table
  704. * @param string $row first row from result or boolean false
  705. *
  706. * @return string $html_output
  707. */
  708. function PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row)
  709. {
  710. $privTable_names = array(0 => __('Data'),
  711. 1 => __('Structure'),
  712. 2 => __('Administration')
  713. );
  714. $privTable = array();
  715. // d a t a
  716. $privTable[0] = PMA_getDataPrivilegeTable($db);
  717. // s t r u c t u r e
  718. $privTable[1] = PMA_getStructurePrivilegeTable($table, $row);
  719. // a d m i n i s t r a t i o n
  720. $privTable[2] = PMA_getAdministrationPrivilegeTable($db);
  721. $html_output = '<input type="hidden" name="grant_count" value="'
  722. . (count($privTable[0])
  723. + count($privTable[1])
  724. + count($privTable[2])
  725. - (isset($row['Grant_priv']) ? 1 : 0)
  726. )
  727. . '" />';
  728. $html_output .= '<fieldset id="fieldset_user_global_rights"><legend>';
  729. if ($db == '*') {
  730. $html_output .= __('Global privileges');
  731. } else if ($table == '*') {
  732. $html_output .= __('Database-specific privileges');
  733. } else {
  734. $html_output .= __('Table-specific privileges');
  735. }
  736. $html_output .= ' (<a href="#" '
  737. . 'onclick="setCheckboxes(\'fieldset_user_global_rights\', true); '
  738. . 'return false;">' . __('Check All') . '</a> /'
  739. . '<a href="#" '
  740. . 'onclick="setCheckboxes(\'fieldset_user_global_rights\', false); '
  741. . 'return false;">' . __('Uncheck All') . '</a>)';
  742. $html_output .= '</legend>';
  743. $html_output .= '<p><small><i>'
  744. . __('Note: MySQL privilege names are expressed in English')
  745. . '</i></small></p>';
  746. // Output the Global privilege tables with checkboxes
  747. $html_output .= PMA_getHtmlForGlobalPrivTableWithCheckboxes(
  748. $privTable, $privTable_names, $row
  749. );
  750. // The "Resource limits" box is not displayed for db-specific privs
  751. if ($db == '*') {
  752. $html_output .= PMA_getHtmlForDisplayResourceLimits($row);
  753. }
  754. // for Safari 2.0.2
  755. $html_output .= '<div class="clearfloat"></div>';
  756. return $html_output;
  757. }
  758. /**
  759. * Get data privilege table as an array
  760. *
  761. * @param string $db the database
  762. *
  763. * @return string data privilege table
  764. */
  765. function PMA_getDataPrivilegeTable($db)
  766. {
  767. $data_privTable = array(
  768. array('Select', 'SELECT', __('Allows reading data.')),
  769. array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
  770. array('Update', 'UPDATE', __('Allows changing data.')),
  771. array('Delete', 'DELETE', __('Allows deleting data.'))
  772. );
  773. if ($db == '*') {
  774. $data_privTable[]
  775. = array('File',
  776. 'FILE',
  777. __('Allows importing data from and exporting data into files.')
  778. );
  779. }
  780. return $data_privTable;
  781. }
  782. /**
  783. * Get structure privilege table as an array
  784. *
  785. * @param string $table the table
  786. * @param array $row first row from result or boolean false
  787. *
  788. * @return string structure privilege table
  789. */
  790. function PMA_getStructurePrivilegeTable($table, $row)
  791. {
  792. $structure_privTable = array(
  793. array('Create',
  794. 'CREATE',
  795. ($table == '*'
  796. ? __('Allows creating new databases and tables.')
  797. : __('Allows creating new tables.')
  798. )
  799. ),
  800. array('Alter',
  801. 'ALTER',
  802. __('Allows altering the structure of existing tables.')
  803. ),
  804. array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
  805. array('Drop',
  806. 'DROP',
  807. ($table == '*'
  808. ? __('Allows dropping databases and tables.')
  809. : __('Allows dropping tables.')
  810. )
  811. ),
  812. array('Create_tmp_table',
  813. 'CREATE TEMPORARY TABLES',
  814. __('Allows creating temporary tables.')
  815. ),
  816. array('Show_view',
  817. 'SHOW VIEW',
  818. __('Allows performing SHOW CREATE VIEW queries.')
  819. ),
  820. array('Create_routine',
  821. 'CREATE ROUTINE',
  822. __('Allows creating stored routines.')
  823. ),
  824. array('Alter_routine',
  825. 'ALTER ROUTINE',
  826. __('Allows altering and dropping stored routines.')
  827. ),
  828. array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
  829. );
  830. // this one is for a db-specific priv: Create_view_priv
  831. if (isset($row['Create_view_priv'])) {
  832. $structure_privTable[] = array('Create_view',
  833. 'CREATE VIEW',
  834. __('Allows creating new views.')
  835. );
  836. }
  837. // this one is for a table-specific priv: Create View_priv
  838. if (isset($row['Create View_priv'])) {
  839. $structure_privTable[] = array('Create View',
  840. 'CREATE VIEW',
  841. __('Allows creating new views.')
  842. );
  843. }
  844. if (isset($row['Event_priv'])) {
  845. // MySQL 5.1.6
  846. $structure_privTable[] = array('Event',
  847. 'EVENT',
  848. __('Allows to set up events for the event scheduler')
  849. );
  850. $structure_privTable[] = array('Trigger',
  851. 'TRIGGER',
  852. __('Allows creating and dropping triggers')
  853. );
  854. }
  855. return $structure_privTable;
  856. }
  857. /**
  858. * Get administration privilege table as an array
  859. *
  860. * @param string $db the table
  861. *
  862. * @return string administration privilege table
  863. */
  864. function PMA_getAdministrationPrivilegeTable($db)
  865. {
  866. $administration_privTable = array(
  867. array('Grant',
  868. 'GRANT',
  869. __('Allows adding users and privileges without reloading the privilege tables.')
  870. ),
  871. );
  872. if ($db == '*') {
  873. $administration_privTable[] = array('Super',
  874. 'SUPER',
  875. __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.')
  876. );
  877. $administration_privTable[] = array('Process',
  878. 'PROCESS',
  879. __('Allows viewing processes of all users')
  880. );
  881. $administration_privTable[] = array('Reload',
  882. 'RELOAD',
  883. __('Allows reloading server settings and flushing the server\'s caches.')
  884. );
  885. $administration_privTable[] = array('Shutdown',
  886. 'SHUTDOWN',
  887. __('Allows shutting down the server.')
  888. );
  889. $administration_privTable[] = array('Show_db',
  890. 'SHOW DATABASES',
  891. __('Gives access to the complete list of databases.')
  892. );
  893. }
  894. $administration_privTable[] = array('Lock_tables',
  895. 'LOCK TABLES',
  896. __('Allows locking tables for the current thread.')
  897. );
  898. $administration_privTable[] = array('References',
  899. 'REFERENCES',
  900. __('Has no effect in this MySQL version.')
  901. );
  902. if ($db == '*') {
  903. $administration_privTable[] = array('Repl_client',
  904. 'REPLICATION CLIENT',
  905. __('Allows the user to ask where the slaves / masters are.')
  906. );
  907. $administration_privTable[] = array('Repl_slave',
  908. 'REPLICATION SLAVE',
  909. __('Needed for the replication slaves.')
  910. );
  911. $administration_privTable[] = array('Create_user',
  912. 'CREATE USER',
  913. __('Allows creating, dropping and renaming user accounts.')
  914. );
  915. }
  916. return $administration_privTable;
  917. }
  918. /**
  919. * Get HTML snippet for global privileges table with check boxes
  920. *
  921. * @param array $privTable privileges table array
  922. * @param array $privTable_names names of the privilege tables
  923. * (Data, Structure, Administration)
  924. * @param array $row first row from result or boolean false
  925. *
  926. * @return string $html_output
  927. */
  928. function PMA_getHtmlForGlobalPrivTableWithCheckboxes(
  929. $privTable, $privTable_names, $row
  930. ) {
  931. $html_output = '';
  932. foreach ($privTable as $i => $table) {
  933. $html_output .= '<fieldset>' . "\n"
  934. . '<legend>' . $privTable_names[$i] . '</legend>' . "\n";
  935. foreach ($table as $priv) {
  936. $html_output .= '<div class="item">' . "\n"
  937. . '<input type="checkbox"'
  938. . ' name="' . $priv[0] . '_priv" '
  939. . 'id="checkbox_' . $priv[0] . '_priv"'
  940. . ' value="Y" title="' . $priv[2] . '"'
  941. . (($row[$priv[0] . '_priv'] == 'Y')
  942. ? ' checked="checked"'
  943. : ''
  944. )
  945. . '/>' . "\n"
  946. . '<label for="checkbox_' . $priv[0] . '_priv">'
  947. . '<code><dfn title="' . $priv[2] . '">'
  948. . $priv[1] . '</dfn></code></label>' . "\n"
  949. . '</div>' . "\n";
  950. }
  951. $html_output .= '</fieldset>' . "\n";
  952. }
  953. return $html_output;
  954. }
  955. /**
  956. * Displays the fields used by the "new user" form as well as the
  957. * "change login information / copy user" form.
  958. *
  959. * @param string $mode are we creating a new user or are we just
  960. * changing one? (allowed values: 'new', 'change')
  961. *
  962. * @global array $cfg the phpMyAdmin configuration
  963. * @global ressource $user_link the database connection
  964. *
  965. * @return string $html_output a HTML snippet
  966. */
  967. function PMA_getHtmlForDisplayLoginInformationFields($mode = 'new')
  968. {
  969. list($username_length, $hostname_length) = PMA_getUsernameAndHostnameLength();
  970. if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
  971. $GLOBALS['pred_username'] = 'any';
  972. }
  973. $html_output = '<fieldset id="fieldset_add_user_login">' . "\n"
  974. . '<legend>' . __('Login Information') . '</legend>' . "\n"
  975. . '<div class="item">' . "\n"
  976. . '<label for="select_pred_username">' . "\n"
  977. . ' ' . __('User name') . ':' . "\n"
  978. . '</label>' . "\n"
  979. . '<span class="options">' . "\n";
  980. $html_output .= '<select name="pred_username" id="select_pred_username" '
  981. . 'title="' . __('User name') . '"' . "\n";
  982. $html_output .= ' onchange="'
  983. . 'if (this.value == \'any\') {'
  984. . ' username.value = \'\'; '
  985. . '} else if (this.value == \'userdefined\') {'
  986. . ' username.focus(); username.select(); '
  987. . '}">' . "\n";
  988. $html_output .= '<option value="any"'
  989. . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any')
  990. ? ' selected="selected"'
  991. : '') . '>'
  992. . __('Any user')
  993. . '</option>' . "\n";
  994. $html_output .= '<option value="userdefined"'
  995. . ((! isset($GLOBALS['pred_username'])
  996. || $GLOBALS['pred_username'] == 'userdefined'
  997. )
  998. ? ' selected="selected"'
  999. : '') . '>'
  1000. . __('Use text field')
  1001. . ':</option>' . "\n";
  1002. $html_output .= '</select>' . "\n"
  1003. . '</span>' . "\n";
  1004. $html_output .= '<input type="text" name="username" class="autofocus"'
  1005. . ' maxlength="' . $username_length . '" title="' . __('User name') . '"'
  1006. . (empty($GLOBALS['username'])
  1007. ? ''
  1008. : ' value="' . htmlspecialchars(
  1009. isset($GLOBALS['new_username'])
  1010. ? $GLOBALS['new_username']
  1011. : $GLOBALS['username']
  1012. ) . '"'
  1013. )
  1014. . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
  1015. . '</div>' . "\n";
  1016. $html_output .= '<div class="item">' . "\n"
  1017. . '<label for="select_pred_hostname">' . "\n"
  1018. . ' ' . __('Host') . ':' . "\n"
  1019. . '</label>' . "\n";
  1020. $html_output .= '<span class="options">' . "\n"
  1021. . ' <select name="pred_hostname" id="select_pred_hostname" '
  1022. . 'title="' . __('Host') . '"' . "\n";
  1023. $_current_user = PMA_DBI_fetch_value('SELECT USER();');
  1024. if (! empty($_current_user)) {
  1025. $thishost = str_replace(
  1026. "'",
  1027. '',
  1028. substr($_current_user, (strrpos($_current_user, '@') + 1))
  1029. );
  1030. if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
  1031. unset($thishost);
  1032. }
  1033. }
  1034. $html_output .= ' onchange="'
  1035. . 'if (this.value == \'any\') { '
  1036. . ' hostname.value = \'%\'; '
  1037. . '} else if (this.value == \'localhost\') { '
  1038. . ' hostname.value = \'localhost\'; '
  1039. . '} '
  1040. . (empty($thishost)
  1041. ? ''
  1042. : 'else if (this.value == \'thishost\') { '
  1043. . ' hostname.value = \'' . addslashes(htmlspecialchars($thishost))
  1044. . '\'; '
  1045. . '} '
  1046. )
  1047. . 'else if (this.value == \'hosttable\') { '
  1048. . ' hostname.value = \'\'; '
  1049. . '} else if (this.value == \'userdefined\') {'
  1050. . ' hostname.focus(); hostname.select(); '
  1051. . '}">' . "\n";
  1052. unset($_current_user);
  1053. // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
  1054. if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
  1055. switch (strtolower($GLOBALS['hostname'])) {
  1056. case 'localhost':
  1057. case '127.0.0.1':
  1058. $GLOBALS['pred_hostname'] = 'localhost';
  1059. break;
  1060. case '%':
  1061. $GLOBALS['pred_hostname'] = 'any';
  1062. break;
  1063. default:
  1064. $GLOBALS['pred_hostname'] = 'userdefined';
  1065. break;
  1066. }
  1067. }
  1068. $html_output .= '<option value="any"'
  1069. . ((isset($GLOBALS['pred_hostname'])
  1070. && $GLOBALS['pred_hostname'] == 'any'
  1071. )
  1072. ? ' selected="selected"'
  1073. : '') . '>'
  1074. . __('Any host')
  1075. . '</option>' . "\n"
  1076. . '<option value="localhost"'
  1077. . ((isset($GLOBALS['pred_hostname'])
  1078. && $GLOBALS['pred_hostname'] == 'localhost'
  1079. )
  1080. ? ' selected="selected"'
  1081. : '') . '>'
  1082. . __('Local')
  1083. . '</option>' . "\n";
  1084. if (! empty($thishost)) {
  1085. $html_output .= '<option value="thishost"'
  1086. . ((isset($GLOBALS['pred_hostname'])
  1087. && $GLOBALS['pred_hostname'] == 'thishost'
  1088. )
  1089. ? ' selected="selected"'
  1090. : '') . '>'
  1091. . __('This Host')
  1092. . '</option>' . "\n";
  1093. }
  1094. unset($thishost);
  1095. $html_output .= '<option value="hosttable"'
  1096. . ((isset($GLOBALS['pred_hostname'])
  1097. && $GLOBALS['pred_hostname'] == 'hosttable'
  1098. )
  1099. ? ' selected="selected"'
  1100. : '') . '>'
  1101. . __('Use Host Table')
  1102. . '</option>' . "\n";
  1103. $html_output .= '<option value="userdefined"'
  1104. . ((isset($GLOBALS['pred_hostname'])
  1105. && $GLOBALS['pred_hostname'] == 'userdefined'
  1106. )
  1107. ? ' selected="selected"'
  1108. : '') . '>'
  1109. . __('Use text field') . ':</option>' . "\n"
  1110. . '</select>' . "\n"
  1111. . '</span>' . "\n";
  1112. $html_output .= '<input type="text" name="hostname" maxlength="'
  1113. . $hostname_length . '" value="'
  1114. . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
  1115. . '" title="' . __('Host')
  1116. . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
  1117. . PMA_Util::showHint(
  1118. __('When Host table is used, this field is ignored and values stored in Host table are used instead.')
  1119. )
  1120. . '</div>' . "\n";
  1121. $html_output .= '<div class="item">' . "\n"
  1122. . '<label for="select_pred_password">' . "\n"
  1123. . ' ' . __('Password') . ':' . "\n"
  1124. . '</label>' . "\n"
  1125. . '<span class="options">' . "\n"
  1126. . '<select name="pred_password" id="select_pred_password" title="'
  1127. . __('Password') . '"' . "\n";
  1128. $html_output .= ' onchange="'
  1129. . 'if (this.value == \'none\') { '
  1130. . ' pma_pw.value = \'\'; pma_pw2.value = \'\'; '
  1131. . '} else if (this.value == \'userdefined\') { '
  1132. . ' pma_pw.focus(); pma_pw.select(); '
  1133. . '}">' . "\n"
  1134. . ($mode == 'change' ? '<option value="keep" selected="selected">'
  1135. . __('Do not change the password')
  1136. . '</option>' . "\n" : '')
  1137. . '<option value="none"';
  1138. if (isset($GLOBALS['username']) && $mode != 'change') {
  1139. $html_output .= ' selected="selected"';
  1140. }
  1141. $html_output .= '>' . __('No Password') . '</option>' . "\n"
  1142. . '<option value="userdefined"'
  1143. . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>'
  1144. . __('Use text field')
  1145. . ':</option>' . "\n"
  1146. . '</select>' . "\n"
  1147. . '</span>' . "\n"
  1148. . '<input type="password" id="text_pma_pw" name="pma_pw" '
  1149. . 'title="' . __('Password') . '" '
  1150. . 'onchange="pred_password.value = \'userdefined\';" />' . "\n"
  1151. . '</div>' . "\n";
  1152. $html_output .= '<div class="item" '
  1153. . 'id="div_element_before_generate_password">' . "\n"
  1154. . '<label for="text_pma_pw2">' . "\n"
  1155. . ' ' . __('Re-type') . ':' . "\n"
  1156. . '</label>' . "\n"
  1157. . '<span class="options">&nbsp;</span>' . "\n"
  1158. . '<input type="password" name="pma_pw2" id="text_pma_pw2" '
  1159. . 'title="' . __('Re-type') . '" '
  1160. . 'onchange="pred_password.value = \'userdefined\';" />' . "\n"
  1161. . '</div>' . "\n"
  1162. // Generate password added here via jQuery
  1163. . '</fieldset>' . "\n";
  1164. return $html_output;
  1165. } // end of the 'PMA_displayUserAndHostFields()' function
  1166. /**
  1167. * Get username and hostname length
  1168. *
  1169. * @return array username length and hostname length
  1170. */
  1171. function PMA_getUsernameAndHostnameLength()
  1172. {
  1173. $fields_info = PMA_DBI_get_columns('mysql', 'user', null, true);
  1174. $username_length = 16;
  1175. $hostname_length = 41;
  1176. foreach ($fields_info as $val) {
  1177. if ($val['Field'] == 'User') {
  1178. strtok($val['Type'], '()');
  1179. $value = strtok('()');
  1180. if (is_int($value)) {
  1181. $username_length = $value;
  1182. }
  1183. } elseif ($val['Field'] == 'Host') {
  1184. strtok($val['Type'], '()');
  1185. $value = strtok('()');
  1186. if (is_int($value)) {
  1187. $hostname_length = $value;
  1188. }
  1189. }
  1190. }
  1191. return array($username_length, $hostname_length);
  1192. }
  1193. /**
  1194. * Returns all the grants for a certain user on a certain host
  1195. * Used in the export privileges for all users section
  1196. *
  1197. * @param string $user User name
  1198. * @param string $host Host name
  1199. *
  1200. * @return string containing all the grants text
  1201. */
  1202. function PMA_getGrants($user, $host)
  1203. {
  1204. $grants = PMA_DBI_fetch_result(
  1205. "SHOW GRANTS FOR '"
  1206. . PMA_Util::sqlAddSlashes($user) . "'@'"
  1207. . PMA_Util::sqlAddSlashes($host) . "'"
  1208. );
  1209. $response = '';
  1210. foreach ($grants as $one_grant) {
  1211. $response .= $one_grant . ";\n\n";
  1212. }
  1213. return $response;
  1214. } // end of the 'PMA_getGrants()' function
  1215. /**
  1216. * Update password and get message for password updating
  1217. *
  1218. * @param string $err_url error url
  1219. * @param string $username username
  1220. * @param string $hostname hostname
  1221. *
  1222. * @return string $message success or error message after updating password
  1223. */
  1224. function PMA_getMessageForUpdatePassword($err_url, $username, $hostname)
  1225. {
  1226. // similar logic in user_password.php
  1227. $message = '';
  1228. if (empty($_REQUEST['nopass'])
  1229. && isset($_POST['pma_pw'])
  1230. && isset($_POST['pma_pw2'])
  1231. ) {
  1232. if ($_POST['pma_pw'] != $_POST['pma_pw2']) {
  1233. $message = PMA_Message::error(__('The passwords aren\'t the same!'));
  1234. } elseif (empty($_POST['pma_pw']) || empty($_POST['pma_pw2'])) {
  1235. $message = PMA_Message::error(__('The password is empty!'));
  1236. }
  1237. }
  1238. // here $nopass could be == 1
  1239. if (empty($message)) {
  1240. $hashing_function
  1241. = (! empty($_REQUEST['pw_hash']) && $_REQUEST['pw_hash'] == 'old'
  1242. ? 'OLD_'
  1243. : ''
  1244. )
  1245. . 'PASSWORD';
  1246. // in $sql_query which will be displayed, hide the password
  1247. $sql_query = 'SET PASSWORD FOR \''
  1248. . PMA_Util::sqlAddSlashes($username)
  1249. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\' = '
  1250. . (($_POST['pma_pw'] == '')
  1251. ? '\'\''
  1252. : $hashing_function . '(\''
  1253. . preg_replace('@.@s', '*', $_POST['pma_pw']) . '\')');
  1254. $local_query = 'SET PASSWORD FOR \''
  1255. . PMA_Util::sqlAddSlashes($username)
  1256. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\' = '
  1257. . (($_POST['pma_pw'] == '') ? '\'\'' : $hashing_function
  1258. . '(\'' . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\')');
  1259. PMA_DBI_try_query($local_query)
  1260. or PMA_Util::mysqlDie(
  1261. PMA_DBI_getError(), $sql_query, false, $err_url
  1262. );
  1263. $message = PMA_Message::success(
  1264. __('The password for %s was changed successfully.')
  1265. );
  1266. $message->addParam(
  1267. '\'' . htmlspecialchars($username)
  1268. . '\'@\'' . htmlspecialchars($hostname) . '\''
  1269. );
  1270. }
  1271. return $message;
  1272. }
  1273. /**
  1274. * Revokes privileges and get message and SQL query for privileges revokes
  1275. *
  1276. * @param string $db_and_table wildcard Escaped database+table specification
  1277. * @param string $dbname database name
  1278. * @param string $tablename table name
  1279. * @param string $username username
  1280. * @param string $hostname host name
  1281. *
  1282. * @return array ($message, $sql_query)
  1283. */
  1284. function PMA_getMessageAndSqlQueryForPrivilegesRevoke($db_and_table, $dbname,
  1285. $tablename, $username, $hostname
  1286. ) {
  1287. $db_and_table = PMA_wildcardEscapeForGrant($dbname, $tablename);
  1288. $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
  1289. . ' FROM \''
  1290. . PMA_Util::sqlAddSlashes($username) . '\'@\''
  1291. . PMA_Util::sqlAddSlashes($hostname) . '\';';
  1292. $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
  1293. . ' FROM \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
  1294. . PMA_Util::sqlAddSlashes($hostname) . '\';';
  1295. PMA_DBI_query($sql_query0);
  1296. if (! PMA_DBI_try_query($sql_query1)) {
  1297. // this one may fail, too...
  1298. $sql_query1 = '';
  1299. }
  1300. $sql_query = $sql_query0 . ' ' . $sql_query1;
  1301. $message = PMA_Message::success(
  1302. __('You have revoked the privileges for %s')
  1303. );
  1304. $message->addParam(
  1305. '\'' . htmlspecialchars($username)
  1306. . '\'@\'' . htmlspecialchars($hostname) . '\''
  1307. );
  1308. return array($message, $sql_query);
  1309. }
  1310. /**
  1311. * Get a WITH clause for 'update privileges' and 'add user'
  1312. *
  1313. * @return string $sql_query
  1314. */
  1315. function PMA_getWithClauseForAddUserAndUpdatePrivs()
  1316. {
  1317. $sql_query = '';
  1318. if (isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y') {
  1319. $sql_query .= ' GRANT OPTION';
  1320. }
  1321. if (isset($_POST['max_questions'])) {
  1322. $max_questions = max(0, (int)$_POST['max_questions']);
  1323. $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
  1324. }
  1325. if (isset($_POST['max_connections'])) {
  1326. $max_connections = max(0, (int)$_POST['max_connections']);
  1327. $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
  1328. }
  1329. if (isset($_POST['max_updates'])) {
  1330. $max_updates = max(0, (int)$_POST['max_updates']);
  1331. $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
  1332. }
  1333. if (isset($_POST['max_user_connections'])) {
  1334. $max_user_connections = max(0, (int)$_POST['max_user_connections']);
  1335. $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
  1336. }
  1337. return ((!empty($sql_query)) ? 'WITH' . $sql_query : '');
  1338. }
  1339. /**
  1340. * Get HTML for addUsersForm, This function call if isset($_REQUEST['adduser'])
  1341. *
  1342. * @param string $dbname
  1343. *
  1344. * @return string HTML for addUserForm
  1345. */
  1346. function PMA_getHtmlForAddUser($dbname)
  1347. {
  1348. $GLOBALS['url_query'] .= '&amp;adduser=1';
  1349. $html_output = '<h2>' . "\n"
  1350. . PMA_Util::getIcon('b_usradd.png') . __('Add user') . "\n"
  1351. . '</h2>' . "\n"
  1352. . '<form name="usersForm" class="ajax" id="addUsersForm"'
  1353. . ' action="server_privileges.php" method="post" autocomplete="off" >' . "\n"
  1354. . PMA_generate_common_hidden_inputs('', '')
  1355. . PMA_getHtmlForDisplayLoginInformationFields('new');
  1356. $html_output .= '<fieldset id="fieldset_add_user_database">' . "\n"
  1357. . '<legend>' . __('Database for user') . '</legend>' . "\n";
  1358. $html_output .= PMA_Util::getCheckbox(
  1359. 'createdb-1',
  1360. __('Create database with same name and grant all privileges'),
  1361. false, false
  1362. );
  1363. $html_output .= '<br />' . "\n";
  1364. $html_output .= PMA_Util::getCheckbox(
  1365. 'createdb-2',
  1366. __('Grant all privileges on wildcard name (username\\_%)'),
  1367. false, false
  1368. );
  1369. $html_output .= '<br />' . "\n";
  1370. if (! empty($dbname) ) {
  1371. $html_output .= PMA_Util::getCheckbox(
  1372. 'createdb-3',
  1373. sprintf(__('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname)),
  1374. true,
  1375. false
  1376. );
  1377. $html_output .= '<input type="hidden" name="dbname" value="'
  1378. . htmlspecialchars($dbname) . '" />' . "\n";
  1379. $html_output .= '<br />' . "\n";
  1380. }
  1381. $html_output .= '</fieldset>' . "\n";
  1382. $html_output .= PMA_getHtmlToDisplayPrivilegesTable('*', '*', false);
  1383. $html_output .= '<fieldset id="fieldset_add_user_footer" class="tblFooters">'
  1384. . "\n"
  1385. . '<input type="submit" name="adduser_submit" '
  1386. . 'value="' . __('Go') . '" />' . "\n"
  1387. . '</fieldset>' . "\n"
  1388. . '</form>' . "\n";
  1389. return $html_output;
  1390. }
  1391. /**
  1392. * Get the list of privileges and list of compared privileges as strings
  1393. * and return a array that contains both strings
  1394. *
  1395. * @return array $list_of_privileges, $list_of_compared_privileges
  1396. */
  1397. function PMA_getListOfPrivilegesAndComparedPrivileges()
  1398. {
  1399. $list_of_privileges
  1400. = '`User`, '
  1401. . '`Host`, '
  1402. . '`Select_priv`, '
  1403. . '`Insert_priv`, '
  1404. . '`Update_priv`, '
  1405. . '`Delete_priv`, '
  1406. . '`Create_priv`, '
  1407. . '`Drop_priv`, '
  1408. . '`Grant_priv`, '
  1409. . '`Index_priv`, '
  1410. . '`Alter_priv`, '
  1411. . '`References_priv`, '
  1412. . '`Create_tmp_table_priv`, '
  1413. . '`Lock_tables_priv`, '
  1414. . '`Create_view_priv`, '
  1415. . '`Show_view_priv`, '
  1416. . '`Create_routine_priv`, '
  1417. . '`Alter_routine_priv`, '
  1418. . '`Execute_priv`';
  1419. $list_of_compared_privileges
  1420. = '`Select_priv` = \'N\''
  1421. . ' AND `Insert_priv` = \'N\''
  1422. . ' AND `Update_priv` = \'N\''
  1423. . ' AND `Delete_priv` = \'N\''
  1424. . ' AND `Create_priv` = \'N\''
  1425. . ' AND `Drop_priv` = \'N\''
  1426. . ' AND `Grant_priv` = \'N\''
  1427. . ' AND `References_priv` = \'N\''
  1428. . ' AND `Create_tmp_table_priv` = \'N\''
  1429. . ' AND `Lock_tables_priv` = \'N\''
  1430. . ' AND `Create_view_priv` = \'N\''
  1431. . ' AND `Show_view_priv` = \'N\''
  1432. . ' AND `Create_routine_priv` = \'N\''
  1433. . ' AND `Alter_routine_priv` = \'N\''
  1434. . ' AND `Execute_priv` = \'N\'';
  1435. if (PMA_MYSQL_INT_VERSION >= 50106) {
  1436. $list_of_privileges .=
  1437. ', `Event_priv`, '
  1438. . '`Trigger_priv`';
  1439. $list_of_compared_privileges .=
  1440. ' AND `Event_priv` = \'N\''
  1441. . ' AND `Trigger_priv` = \'N\'';
  1442. }
  1443. return array($list_of_privileges, $list_of_compared_privileges);
  1444. }
  1445. /**
  1446. * Get the HTML for user form and check the privileges for a particular database.
  1447. *
  1448. * @param string $link_edit standard link for edit
  1449. * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
  1450. *
  1451. * @return string $html_output
  1452. */
  1453. function PMA_getHtmlForSpecificDbPrivileges($link_edit, $conditional_class)
  1454. {
  1455. // check the privileges for a particular database.
  1456. $html_output = '<form id="usersForm" action="server_privileges.php">'
  1457. . '<fieldset>' . "\n";
  1458. $html_output .= '<legend>' . "\n"
  1459. . PMA_Util::getIcon('b_usrcheck.png')
  1460. . ' '
  1461. . sprintf(
  1462. __('Users having access to &quot;%s&quot;'),
  1463. '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
  1464. . PMA_generate_common_url($_REQUEST['checkprivs']) . '">'
  1465. . htmlspecialchars($_REQUEST['checkprivs'])
  1466. . '</a>'
  1467. )
  1468. . "\n"
  1469. . '</legend>' . "\n";
  1470. $html_output .= '<table id="dbspecificuserrights" class="data">' . "\n"
  1471. . '<thead>' . "\n"
  1472. . '<tr><th>' . __('User') . '</th>' . "\n"
  1473. . '<th>' . __('Host') . '</th>' . "\n"
  1474. . '<th>' . __('Type') . '</th>' . "\n"
  1475. . '<th>' . __('Privileges') . '</th>' . "\n"
  1476. . '<th>' . __('Grant') . '</th>' . "\n"
  1477. . '<th>' . __('Action') . '</th>' . "\n"
  1478. . '</tr>' . "\n"
  1479. . '</thead>' . "\n";
  1480. $odd_row = true;
  1481. // now, we build the table...
  1482. list($list_of_privileges, $list_of_compared_privileges)
  1483. = PMA_getListOfPrivilegesAndComparedPrivileges();
  1484. $sql_query = '(SELECT ' . $list_of_privileges . ', `Db`'
  1485. .' FROM `mysql`.`db`'
  1486. .' WHERE \'' . PMA_Util::sqlAddSlashes($_REQUEST['checkprivs'])
  1487. . "'"
  1488. .' LIKE `Db`'
  1489. .' AND NOT (' . $list_of_compared_privileges. ')) '
  1490. .'UNION '
  1491. .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
  1492. .' FROM `mysql`.`user` '
  1493. .' WHERE NOT (' . $list_of_compared_privileges . ')) '
  1494. .' ORDER BY `User` ASC,'
  1495. .' `Host` ASC,'
  1496. .' `Db` ASC;';
  1497. $res = PMA_DBI_query($sql_query);
  1498. $row = PMA_DBI_fetch_assoc($res);
  1499. if ($row) {
  1500. $found = true;
  1501. }
  1502. $html_output .= PMA_getHtmlTableBodyForSpecificDbPrivs(
  1503. $found, $row, $odd_row, $link_edit, $res
  1504. );
  1505. $html_output .= '</table>'
  1506. . '</fieldset>'
  1507. . '</form>' . "\n";
  1508. if ($GLOBALS['is_ajax_request'] == true && empty($_REQUEST['ajax_page_request'])) {
  1509. $message = PMA_Message::success(__('User has been added.'));
  1510. $response = PMA_Response::getInstance();
  1511. $response->addJSON('message', $message);
  1512. $response->addJSON('user_form', $html_output);
  1513. exit;
  1514. } else {
  1515. // Offer to create a new user for the current database
  1516. $html_output .= '<fieldset id="fieldset_add_user">' . "\n"
  1517. . '<legend>' . _pgettext('Create new user', 'New') . '</legend>' . "\n";
  1518. $html_output .= '<a href="server_privileges.php?'
  1519. . $GLOBALS['url_query'] . '&amp;adduser=1&amp;'
  1520. . 'dbname=' . htmlspecialchars($_REQUEST['checkprivs'])
  1521. .'" rel="'
  1522. .'checkprivs='.htmlspecialchars($_REQUEST['checkprivs'])
  1523. . '&amp;'.$GLOBALS['url_query']
  1524. . '" class="'.$conditional_class
  1525. .'" name="db_specific">' . "\n"
  1526. . PMA_Util::getIcon('b_usradd.png')
  1527. . ' ' . __('Add user') . '</a>' . "\n";
  1528. $html_output .= '</fieldset>' . "\n";
  1529. }
  1530. return $html_output;
  1531. }
  1532. /**
  1533. * Get HTML snippet for table body of specific database privileges
  1534. *
  1535. * @param boolean $found whether user found or not
  1536. * @param array $row array of rows from mysql,
  1537. * db table with list of privileges
  1538. * @param boolean $odd_row whether odd or not
  1539. * @param string $link_edit standard link for edit
  1540. * @param string $res ran sql query
  1541. *
  1542. * @return string $html_output
  1543. */
  1544. function PMA_getHtmlTableBodyForSpecificDbPrivs($found, $row, $odd_row,
  1545. $link_edit, $res
  1546. ) {
  1547. $html_output = '<tbody>' . "\n";
  1548. if ($found) {
  1549. while (true) {
  1550. // prepare the current user
  1551. $current_privileges = array();
  1552. $current_user = $row['User'];
  1553. $current_host = $row['Host'];
  1554. while ($row
  1555. && $current_user == $row['User']
  1556. && $current_host == $row['Host']
  1557. ) {
  1558. $current_privileges[] = $row;
  1559. $row = PMA_DBI_fetch_assoc($res);
  1560. }
  1561. $html_output .= '<tr '
  1562. . 'class="noclick ' . ($odd_row ? 'odd' : 'even')
  1563. . '">' . "\n"
  1564. . '<td';
  1565. if (count($current_privileges) > 1) {
  1566. $html_output .= ' rowspan="' . count($current_privileges) . '"';
  1567. }
  1568. $html_output .= '>'
  1569. . (empty($current_user)
  1570. ? '<span style="color: #FF0000">' . __('Any') . '</span>'
  1571. : htmlspecialchars($current_user)) . "\n"
  1572. . '</td>' . "\n";
  1573. $html_output .= '<td';
  1574. if (count($current_privileges) > 1) {
  1575. $html_output .= ' rowspan="' . count($current_privileges) . '"';
  1576. }
  1577. $html_output .= '>'
  1578. . htmlspecialchars($current_host) . '</td>' . "\n";
  1579. for ($i = 0; $i < count($current_privileges); $i++) {
  1580. $current = $current_privileges[$i];
  1581. $html_output .= '<td>' . "\n"
  1582. . ' ';
  1583. if (! isset($current['Db']) || $current['Db'] == '*') {
  1584. $html_output .= __('global');
  1585. } elseif (
  1586. $current['Db'] == PMA_Util::escapeMysqlWildcards(
  1587. $_REQUEST['checkprivs']
  1588. )
  1589. ) {
  1590. $html_output .= __('database-specific');
  1591. } else {
  1592. $html_output .= __('wildcard'). ': '
  1593. . '<code>' . htmlspecialchars($current['Db']) . '</code>';
  1594. }
  1595. $html_output .= "\n"
  1596. . '</td>' . "\n";
  1597. $html_output .='<td>' . "\n"
  1598. . '<code>' . "\n"
  1599. . ''
  1600. . join(
  1601. ',' . "\n" . ' ',
  1602. PMA_extractPrivInfo($current, true)
  1603. )
  1604. . "\n"
  1605. . '</code>' . "\n"
  1606. . '</td>' . "\n";
  1607. $html_output .= '<td>' . "\n"
  1608. . '' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No'))
  1609. . "\n"
  1610. . '</td>' . "\n"
  1611. . '<td>' . "\n";
  1612. $html_output .= sprintf(
  1613. $link_edit,
  1614. urlencode($current_user),
  1615. urlencode($current_host),
  1616. urlencode(
  1617. ! (isset($current['Db']) || $current['Db'] == '*') ? '' : $current['Db']
  1618. ),
  1619. ''
  1620. );
  1621. $html_output .= '</td>' . "\n"
  1622. . ' </tr>' . "\n";
  1623. if (($i + 1) < count($current_privileges)) {
  1624. $html_output .= '<tr '
  1625. . 'class="noclick ' . ($odd_row ? 'odd' : 'even') . '">'
  1626. . "\n";
  1627. }
  1628. }
  1629. if (empty($row)) {
  1630. break;
  1631. }
  1632. $odd_row = ! $odd_row;
  1633. }
  1634. } else {
  1635. $html_output .= '<tr class="odd">' . "\n"
  1636. . '<td colspan="6">' . "\n"
  1637. . ' ' . __('No user found.') . "\n"
  1638. . '</td>' . "\n"
  1639. . '</tr>' . "\n";
  1640. }
  1641. $html_output .= '</tbody>' . "\n";
  1642. return $html_output;
  1643. }
  1644. /**
  1645. * Define some standard links
  1646. * $link_edit, $link_revoke, $link_export
  1647. *
  1648. * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
  1649. *
  1650. * @return array with some standard links
  1651. */
  1652. function PMA_getStandardLinks($conditional_class)
  1653. {
  1654. $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '"'
  1655. . ' href="server_privileges.php?'
  1656. . str_replace('%', '%%', $GLOBALS['url_query'])
  1657. . '&amp;username=%s'
  1658. . '&amp;hostname=%s'
  1659. . '&amp;dbname=%s'
  1660. . '&amp;tablename=%s">'
  1661. . PMA_Util::getIcon('b_usredit.png', __('Edit Privileges'))
  1662. . '</a>';
  1663. $link_revoke = '<a href='
  1664. .'"server_privileges.php?'
  1665. . str_replace('%', '%%', $GLOBALS['url_query'])
  1666. . '&amp;username=%s'
  1667. . '&amp;hostname=%s'
  1668. . '&amp;dbname=%s'
  1669. . '&amp;tablename=%s'
  1670. . '&amp;revokeall=1">'
  1671. . PMA_Util::getIcon('b_usrdrop.png', __('Revoke'))
  1672. . '</a>';
  1673. $link_export = '<a class="export_user_anchor ' . $conditional_class . '"'
  1674. . ' href="server_privileges.php?'
  1675. . str_replace('%', '%%', $GLOBALS['url_query'])
  1676. . '&amp;username=%s'
  1677. . '&amp;hostname=%s'
  1678. . '&amp;initial=%s'
  1679. . '&amp;export=1">'
  1680. . PMA_Util::getIcon('b_tblexport.png', __('Export'))
  1681. . '</a>';
  1682. return array($link_edit, $link_revoke, $link_export);
  1683. }
  1684. /**
  1685. * This function return the extra data array for the ajax behavior
  1686. *
  1687. * @param string $password password
  1688. * @param string $link_export export link
  1689. * @param string $sql_query sql query
  1690. * @param string $link_edit standard link for edit
  1691. * @param string $hostname hostname
  1692. * @param string $username username
  1693. *
  1694. * @return array $extra_data
  1695. */
  1696. function PMA_getExtraDataForAjaxBehavior($password, $link_export, $sql_query,
  1697. $link_edit, $hostname, $username
  1698. ) {
  1699. if (isset($GLOBALS['dbname'])) {
  1700. //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
  1701. if (preg_match('/(?<!\\\\)(?:_|%)/i', $GLOBALS['dbname'])) {
  1702. $dbname_is_wildcard = true;
  1703. } else {
  1704. $dbname_is_wildcard = false;
  1705. }
  1706. }
  1707. $extra_data = array();
  1708. if (strlen($sql_query)) {
  1709. $extra_data['sql_query']
  1710. = PMA_Util::getMessage(null, $sql_query);
  1711. }
  1712. if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
  1713. /**
  1714. * generate html on the fly for the new user that was just created.
  1715. */
  1716. $new_user_string = '<tr>'."\n"
  1717. . '<td> <input type="checkbox" name="selected_usr[]" '
  1718. . 'id="checkbox_sel_users_"'
  1719. . 'value="'
  1720. . htmlspecialchars($username)
  1721. . '&amp;#27;' . htmlspecialchars($hostname) . '" />'
  1722. . '</td>' . "\n"
  1723. . '<td><label for="checkbox_sel_users_">'
  1724. . (empty($_REQUEST['username'])
  1725. ? '<span style="color: #FF0000">' . __('Any') . '</span>'
  1726. : htmlspecialchars($username) ) . '</label></td>' . "\n"
  1727. . '<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
  1728. $new_user_string .= '<td>';
  1729. if (! empty($password) || isset($_POST['pma_pw'])) {
  1730. $new_user_string .= __('Yes');
  1731. } else {
  1732. $new_user_string .= '<span style="color: #FF0000">'
  1733. . __('No')
  1734. . '</span>';
  1735. };
  1736. $new_user_string .= '</td>'."\n";
  1737. $new_user_string .= '<td>'
  1738. . '<code>' . join(', ', PMA_extractPrivInfo('', true)) . '</code>'
  1739. . '</td>'; //Fill in privileges here
  1740. $new_user_string .= '<td>';
  1741. if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')) {
  1742. $new_user_string .= __('Yes');
  1743. } else {
  1744. $new_user_string .= __('No');
  1745. }
  1746. $new_user_string .='</td>';
  1747. $new_user_string .= '<td>'
  1748. . sprintf(
  1749. $link_edit,
  1750. urlencode($username),
  1751. urlencode($hostname),
  1752. '',
  1753. ''
  1754. )
  1755. . '</td>' . "\n";
  1756. $new_user_string .= '<td>'
  1757. . sprintf(
  1758. $link_export,
  1759. urlencode($username),
  1760. urlencode($hostname),
  1761. (isset($_GET['initial']) ? $_GET['initial'] : '')
  1762. )
  1763. . '</td>' . "\n";
  1764. $new_user_string .= '</tr>';
  1765. $extra_data['new_user_string'] = $new_user_string;
  1766. /**
  1767. * Generate the string for this alphabet's initial, to update the user
  1768. * pagination
  1769. */
  1770. $new_user_initial = strtoupper(substr($username, 0, 1));
  1771. $new_user_initial_string = '<a href="server_privileges.php?'
  1772. . $GLOBALS['url_query'] . '&initial=' . $new_user_initial .'">'
  1773. . $new_user_initial . '</a>';
  1774. $extra_data['new_user_initial'] = $new_user_initial;
  1775. $extra_data['new_user_initial_string'] = $new_user_initial_string;
  1776. }
  1777. if (isset($_POST['update_privs'])) {
  1778. $extra_data['db_specific_privs'] = false;
  1779. $extra_data['db_wildcard_privs'] = false;
  1780. if (isset($dbname_is_wildcard)) {
  1781. $extra_data['db_specific_privs'] = ! $dbname_is_wildcard;
  1782. $extra_data['db_wildcard_privs'] = $dbname_is_wildcard;
  1783. }
  1784. $new_privileges = join(', ', PMA_extractPrivInfo('', true));
  1785. $extra_data['new_privileges'] = $new_privileges;
  1786. }
  1787. return $extra_data;
  1788. }
  1789. /**
  1790. * Get the HTML snippet for change user login information
  1791. *
  1792. * @param string $username username
  1793. * @param string $hostname host name
  1794. *
  1795. * @return string HTML snippet
  1796. */
  1797. function PMA_getChangeLoginInformationHtmlForm($username, $hostname)
  1798. {
  1799. $choices = array(
  1800. '4' => __('… keep the old one.'),
  1801. '1' => __('… delete the old one from the user tables.'),
  1802. '2' => __('… revoke all active privileges from the old one and delete it afterwards.'),
  1803. '3' => __('… delete the old one from the user tables and reload the privileges afterwards.'));
  1804. $class = ' ajax';
  1805. $html_output = '<form action="server_privileges.php" '
  1806. . 'method="post" class="copyUserForm' . $class .'">' . "\n"
  1807. . PMA_generate_common_hidden_inputs('', '')
  1808. . '<input type="hidden" name="old_username" '
  1809. . 'value="' . htmlspecialchars($username) . '" />' . "\n"
  1810. . '<input type="hidden" name="old_hostname" '
  1811. . 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
  1812. . '<fieldset id="fieldset_change_copy_user">' . "\n"
  1813. . '<legend>' . __('Change Login Information / Copy User')
  1814. . '</legend>' . "\n"
  1815. . PMA_getHtmlForDisplayLoginInformationFields('change');
  1816. $html_output .= '<fieldset id="fieldset_mode">' . "\n"
  1817. . ' <legend>'
  1818. . __('Create a new user with the same privileges and …')
  1819. . '</legend>' . "\n";
  1820. $html_output .= PMA_Util::getRadioFields(
  1821. 'mode', $choices, '4', true
  1822. );
  1823. $html_output .= '</fieldset>' . "\n"
  1824. . '</fieldset>' . "\n";
  1825. $html_output .= '<fieldset id="fieldset_change_copy_user_footer" '
  1826. . 'class="tblFooters">' . "\n"
  1827. . '<input type="submit" name="change_copy" '
  1828. . 'value="' . __('Go') . '" />' . "\n"
  1829. . '</fieldset>' . "\n"
  1830. . '</form>' . "\n";
  1831. return $html_output;
  1832. }
  1833. /**
  1834. * Provide a line with links to the relevant database and table
  1835. *
  1836. * @param string $url_dbname url database name that urlencode() string
  1837. * @param string $dbname database name
  1838. * @param string $tablename table name
  1839. *
  1840. * @return string HTML snippet
  1841. */
  1842. function PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename)
  1843. {
  1844. $html_output = '[ ' . __('Database')
  1845. . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
  1846. . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
  1847. . htmlspecialchars($dbname) . ': '
  1848. . PMA_Util::getTitleForTarget(
  1849. $GLOBALS['cfg']['DefaultTabDatabase']
  1850. )
  1851. . "</a> ]\n";
  1852. if (strlen($tablename)) {
  1853. $html_output .= ' [ ' . __('Table') . ' <a href="'
  1854. . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
  1855. . '&amp;db=' . $url_dbname
  1856. . '&amp;table=' . htmlspecialchars(urlencode($tablename))
  1857. . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
  1858. . PMA_Util::getTitleForTarget(
  1859. $GLOBALS['cfg']['DefaultTabTable']
  1860. )
  1861. . "</a> ]\n";
  1862. }
  1863. return $html_output;
  1864. }
  1865. /**
  1866. * no db name given, so we want all privs for the given user
  1867. * db name was given, so we want all user specific rights for this db
  1868. * So this function returns user rights as an array
  1869. *
  1870. * @param array $tables tables
  1871. * @param string $user_host_condition a where clause that containd user's host condition
  1872. * @param string $dbname database name
  1873. *
  1874. * @return array $db_rights database rights
  1875. */
  1876. function PMA_getUserSpecificRights($tables, $user_host_condition, $dbname)
  1877. {
  1878. if (! strlen($dbname)) {
  1879. $tables_to_search_for_users = array(
  1880. 'tables_priv', 'columns_priv',
  1881. );
  1882. $dbOrTableName = 'Db';
  1883. } else {
  1884. $user_host_condition .=
  1885. ' AND `Db`'
  1886. .' LIKE \''
  1887. . PMA_Util::sqlAddSlashes($dbname, true) . "'";
  1888. $tables_to_search_for_users = array('columns_priv',);
  1889. $dbOrTableName = 'Table_name';
  1890. }
  1891. $db_rights_sqls = array();
  1892. foreach ($tables_to_search_for_users as $table_search_in) {
  1893. if (in_array($table_search_in, $tables)) {
  1894. $db_rights_sqls[] = '
  1895. SELECT DISTINCT `' . $dbOrTableName .'`
  1896. FROM `mysql`.' . PMA_Util::backquote($table_search_in)
  1897. . $user_host_condition;
  1898. }
  1899. }
  1900. $user_defaults = array(
  1901. $dbOrTableName => '',
  1902. 'Grant_priv' => 'N',
  1903. 'privs' => array('USAGE'),
  1904. 'Column_priv' => true,
  1905. );
  1906. // for the rights
  1907. $db_rights = array();
  1908. $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
  1909. .' ORDER BY `' . $dbOrTableName .'` ASC';
  1910. $db_rights_result = PMA_DBI_query($db_rights_sql);
  1911. while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
  1912. $db_rights_row = array_merge($user_defaults, $db_rights_row);
  1913. if (! strlen($dbname)) {
  1914. // only Db names in the table `mysql`.`db` uses wildcards
  1915. // as we are in the db specific rights display we want
  1916. // all db names escaped, also from other sources
  1917. $db_rights_row['Db'] = PMA_Util::escapeMysqlWildcards(
  1918. $db_rights_row['Db']
  1919. );
  1920. }
  1921. $db_rights[$db_rights_row[$dbOrTableName]] = $db_rights_row;
  1922. }
  1923. PMA_DBI_free_result($db_rights_result);
  1924. if (! strlen($dbname)) {
  1925. $sql_query = 'SELECT * FROM `mysql`.`db`'
  1926. . $user_host_condition . ' ORDER BY `Db` ASC';
  1927. } else {
  1928. $sql_query = 'SELECT `Table_name`,'
  1929. .' `Table_priv`,'
  1930. .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
  1931. .' AS \'Column_priv\''
  1932. .' FROM `mysql`.`tables_priv`'
  1933. . $user_host_condition
  1934. .' ORDER BY `Table_name` ASC;';
  1935. }
  1936. $result = PMA_DBI_query($sql_query);
  1937. $sql_query = '';
  1938. while ($row = PMA_DBI_fetch_assoc($result)) {
  1939. if (isset($db_rights[$row[$dbOrTableName]])) {
  1940. $db_rights[$row[$dbOrTableName]]
  1941. = array_merge($db_rights[$row[$dbOrTableName]], $row);
  1942. } else {
  1943. $db_rights[$row[$dbOrTableName]] = $row;
  1944. }
  1945. if (! strlen($dbname)) {
  1946. // there are db specific rights for this user
  1947. // so we can drop this db rights
  1948. $db_rights[$row['Db']]['can_delete'] = true;
  1949. }
  1950. }
  1951. PMA_DBI_free_result($result);
  1952. return $db_rights;
  1953. }
  1954. /**
  1955. * Display user rights in table rows(Table specific or database specific privs)
  1956. *
  1957. * @param array $db_rights user's database rights array
  1958. * @param string $link_edit standard link to edit privileges
  1959. * @param string $dbname database name
  1960. * @param string $link_revoke standard link to revoke
  1961. * @param string $hostname host name
  1962. * @param string $username username
  1963. *
  1964. * @return array $found_rows, $html_output
  1965. */
  1966. function PMA_getHtmlForDisplayUserRightsInRows($db_rights, $link_edit, $dbname,
  1967. $link_revoke, $hostname, $username
  1968. ) {
  1969. $html_output = '';
  1970. $found_rows = array();
  1971. // display rows
  1972. if (count($db_rights) < 1) {
  1973. $html_output .= '<tr class="odd">' . "\n"
  1974. . '<td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
  1975. . '</tr>' . "\n";
  1976. } else {
  1977. $odd_row = true;
  1978. //while ($row = PMA_DBI_fetch_assoc($res)) {
  1979. foreach ($db_rights as $row) {
  1980. $found_rows[] = (! strlen($dbname)) ? $row['Db'] : $row['Table_name'];
  1981. $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
  1982. . '<td>'
  1983. . htmlspecialchars(
  1984. (! strlen($dbname)) ? $row['Db'] : $row['Table_name']
  1985. )
  1986. . '</td>' . "\n"
  1987. . '<td><code>' . "\n"
  1988. . ' '
  1989. . join(
  1990. ',' . "\n" . ' ',
  1991. PMA_extractPrivInfo($row, true)
  1992. ) . "\n"
  1993. . '</code></td>' . "\n"
  1994. . '<td>'
  1995. . ((((! strlen($dbname)) && $row['Grant_priv'] == 'Y')
  1996. || (strlen($dbname) && in_array('Grant', explode(',', $row['Table_priv']))))
  1997. ? __('Yes')
  1998. : __('No'))
  1999. . '</td>' . "\n"
  2000. . '<td>';
  2001. if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
  2002. $html_output .= __('Yes');
  2003. } else {
  2004. $html_output .= __('No');
  2005. }
  2006. $html_output .= '</td>' . "\n"
  2007. . '<td>';
  2008. $html_output .= sprintf(
  2009. $link_edit,
  2010. htmlspecialchars(urlencode($username)),
  2011. urlencode(htmlspecialchars($hostname)),
  2012. urlencode(
  2013. (! strlen($dbname)) ? $row['Db'] : htmlspecialchars($dbname)
  2014. ),
  2015. urlencode((! strlen($dbname)) ? '' : $row['Table_name'])
  2016. );
  2017. $html_output .= '</td>' . "\n"
  2018. . ' <td>';
  2019. if (! empty($row['can_delete'])
  2020. || isset($row['Table_name'])
  2021. && strlen($row['Table_name'])
  2022. ) {
  2023. $html_output .= sprintf(
  2024. $link_revoke,
  2025. htmlspecialchars(urlencode($username)),
  2026. urlencode(htmlspecialchars($hostname)),
  2027. urlencode(
  2028. (! strlen($dbname)) ? $row['Db'] : htmlspecialchars($dbname)
  2029. ),
  2030. urlencode((! strlen($dbname)) ? '' : $row['Table_name'])
  2031. );
  2032. }
  2033. $html_output .= '</td>' . "\n"
  2034. . '</tr>' . "\n";
  2035. $odd_row = ! $odd_row;
  2036. } // end while
  2037. } //end if
  2038. return array($found_rows, $html_output);
  2039. }
  2040. /**
  2041. * Get a HTML table for display user's tabel specific or database specific rights
  2042. *
  2043. * @param string $username username
  2044. * @param string $hostname host name
  2045. * @param string $link_edit standard link to edit privileges
  2046. * @param string $link_revoke standard link to revoke
  2047. * @param string $dbname database name
  2048. *
  2049. * @return array $html_output, $found_rows
  2050. */
  2051. function PMA_getTableForDisplayAllTableSpecificRights($username, $hostname
  2052. , $link_edit, $link_revoke, $dbname
  2053. ) {
  2054. // table header
  2055. $html_output = PMA_generate_common_hidden_inputs('', '')
  2056. . '<input type="hidden" name="username" '
  2057. . 'value="' . htmlspecialchars($username) . '" />' . "\n"
  2058. . '<input type="hidden" name="hostname" '
  2059. . 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
  2060. . '<fieldset>' . "\n"
  2061. . '<legend>'
  2062. . (! strlen($dbname)
  2063. ? __('Database-specific privileges')
  2064. : __('Table-specific privileges')
  2065. )
  2066. . '</legend>' . "\n"
  2067. . '<table class="data">' . "\n"
  2068. . '<thead>' . "\n"
  2069. . '<tr><th>'
  2070. . (! strlen($dbname) ? __('Database') : __('Table'))
  2071. . '</th>' . "\n"
  2072. . '<th>' . __('Privileges') . '</th>' . "\n"
  2073. . '<th>' . __('Grant') . '</th>' . "\n"
  2074. . '<th>'
  2075. . (! strlen($dbname)
  2076. ? __('Table-specific privileges')
  2077. : __('Column-specific privileges')
  2078. )
  2079. . '</th>' . "\n"
  2080. . '<th colspan="2">' . __('Action') . '</th>' . "\n"
  2081. . '</tr>' . "\n"
  2082. . '</thead>' . "\n";
  2083. $user_host_condition = ' WHERE `User`'
  2084. . ' = \'' . PMA_Util::sqlAddSlashes($username) . "'"
  2085. . ' AND `Host`'
  2086. . ' = \'' . PMA_Util::sqlAddSlashes($hostname) . "'";
  2087. // table body
  2088. // get data
  2089. // we also want privielgs for this user not in table `db` but in other table
  2090. $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
  2091. /**
  2092. * no db name given, so we want all privs for the given user
  2093. * db name was given, so we want all user specific rights for this db
  2094. */
  2095. $db_rights = PMA_getUserSpecificRights($tables, $user_host_condition, $dbname);
  2096. ksort($db_rights);
  2097. $html_output .= '<tbody>' . "\n";
  2098. // display rows
  2099. list ($found_rows, $html_out) = PMA_getHtmlForDisplayUserRightsInRows(
  2100. $db_rights, $link_edit, $dbname, $link_revoke, $hostname, $username
  2101. );
  2102. $html_output .= $html_out;
  2103. $html_output .= '</tbody>' . "\n";
  2104. $html_output .='</table>' . "\n";
  2105. return array($html_output, $found_rows);
  2106. }
  2107. /**
  2108. * Get HTML for display select db
  2109. *
  2110. * @param array $found_rows isset($dbname)) ? $row['Db'] : $row['Table_name']
  2111. *
  2112. * @return string HTML snippet
  2113. */
  2114. function PMA_getHtmlForDisplaySelectDbInEditPrivs($found_rows)
  2115. {
  2116. $pred_db_array = PMA_DBI_fetch_result('SHOW DATABASES;');
  2117. $html_output = '<label for="text_dbname">'
  2118. . __('Add privileges on the following database') . ':</label>' . "\n";
  2119. if (! empty($pred_db_array)) {
  2120. $html_output .= '<select name="pred_dbname" class="autosubmit">' . "\n"
  2121. . '<option value="" selected="selected">'
  2122. . __('Use text field') . ':</option>' . "\n";
  2123. foreach ($pred_db_array as $current_db) {
  2124. $current_db_show = $current_db;
  2125. $current_db = PMA_Util::escapeMysqlWildcards($current_db);
  2126. // cannot use array_diff() once, outside of the loop,
  2127. // because the list of databases has special characters
  2128. // already escaped in $found_rows,
  2129. // contrary to the output of SHOW DATABASES
  2130. if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
  2131. $html_output .= '<option value="' . htmlspecialchars($current_db) . '">'
  2132. . htmlspecialchars($current_db_show) . '</option>' . "\n";
  2133. }
  2134. }
  2135. $html_output .= '</select>' . "\n";
  2136. }
  2137. $html_output .= '<input type="text" id="text_dbname" name="dbname" />' . "\n"
  2138. . PMA_Util::showHint(
  2139. __('Wildcards % and _ should be escaped with a \ to use them literally')
  2140. );
  2141. return $html_output;
  2142. }
  2143. /**
  2144. * Get HTML for display table in edit privilege
  2145. *
  2146. * @param string $dbname database naame
  2147. * @param array $found_rows isset($dbname)) ? $row['Db'] : $row['Table_name']
  2148. *
  2149. * @return string HTML snippet
  2150. */
  2151. function PMA_displayTablesInEditPrivs($dbname, $found_rows)
  2152. {
  2153. $html_output = '<input type="hidden" name="dbname"
  2154. '. 'value="' . htmlspecialchars($dbname) . '"/>' . "\n";
  2155. $html_output .= '<label for="text_tablename">'
  2156. . __('Add privileges on the following table') . ':</label>' . "\n";
  2157. $result = @PMA_DBI_try_query(
  2158. 'SHOW TABLES FROM ' . PMA_Util::backquote(
  2159. PMA_Util::unescapeMysqlWildcards($dbname)
  2160. ) . ';',
  2161. null,
  2162. PMA_DBI_QUERY_STORE
  2163. );
  2164. if ($result) {
  2165. $pred_tbl_array = array();
  2166. while ($row = PMA_DBI_fetch_row($result)) {
  2167. if (! isset($found_rows) || ! in_array($row[0], $found_rows)) {
  2168. $pred_tbl_array[] = $row[0];
  2169. }
  2170. }
  2171. PMA_DBI_free_result($result);
  2172. if (! empty($pred_tbl_array)) {
  2173. $html_output .= '<select name="pred_tablename" '
  2174. . 'class="autosubmit">' . "\n"
  2175. . '<option value="" selected="selected">' . __('Use text field')
  2176. . ':</option>' . "\n";
  2177. foreach ($pred_tbl_array as $current_table) {
  2178. $html_output .= '<option '
  2179. . 'value="' . htmlspecialchars($current_table) . '">'
  2180. . htmlspecialchars($current_table)
  2181. . '</option>' . "\n";
  2182. }
  2183. $html_output .= '</select>' . "\n";
  2184. }
  2185. }
  2186. $html_output .= '<input type="text" id="text_tablename" name="tablename" />'
  2187. . "\n";
  2188. return $html_output;
  2189. }
  2190. /**
  2191. * Get HTML for display the users overview
  2192. * (if less than 50 users, display them immediately)
  2193. *
  2194. * @param array $result ran sql query
  2195. * @param array $db_rights user's database rights array
  2196. * @param string $link_edit standard link to edit privileges
  2197. * @param string $pmaThemeImage a image source link
  2198. * @param string $text_dir text directory
  2199. * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
  2200. * @param string $link_export standard link to export privileges
  2201. *
  2202. * @return string HTML snippet
  2203. */
  2204. function PMA_getUsersOverview($result, $db_rights, $link_edit, $pmaThemeImage,
  2205. $text_dir, $conditional_class, $link_export
  2206. ) {
  2207. while ($row = PMA_DBI_fetch_assoc($result)) {
  2208. $row['privs'] = PMA_extractPrivInfo($row, true);
  2209. $db_rights[$row['User']][$row['Host']] = $row;
  2210. }
  2211. @PMA_DBI_free_result($result);
  2212. $html_output
  2213. = '<form name="usersForm" id="usersForm" action="server_privileges.php" '
  2214. . 'method="post">' . "\n"
  2215. . PMA_generate_common_hidden_inputs('', '')
  2216. . '<table id="tableuserrights" class="data">' . "\n"
  2217. . '<thead>' . "\n"
  2218. . '<tr><th></th>' . "\n"
  2219. . '<th>' . __('User') . '</th>' . "\n"
  2220. . '<th>' . __('Host') . '</th>' . "\n"
  2221. . '<th>' . __('Password') . '</th>' . "\n"
  2222. . '<th>' . __('Global privileges') . ' '
  2223. . PMA_Util::showHint(
  2224. __('Note: MySQL privilege names are expressed in English')
  2225. )
  2226. . '</th>' . "\n"
  2227. . '<th>' . __('Grant') . '</th>' . "\n"
  2228. . '<th colspan="2">' . __('Action') . '</th>' . "\n"
  2229. . '</tr>' . "\n"
  2230. . '</thead>' . "\n";
  2231. $html_output .= '<tbody>' . "\n";
  2232. $html_output .= PMA_getTableBodyForUserRightsTable(
  2233. $db_rights, $link_edit, $link_export
  2234. );
  2235. $html_output .= '</tbody>'
  2236. . '</table>' . "\n";
  2237. $html_output .= '<div style="float:left;">'
  2238. .'<img class="selectallarrow"'
  2239. .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
  2240. .' width="38" height="22"'
  2241. .' alt="' . __('With selected:') . '" />' . "\n"
  2242. .'<input type="checkbox" id="checkall" title="' . __('Check All') . '" /> '
  2243. .'<label for="checkall">' . __('Check All') . '</label> '
  2244. .'<i style="margin-left: 2em">' . __('With selected:') . '</i>' . "\n";
  2245. $html_output .= PMA_Util::getButtonOrImage(
  2246. 'submit_mult', 'mult_submit', 'submit_mult_export',
  2247. __('Export'), 'b_tblexport.png', 'export'
  2248. );
  2249. $html_output .= '<input type="hidden" name="initial" '
  2250. . 'value="' . (isset($_GET['initial']) ? htmlspecialchars($_GET['initial']) : '') . '" />';
  2251. $html_output .= '</div>'
  2252. . '<div class="clear_both" style="clear:both"></div>';
  2253. // add/delete user fieldset
  2254. $html_output .= PMA_getFieldsetForAddDeleteUser($conditional_class);
  2255. $html_output .= '</form>' . "\n";
  2256. return $html_output;
  2257. }
  2258. /**
  2259. * Get table body for 'tableuserrights' table in userform
  2260. *
  2261. * @param array $db_rights user's database rights array
  2262. * @param string $link_edit standard link to edit privileges
  2263. * @param string $link_export Link for export all users
  2264. *
  2265. * @return string HTML snippet
  2266. */
  2267. function PMA_getTableBodyForUserRightsTable($db_rights, $link_edit, $link_export)
  2268. {
  2269. $odd_row = true;
  2270. $index_checkbox = -1;
  2271. $html_output = '';
  2272. foreach ($db_rights as $user) {
  2273. $index_checkbox++;
  2274. ksort($user);
  2275. foreach ($user as $host) {
  2276. $index_checkbox++;
  2277. $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">'
  2278. . "\n";
  2279. $html_output .= '<td>'
  2280. . '<input type="checkbox" class="checkall" name="selected_usr[]" '
  2281. . 'id="checkbox_sel_users_'
  2282. . $index_checkbox . '" value="'
  2283. . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
  2284. . '"'
  2285. . ' /></td>' . "\n";
  2286. $html_output .= '<td><label '
  2287. . 'for="checkbox_sel_users_' . $index_checkbox . '">'
  2288. . (empty($host['User'])
  2289. ? '<span style="color: #FF0000">' . __('Any') . '</span>'
  2290. : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
  2291. . '<td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
  2292. $html_output .= '<td>';
  2293. switch ($host['Password']) {
  2294. case 'Y':
  2295. $html_output .= __('Yes');
  2296. break;
  2297. case 'N':
  2298. $html_output .= '<span style="color: #FF0000">' . __('No')
  2299. . '</span>';
  2300. break;
  2301. // this happens if this is a definition not coming from mysql.user
  2302. default:
  2303. $html_output .= '--'; // in future version, replace by "not present"
  2304. break;
  2305. } // end switch
  2306. $html_output .= '</td>' . "\n";
  2307. $html_output .= '<td><code>' . "\n"
  2308. . '' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
  2309. . '</code></td>' . "\n"
  2310. . '<td>'
  2311. . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No'))
  2312. . '</td>' . "\n"
  2313. . '<td class="center">'
  2314. . sprintf(
  2315. $link_edit,
  2316. urlencode($host['User']),
  2317. urlencode($host['Host']),
  2318. '',
  2319. ''
  2320. );
  2321. $html_output .= '</td>';
  2322. $html_output .= '<td class="center">';
  2323. $html_output .= sprintf(
  2324. $link_export,
  2325. urlencode($host['User']),
  2326. urlencode($host['Host']),
  2327. (isset($_GET['initial']) ? $_GET['initial'] : '')
  2328. );
  2329. $html_output .= '</td>';
  2330. $html_output .= '</tr>';
  2331. $odd_row = ! $odd_row;
  2332. }
  2333. }
  2334. return $html_output;
  2335. }
  2336. /**
  2337. * Get HTML fieldset for Add/Delete user
  2338. *
  2339. * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
  2340. *
  2341. * @return string HTML snippet
  2342. */
  2343. function PMA_getFieldsetForAddDeleteUser($conditional_class)
  2344. {
  2345. $html_output = '<fieldset id="fieldset_add_user">' . "\n";
  2346. $html_output .= '<a href="server_privileges.php?'
  2347. . $GLOBALS['url_query'] . '&amp;adduser=1"'
  2348. . 'class="' . $conditional_class . '">' . "\n"
  2349. . PMA_Util::getIcon('b_usradd.png')
  2350. . ' ' . __('Add user') . '</a>' . "\n";
  2351. $html_output .= '</fieldset>' . "\n";
  2352. $html_output .= '<fieldset id="fieldset_delete_user">'
  2353. . '<legend>' . "\n"
  2354. . PMA_Util::getIcon('b_usrdrop.png')
  2355. . ' ' . __('Remove selected users') . '' . "\n"
  2356. . '</legend>' . "\n";
  2357. $html_output .= '<input type="hidden" name="mode" value="2" />' . "\n"
  2358. . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')'
  2359. . '<br />' . "\n";
  2360. $html_output .= '<input type="checkbox" '
  2361. . 'title="' . __('Drop the databases that have the same names as the users.') . '" '
  2362. . 'name="drop_users_db" id="checkbox_drop_users_db" />' . "\n";
  2363. $html_output .= '<label for="checkbox_drop_users_db" '
  2364. . 'title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
  2365. . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
  2366. . '</label>' . "\n"
  2367. . '</fieldset>' . "\n";
  2368. $html_output .= '<fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n";
  2369. $html_output .= '<input type="submit" name="delete" '
  2370. . 'value="' . __('Go') . '" id="buttonGo" '
  2371. . 'class="' . $conditional_class . '"/>' . "\n";
  2372. $html_output .= '</fieldset>' . "\n";
  2373. return $html_output;
  2374. }
  2375. /**
  2376. * Get HTML for Displays the initials
  2377. *
  2378. * @param array $array_initials array for all initials, even non A-Z
  2379. * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
  2380. *
  2381. * @return string HTML snippet
  2382. */
  2383. function PMA_getHtmlForDisplayTheInitials($array_initials, $conditional_class)
  2384. {
  2385. // initialize to false the letters A-Z
  2386. for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
  2387. if (! isset($array_initials[chr($letter_counter + 64)])) {
  2388. $array_initials[chr($letter_counter + 64)] = false;
  2389. }
  2390. }
  2391. $initials = PMA_DBI_try_query(
  2392. 'SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC',
  2393. null,
  2394. PMA_DBI_QUERY_STORE
  2395. );
  2396. while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
  2397. $array_initials[$tmp_initial] = true;
  2398. }
  2399. // Display the initials, which can be any characters, not
  2400. // just letters. For letters A-Z, we add the non-used letters
  2401. // as greyed out.
  2402. uksort($array_initials, "strnatcasecmp");
  2403. $html_output = '<table id="initials_table" <cellspacing="5">'
  2404. . '<tr>';
  2405. foreach ($array_initials as $tmp_initial => $initial_was_found) {
  2406. if (! empty($tmp_initial)) {
  2407. if ($initial_was_found) {
  2408. $html_output .= '<td>'
  2409. . '<a class="' . $conditional_class . '"'
  2410. . ' href="server_privileges.php?'
  2411. . $GLOBALS['url_query'] . '&amp;'
  2412. . 'initial=' . urlencode($tmp_initial) . '">' . $tmp_initial
  2413. . '</a>'
  2414. . '</td>' . "\n";
  2415. } else {
  2416. $html_output .= '<td>' . $tmp_initial . '</td>';
  2417. }
  2418. }
  2419. }
  2420. $html_output .= '<td>'
  2421. . '<a href="server_privileges.php?' . $GLOBALS['url_query']
  2422. . '&amp;showall=1" '
  2423. . 'class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
  2424. $html_output .= '</tr></table>';
  2425. return $html_output;
  2426. }
  2427. /**
  2428. * Get the database rigths array for Display user overview
  2429. *
  2430. * @return array $db_rights database rights array
  2431. */
  2432. function PMA_getDbRightsForUserOverview()
  2433. {
  2434. // we also want users not in table `user` but in other table
  2435. $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
  2436. $tables_to_search_for_users = array(
  2437. 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
  2438. );
  2439. $db_rights_sqls = array();
  2440. foreach ($tables_to_search_for_users as $table_search_in) {
  2441. if (in_array($table_search_in, $tables)) {
  2442. $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`'
  2443. . $table_search_in . '` '
  2444. . (isset($_GET['initial']) ? PMA_rangeOfUsers($_GET['initial']) : '');
  2445. }
  2446. }
  2447. $user_defaults = array(
  2448. 'User' => '',
  2449. 'Host' => '%',
  2450. 'Password' => '?',
  2451. 'Grant_priv' => 'N',
  2452. 'privs' => array('USAGE'),
  2453. );
  2454. // for the rights
  2455. $db_rights = array();
  2456. $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
  2457. .' ORDER BY `User` ASC, `Host` ASC';
  2458. $db_rights_result = PMA_DBI_query($db_rights_sql);
  2459. while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
  2460. $db_rights_row = array_merge($user_defaults, $db_rights_row);
  2461. $db_rights[$db_rights_row['User']][$db_rights_row['Host']]
  2462. = $db_rights_row;
  2463. }
  2464. PMA_DBI_free_result($db_rights_result);
  2465. ksort($db_rights);
  2466. return $db_rights;
  2467. }
  2468. /**
  2469. * Delete user and get message and sql query for delete user in privileges
  2470. *
  2471. * @param string $queries queries
  2472. *
  2473. * @return PMA_message
  2474. */
  2475. function PMA_deleteUser($queries)
  2476. {
  2477. if (empty($queries)) {
  2478. $message = PMA_Message::error(__('No users selected for deleting!'));
  2479. } else {
  2480. if ($_REQUEST['mode'] == 3) {
  2481. $queries[] = '# ' . __('Reloading the privileges') . ' …';
  2482. $queries[] = 'FLUSH PRIVILEGES;';
  2483. }
  2484. $drop_user_error = '';
  2485. foreach ($queries as $sql_query) {
  2486. if ($sql_query{0} != '#') {
  2487. if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
  2488. $drop_user_error .= PMA_DBI_getError() . "\n";
  2489. }
  2490. }
  2491. }
  2492. // tracking sets this, causing the deleted db to be shown in navi
  2493. unset($GLOBALS['db']);
  2494. $sql_query = join("\n", $queries);
  2495. if (! empty($drop_user_error)) {
  2496. $message = PMA_Message::rawError($drop_user_error);
  2497. } else {
  2498. $message = PMA_Message::success(
  2499. __('The selected users have been deleted successfully.')
  2500. );
  2501. }
  2502. }
  2503. return array($sql_query, $message);
  2504. }
  2505. /**
  2506. * Update the privileges and return the success or error message
  2507. *
  2508. * @param string $username username
  2509. * @param string $hostname host name
  2510. * @param string $tablename table name
  2511. * @param string $dbname database name
  2512. *
  2513. * @return PMA_message success message or error message for update
  2514. */
  2515. function PMA_updatePrivileges($username, $hostname, $tablename, $dbname)
  2516. {
  2517. $db_and_table = PMA_wildcardEscapeForGrant($dbname, $tablename);
  2518. $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
  2519. . ' FROM \'' . PMA_Util::sqlAddSlashes($username)
  2520. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
  2521. if (! isset($_POST['Grant_priv']) || $_POST['Grant_priv'] != 'Y') {
  2522. $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
  2523. . ' FROM \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
  2524. . PMA_Util::sqlAddSlashes($hostname) . '\';';
  2525. } else {
  2526. $sql_query1 = '';
  2527. }
  2528. // Should not do a GRANT USAGE for a table-specific privilege, it
  2529. // causes problems later (cannot revoke it)
  2530. if (! (strlen($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
  2531. $sql_query2 = 'GRANT ' . join(', ', PMA_extractPrivInfo())
  2532. . ' ON ' . $db_and_table
  2533. . ' TO \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
  2534. . PMA_Util::sqlAddSlashes($hostname) . '\'';
  2535. if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')
  2536. || (! strlen($dbname)
  2537. && (isset($_POST['max_questions']) || isset($_POST['max_connections'])
  2538. || isset($_POST['max_updates']) || isset($_POST['max_user_connections'])))
  2539. ) {
  2540. $sql_query2 .= PMA_getWithClauseForAddUserAndUpdatePrivs();
  2541. }
  2542. $sql_query2 .= ';';
  2543. }
  2544. if (! PMA_DBI_try_query($sql_query0)) {
  2545. // This might fail when the executing user does not have
  2546. // ALL PRIVILEGES himself.
  2547. // See https://sourceforge.net/p/phpmyadmin/bugs/3270/
  2548. $sql_query0 = '';
  2549. }
  2550. if (isset($sql_query1) && ! PMA_DBI_try_query($sql_query1)) {
  2551. // this one may fail, too...
  2552. $sql_query1 = '';
  2553. }
  2554. if (isset($sql_query2)) {
  2555. PMA_DBI_query($sql_query2);
  2556. } else {
  2557. $sql_query2 = '';
  2558. }
  2559. $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
  2560. $message = PMA_Message::success(__('You have updated the privileges for %s.'));
  2561. $message->addParam(
  2562. '\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\''
  2563. );
  2564. return array($sql_query, $message);
  2565. }
  2566. /**
  2567. * Get title and textarea for export user definition in Privileges
  2568. *
  2569. * @param string $username username
  2570. * @param string $hostname host name
  2571. *
  2572. * @return array ($title, $export)
  2573. */
  2574. function PMA_getHtmlForExportUserDefinition($username, $hostname)
  2575. {
  2576. $export = '<textarea class="export" cols="' . $GLOBALS['cfg']['TextareaCols']
  2577. . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
  2578. if (isset($_REQUEST['selected_usr'])) {
  2579. // export privileges for selected users
  2580. $title = __('Privileges');
  2581. foreach ($_REQUEST['selected_usr'] as $export_user) {
  2582. $export_username = substr($export_user, 0, strpos($export_user, '&'));
  2583. $export_hostname = substr($export_user, strrpos($export_user, ';') + 1);
  2584. $export .= '# '
  2585. . sprintf(
  2586. __('Privileges for %s'),
  2587. '`' . htmlspecialchars($export_username)
  2588. . '`@`' . htmlspecialchars($export_hostname) . '`'
  2589. )
  2590. . "\n\n";
  2591. $export .= PMA_getGrants($export_username, $export_hostname) . "\n";
  2592. }
  2593. } else {
  2594. // export privileges for a single user
  2595. $title = __('User') . ' `' . htmlspecialchars($username)
  2596. . '`@`' . htmlspecialchars($hostname) . '`';
  2597. $export .= PMA_getGrants($username, $hostname);
  2598. }
  2599. // remove trailing whitespace
  2600. $export = trim($export);
  2601. $export .= '</textarea>';
  2602. return array($title, $export);
  2603. }
  2604. /**
  2605. * Get HTML for display Add userfieldset
  2606. *
  2607. * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
  2608. *
  2609. * @return string html output
  2610. */
  2611. function PMA_getAddUserHtmlFieldset($conditional_class)
  2612. {
  2613. return '<fieldset id="fieldset_add_user">' . "\n"
  2614. . '<a href="server_privileges.php?' . $GLOBALS['url_query']
  2615. . '&amp;adduser=1" '
  2616. . 'class="' . $conditional_class . '">' . "\n"
  2617. . PMA_Util::getIcon('b_usradd.png')
  2618. . ' ' . __('Add user') . '</a>' . "\n"
  2619. . '</fieldset>' . "\n";
  2620. }
  2621. /**
  2622. * Get HTML header for display User's properties
  2623. *
  2624. * @param boolean $dbname_is_wildcard whether database name is wildcard or not
  2625. * @param string $url_dbname url database name that urlencode() string
  2626. * @param string $dbname database name
  2627. * @param string $username username
  2628. * @param string $hostname host name
  2629. * @param string $tablename table name
  2630. *
  2631. * @return string $html_output
  2632. */
  2633. function PMA_getHtmlHeaderForDisplayUserProperties(
  2634. $dbname_is_wildcard, $url_dbname, $dbname, $username, $hostname, $tablename
  2635. ) {
  2636. $html_output = '<h2>' . "\n"
  2637. . PMA_Util::getIcon('b_usredit.png')
  2638. . __('Edit Privileges') . ': '
  2639. . __('User');
  2640. if (isset($dbname)) {
  2641. $html_output .= ' <i><a href="server_privileges.php?'
  2642. . $GLOBALS['url_query']
  2643. . '&amp;username=' . htmlspecialchars(urlencode($username))
  2644. . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
  2645. . '&amp;dbname=&amp;tablename=">\'' . htmlspecialchars($username)
  2646. . '\'@\'' . htmlspecialchars($hostname)
  2647. . '\'</a></i>' . "\n";
  2648. $html_output .= ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
  2649. if (isset($_REQUEST['tablename'])) {
  2650. $html_output .= ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
  2651. . '&amp;username=' . htmlspecialchars(urlencode($username))
  2652. . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
  2653. . '&amp;dbname=' . htmlspecialchars($url_dbname)
  2654. . '&amp;tablename=">' . htmlspecialchars($dbname)
  2655. . '</a></i>';
  2656. $html_output .= ' - ' . __('Table')
  2657. . ' <i>' . htmlspecialchars($tablename) . '</i>';
  2658. } else {
  2659. $html_output .= ' <i>' . htmlspecialchars($dbname) . '</i>';
  2660. }
  2661. } else {
  2662. $html_output .= ' <i>\'' . htmlspecialchars($username)
  2663. . '\'@\'' . htmlspecialchars($hostname)
  2664. . '\'</i>' . "\n";
  2665. }
  2666. $html_output .= '</h2>' . "\n";
  2667. return $html_output;
  2668. }
  2669. /**
  2670. * Get HTML snippet for display user overview page
  2671. *
  2672. * @param string $link_edit standard link to edit privileges
  2673. * @param string $pmaThemeImage a image source link
  2674. * @param string $text_dir text directory
  2675. * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
  2676. * @param string $link_export standard link to export privileges
  2677. *
  2678. * @return string $html_output
  2679. */
  2680. function PMA_getHtmlForDisplayUserOverviewPage($link_edit, $pmaThemeImage,
  2681. $text_dir, $conditional_class, $link_export
  2682. ) {
  2683. $html_output = '<h2>' . "\n"
  2684. . PMA_Util::getIcon('b_usrlist.png')
  2685. . __('Users overview') . "\n"
  2686. . '</h2>' . "\n";
  2687. $sql_query = 'SELECT *,' .
  2688. " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
  2689. ' FROM `mysql`.`user`';
  2690. $sql_query .= (isset($_REQUEST['initial'])
  2691. ? PMA_rangeOfUsers($_REQUEST['initial'])
  2692. : '');
  2693. $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
  2694. $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
  2695. if (! $res) {
  2696. // the query failed! This may have two reasons:
  2697. // - the user does not have enough privileges
  2698. // - the privilege tables use a structure of an earlier version.
  2699. // so let's try a more simple query
  2700. $sql_query = 'SELECT * FROM `mysql`.`user`';
  2701. $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
  2702. if (! $res) {
  2703. $html_output .= PMA_Message::error(__('No Privileges'))->getDisplay();
  2704. PMA_DBI_free_result($res);
  2705. unset($res);
  2706. } else {
  2707. // This message is hardcoded because I will replace it by
  2708. // a automatic repair feature soon.
  2709. $raw = 'Your privilege table structure seems to be older than'
  2710. . ' this MySQL version!<br />'
  2711. . 'Please run the <code>mysql_upgrade</code> command'
  2712. . '(<code>mysql_fix_privilege_tables</code> on older systems)'
  2713. . ' that should be included in your MySQL server distribution'
  2714. . ' to solve this problem!';
  2715. $html_output .= PMA_Message::rawError($raw)->getDisplay();
  2716. }
  2717. } else {
  2718. $db_rights = PMA_getDbRightsForUserOverview();
  2719. // for all initials, even non A-Z
  2720. $array_initials = array();
  2721. /**
  2722. * Displays the initials
  2723. * Also not necassary if there is less than 20 privileges
  2724. */
  2725. if (PMA_DBI_num_rows($res) > 20 ) {
  2726. $html_output .= PMA_getHtmlForDisplayTheInitials(
  2727. $array_initials, $conditional_class
  2728. );
  2729. }
  2730. /**
  2731. * Display the user overview
  2732. * (if less than 50 users, display them immediately)
  2733. */
  2734. if (isset($_REQUEST['initial'])
  2735. || isset($_REQUEST['showall'])
  2736. || PMA_DBI_num_rows($res) < 50
  2737. ) {
  2738. $html_output .= PMA_getUsersOverview(
  2739. $res, $db_rights, $link_edit, $pmaThemeImage,
  2740. $text_dir, $conditional_class, $link_export
  2741. );
  2742. } else {
  2743. $html_output .= PMA_getAddUserHtmlFieldset($conditional_class);
  2744. } // end if (display overview)
  2745. if (! $GLOBALS['is_ajax_request'] || ! empty($_REQUEST['ajax_page_request'])) {
  2746. $flushnote = new PMA_Message(
  2747. __('Note: phpMyAdmin gets the users\' privileges directly from MySQL\'s privilege tables. The content of these tables may differ from the privileges the server uses, if they have been changed manually. In this case, you should %sreload the privileges%s before you continue.'),
  2748. PMA_Message::NOTICE
  2749. );
  2750. $flushLink = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;'
  2751. . 'flush_privileges=1" id="reload_privileges_anchor">';
  2752. $flushnote->addParam(
  2753. $flushLink,
  2754. false
  2755. );
  2756. $flushnote->addParam('</a>', false);
  2757. $html_output .= $flushnote->getDisplay();
  2758. }
  2759. return $html_output;
  2760. }
  2761. }
  2762. /**
  2763. * Get HTML snippet for display user properties
  2764. *
  2765. * @param boolean $dbname_is_wildcard whether database name is wildcard or not
  2766. * @param type $url_dbname url database name that urlencode() string
  2767. * @param string $username username
  2768. * @param string $hostname host name
  2769. * @param string $link_edit standard link to edit privileges
  2770. * @param string $link_revoke standard link to revoke
  2771. * @param string $dbname database name
  2772. * @param string $tablename table name
  2773. *
  2774. * @return string $html_output
  2775. */
  2776. function PMA_getHtmlForDisplayUserProperties($dbname_is_wildcard,$url_dbname,
  2777. $username, $hostname, $link_edit, $link_revoke, $dbname, $tablename
  2778. ) {
  2779. $html_output = PMA_getHtmlHeaderForDisplayUserProperties(
  2780. $dbname_is_wildcard, $url_dbname, $dbname, $username, $hostname, $tablename
  2781. );
  2782. $sql = "SELECT '1' FROM `mysql`.`user`"
  2783. . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
  2784. . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
  2785. $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
  2786. if ($user_does_not_exists) {
  2787. $html_output .= PMA_Message::error(
  2788. __('The selected user was not found in the privilege table.')
  2789. )->getDisplay();
  2790. $html_output .= PMA_getHtmlForDisplayLoginInformationFields();
  2791. //exit;
  2792. }
  2793. $class = ' class="ajax"';
  2794. $html_output .= '<form' . $class . ' name="usersForm" id="addUsersForm"'
  2795. . ' action="server_privileges.php" method="post">' . "\n";
  2796. $_params = array(
  2797. 'username' => $username,
  2798. 'hostname' => $hostname,
  2799. );
  2800. if (strlen($dbname)) {
  2801. $_params['dbname'] = $dbname;
  2802. if (strlen($tablename)) {
  2803. $_params['tablename'] = $tablename;
  2804. }
  2805. }
  2806. $html_output .= PMA_generate_common_hidden_inputs($_params);
  2807. $html_output .= PMA_getHtmlToDisplayPrivilegesTable(
  2808. PMA_ifSetOr($dbname, '*', 'length'),
  2809. PMA_ifSetOr($tablename, '*', 'length')
  2810. );
  2811. $html_output .= '</form>' . "\n";
  2812. if (! strlen($tablename) && empty($dbname_is_wildcard)) {
  2813. // no table name was given, display all table specific rights
  2814. // but only if $dbname contains no wildcards
  2815. $html_output .= '<form action="server_privileges.php" '
  2816. . 'id="db_or_table_specific_priv" method="post">' . "\n";
  2817. // unescape wildcards in dbname at table level
  2818. $unescaped_db = PMA_Util::unescapeMysqlWildcards($dbname);
  2819. list($html_rightsTable, $found_rows)
  2820. = PMA_getTableForDisplayAllTableSpecificRights(
  2821. $username, $hostname, $link_edit, $link_revoke, $unescaped_db
  2822. );
  2823. $html_output .= $html_rightsTable;
  2824. if (! strlen($dbname)) {
  2825. // no database name was given, display select db
  2826. $html_output .= PMA_getHtmlForDisplaySelectDbInEditPrivs($found_rows);
  2827. } else {
  2828. $html_output .= PMA_displayTablesInEditPrivs($dbname, $found_rows);
  2829. }
  2830. $html_output .= '</fieldset>' . "\n";
  2831. $html_output .= '<fieldset class="tblFooters">' . "\n"
  2832. . ' <input type="submit" value="' . __('Go') . '" />'
  2833. . '</fieldset>' . "\n"
  2834. . '</form>' . "\n";
  2835. }
  2836. // Provide a line with links to the relevant database and table
  2837. if (strlen($dbname) && empty($dbname_is_wildcard)) {
  2838. $html_output .= PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename);
  2839. }
  2840. if (! strlen($dbname) && ! $user_does_not_exists) {
  2841. //change login information
  2842. $html_output .= PMA_getHtmlForChangePassword($username, $hostname);
  2843. $html_output .= PMA_getChangeLoginInformationHtmlForm($username, $hostname);
  2844. }
  2845. return $html_output;
  2846. }
  2847. /**
  2848. * Get queries for Table privileges to change or copy user
  2849. *
  2850. * @param string $user_host_condition user host condition to select relevent table privileges
  2851. * @param array $queries queries array
  2852. * @param string $username username
  2853. * @param string $hostname host name
  2854. *
  2855. * @return array $queries
  2856. */
  2857. function PMA_getTablePrivsQueriesForChangeOrCopyUser($user_host_condition,
  2858. $queries, $username, $hostname
  2859. ) {
  2860. $res = PMA_DBI_query(
  2861. 'SELECT `Db`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv`' . $user_host_condition,
  2862. $GLOBALS['userlink'],
  2863. PMA_DBI_QUERY_STORE
  2864. );
  2865. while ($row = PMA_DBI_fetch_assoc($res)) {
  2866. $res2 = PMA_DBI_QUERY(
  2867. 'SELECT `Column_name`, `Column_priv`'
  2868. .' FROM `mysql`.`columns_priv`'
  2869. .' WHERE `User`'
  2870. .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
  2871. .' AND `Host`'
  2872. .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . '\''
  2873. .' AND `Db`'
  2874. .' = \'' . PMA_Util::sqlAddSlashes($row['Db']) . "'"
  2875. .' AND `Table_name`'
  2876. .' = \'' . PMA_Util::sqlAddSlashes($row['Table_name']) . "'"
  2877. .';',
  2878. null,
  2879. PMA_DBI_QUERY_STORE
  2880. );
  2881. $tmp_privs1 = PMA_extractPrivInfo($row);
  2882. $tmp_privs2 = array(
  2883. 'Select' => array(),
  2884. 'Insert' => array(),
  2885. 'Update' => array(),
  2886. 'References' => array()
  2887. );
  2888. while ($row2 = PMA_DBI_fetch_assoc($res2)) {
  2889. $tmp_array = explode(',', $row2['Column_priv']);
  2890. if (in_array('Select', $tmp_array)) {
  2891. $tmp_privs2['Select'][] = $row2['Column_name'];
  2892. }
  2893. if (in_array('Insert', $tmp_array)) {
  2894. $tmp_privs2['Insert'][] = $row2['Column_name'];
  2895. }
  2896. if (in_array('Update', $tmp_array)) {
  2897. $tmp_privs2['Update'][] = $row2['Column_name'];
  2898. }
  2899. if (in_array('References', $tmp_array)) {
  2900. $tmp_privs2['References'][] = $row2['Column_name'];
  2901. }
  2902. }
  2903. if (count($tmp_privs2['Select']) > 0 && ! in_array('SELECT', $tmp_privs1)) {
  2904. $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
  2905. }
  2906. if (count($tmp_privs2['Insert']) > 0 && ! in_array('INSERT', $tmp_privs1)) {
  2907. $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
  2908. }
  2909. if (count($tmp_privs2['Update']) > 0 && ! in_array('UPDATE', $tmp_privs1)) {
  2910. $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
  2911. }
  2912. if (count($tmp_privs2['References']) > 0 && ! in_array('REFERENCES', $tmp_privs1)) {
  2913. $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
  2914. }
  2915. $queries[] = 'GRANT ' . join(', ', $tmp_privs1)
  2916. . ' ON ' . PMA_Util::backquote($row['Db']) . '.'
  2917. . PMA_Util::backquote($row['Table_name'])
  2918. . ' TO \'' . PMA_Util::sqlAddSlashes($username)
  2919. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\''
  2920. . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
  2921. }
  2922. return $queries;
  2923. }
  2924. /**
  2925. * Get queries for database specific privileges for change or copy user
  2926. *
  2927. * @param array $queries queries array with string
  2928. * @param string $username username
  2929. * @param string $hostname host name
  2930. *
  2931. * @return array $queries
  2932. */
  2933. function PMA_getDbSpecificPrivsQueriesForChangeOrCopyUser(
  2934. $queries, $username, $hostname
  2935. ) {
  2936. $user_host_condition = ' WHERE `User`'
  2937. .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
  2938. .' AND `Host`'
  2939. .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_hostname']) . '\';';
  2940. $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
  2941. while ($row = PMA_DBI_fetch_assoc($res)) {
  2942. $queries[] = 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
  2943. .' ON ' . PMA_Util::backquote($row['Db']) . '.*'
  2944. .' TO \'' . PMA_Util::sqlAddSlashes($username)
  2945. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\''
  2946. . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
  2947. }
  2948. PMA_DBI_free_result($res);
  2949. $queries = PMA_getTablePrivsQueriesForChangeOrCopyUser(
  2950. $user_host_condition, $queries, $username, $hostname
  2951. );
  2952. return $queries;
  2953. }
  2954. /**
  2955. * Prepares queries for adding users and
  2956. * also create database and return query and message
  2957. *
  2958. * @param boolean $_error whether user create or not
  2959. * @param string $real_sql_query SQL query for add a user
  2960. * @param string $sql_query SQL query to be displayed
  2961. * @param string $username username
  2962. * @param string $hostname host name
  2963. * @param string $dbname database name
  2964. *
  2965. * @return array $sql_query, $message
  2966. */
  2967. function PMA_addUserAndCreateDatabase($_error, $real_sql_query, $sql_query,
  2968. $username, $hostname, $dbname
  2969. ) {
  2970. if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
  2971. $_REQUEST['createdb-1'] = $_REQUEST['createdb-2']
  2972. = $_REQUEST['createdb-3'] = false;
  2973. $message = PMA_Message::rawError(PMA_DBI_getError());
  2974. } else {
  2975. $message = PMA_Message::success(__('You have added a new user.'));
  2976. }
  2977. if (isset($_REQUEST['createdb-1'])) {
  2978. // Create database with same name and grant all privileges
  2979. $q = 'CREATE DATABASE IF NOT EXISTS '
  2980. . PMA_Util::backquote(
  2981. PMA_Util::sqlAddSlashes($username)
  2982. ) . ';';
  2983. $sql_query .= $q;
  2984. if (! PMA_DBI_try_query($q)) {
  2985. $message = PMA_Message::rawError(PMA_DBI_getError());
  2986. }
  2987. /**
  2988. * Reload the navigation
  2989. */
  2990. $GLOBALS['reload'] = true;
  2991. $GLOBALS['db'] = $username;
  2992. $q = 'GRANT ALL PRIVILEGES ON '
  2993. . PMA_Util::backquote(
  2994. PMA_Util::escapeMysqlWildcards(
  2995. PMA_Util::sqlAddSlashes($username)
  2996. )
  2997. ) . '.* TO \''
  2998. . PMA_Util::sqlAddSlashes($username)
  2999. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
  3000. $sql_query .= $q;
  3001. if (! PMA_DBI_try_query($q)) {
  3002. $message = PMA_Message::rawError(PMA_DBI_getError());
  3003. }
  3004. }
  3005. if (isset($_REQUEST['createdb-2'])) {
  3006. // Grant all privileges on wildcard name (username\_%)
  3007. $q = 'GRANT ALL PRIVILEGES ON '
  3008. . PMA_Util::backquote(
  3009. PMA_Util::sqlAddSlashes($username) . '\_%'
  3010. ) . '.* TO \''
  3011. . PMA_Util::sqlAddSlashes($username)
  3012. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
  3013. $sql_query .= $q;
  3014. if (! PMA_DBI_try_query($q)) {
  3015. $message = PMA_Message::rawError(PMA_DBI_getError());
  3016. }
  3017. }
  3018. if (isset($_REQUEST['createdb-3'])) {
  3019. // Grant all privileges on the specified database to the new user
  3020. $q = 'GRANT ALL PRIVILEGES ON '
  3021. . PMA_Util::backquote(
  3022. PMA_Util::sqlAddSlashes($dbname)
  3023. ) . '.* TO \''
  3024. . PMA_Util::sqlAddSlashes($username)
  3025. . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
  3026. $sql_query .= $q;
  3027. if (! PMA_DBI_try_query($q)) {
  3028. $message = PMA_Message::rawError(PMA_DBI_getError());
  3029. }
  3030. }
  3031. return array($sql_query, $message);
  3032. }
  3033. /**
  3034. * Get SQL queries for Display and Add user
  3035. *
  3036. * @param string $username usernam
  3037. * @param string $hostname host name
  3038. * @param string $password password
  3039. *
  3040. * @return array ($create_user_real, $create_user_show,$real_sql_query, $sql_query)
  3041. */
  3042. function PMA_getSqlQueriesForDisplayAndAddUser($username, $hostname, $password)
  3043. {
  3044. $sql_query = '';
  3045. $create_user_real = 'CREATE USER \''
  3046. . PMA_Util::sqlAddSlashes($username) . '\'@\''
  3047. . PMA_Util::sqlAddSlashes($hostname) . '\'';
  3048. $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
  3049. . PMA_Util::sqlAddSlashes($username) . '\'@\''
  3050. . PMA_Util::sqlAddSlashes($hostname) . '\'';
  3051. if ($_POST['pred_password'] != 'none' && $_POST['pred_password'] != 'keep') {
  3052. $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
  3053. $real_sql_query .= ' IDENTIFIED BY \''
  3054. . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
  3055. if (isset($create_user_real)) {
  3056. $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
  3057. $create_user_real .= ' IDENTIFIED BY \''
  3058. . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
  3059. }
  3060. } else {
  3061. if ($_POST['pred_password'] == 'keep' && ! empty($password)) {
  3062. $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
  3063. if (isset($create_user_real)) {
  3064. $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
  3065. }
  3066. }
  3067. $sql_query = $real_sql_query;
  3068. if (isset($create_user_real)) {
  3069. $create_user_show = $create_user_real;
  3070. }
  3071. }
  3072. if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')
  3073. || (isset($_POST['max_questions']) || isset($_POST['max_connections'])
  3074. || isset($_POST['max_updates']) || isset($_POST['max_user_connections']))
  3075. ) {
  3076. $with_clause = PMA_getWithClauseForAddUserAndUpdatePrivs();
  3077. $real_sql_query .= ' ' . $with_clause;
  3078. $sql_query .= ' ' . $with_clause;
  3079. }
  3080. if (isset($create_user_real)) {
  3081. $create_user_real .= ';';
  3082. $create_user_show .= ';';
  3083. }
  3084. $real_sql_query .= ';';
  3085. $sql_query .= ';';
  3086. return array($create_user_real,
  3087. $create_user_show,
  3088. $real_sql_query,
  3089. $sql_query
  3090. );
  3091. }
  3092. ?>