The following error has been popping up recently:
Error: {"message":"strtolower(): Argument <a href='/1'>#1</a> ($string) must be of type string, array given","file":"\/var\/www\/html\/core\/Date.php","line":1083,"request_id":"7a78b","backtrace":" on \/var\/www\/html\/core\/Date.php(1083)\n<a href='/0'>#0</a> \/var\/www\/html\/core\/Date.php(1083): strtolower(Array)\n<a href='/1'>#1</a> \/var\/www\/html\/core\/Period\/Range.php(255): Piwik\\Date->addPeriod(-29, Array)\n<a href='/2'>#2</a> \/var\/www\/html\/core\/Period.php(131): Piwik\\Period\\Range->generate()\n<a href='/3'>#3</a> \/var\/www\/html\/core\/Period\/Range.php(152): Piwik\\Period->getDateStart()\n<a href='/4'>#4</a> \/var\/www\/html\/core\/Period\/Range.php(543): Piwik\\Period\\Range->getDateStart()\n<a href='/5'>#5</a> \/var\/www\/html\/plugins\/ImageGraph\/ImageGraph.php(91): Piwik\\Period\\Range::getRelativeToEndDate(Array, 'last30', Object(Piwik\\Date), Object(Piwik\\Site))\n<a href='/6'>#6</a> [internal function]: Piwik\\Plugins\\ImageGraph\\ImageGraph->getReportMetadata(Array, Array)\n<a href='/7'>#7</a> \/var\/www\/html\/core\/EventDispatcher.php(141): call_user_func_array(Array, Array)\n<a href='/8'>#8</a> \/var\/www\/html\/core\/Piwik.php(845): Piwik\\EventDispatcher->postEvent('API.getReportMe...', Array, false, Array)\n<a href='/9'>#9</a> \/var\/www\/html\/plugins\/API\/ProcessedReport.php(220): Piwik\\Piwik::postEvent('API.getReportMe...', Array)\n<a href='/10'>#10</a> \/var\/www\/html\/plugins\/API\/API.php(272): Piwik\\Plugins\\API\\ProcessedReport->getReportMetadata('1', Array, 'yesterday', false, false)\n<a href='/11'>#11</a> [internal function]: Piwik\\Plugins\\API\\API->getReportMetadata('1,2', Array, 'yesterday', false, false, '1')\n<a href='/12'>#12</a> \/var\/www\/html\/core\/API\/Proxy.php(244): call_user_func_array(Array, Array)\n<a href='/13'>#13</a> \/var\/www\/html\/core\/Context.php(28): Piwik\\API\\Proxy->Piwik\\API\\{closure}()\n<a href='/14'>#14</a> \/var\/www\/html\/core\/API\/Proxy.php(335): Piwik\\Context::executeWithQueryParameters(Array, Object(Closure))\n<a href='/15'>#15</a> \/var\/www\/html\/core\/API\/Request.php(266): Piwik\\API\\Proxy->call('\\\\Piwik\\\\Plugins\\\\...', 'getReportMetada...', Array)\n<a href='/16'>#16</a> \/var\/www\/html\/plugins\/API\/Controller.php(45): Piwik\\API\\Request->process()\n<a href='/17'>#17</a> [internal function]: Piwik\\Plugins\\API\\Controller->index()\n<a href='/18'>#18</a> \/var\/www\/html\/core\/FrontController.php(631): call_user_func_array(Array, Array)\n<a href='/19'>#19</a> \/var\/www\/html\/core\/FrontController.php(169): Piwik\\FrontController->doDispatch('API', false, Array)\n<a href='/20'>#20</a> \/var\/www\/html\/core\/dispatch.php(32): Piwik\\FrontController->dispatch()\n<a href='/21'>#21</a> \/var\/www\/html\/index.php(25): require_once('\/var\/www\/html\/c...')\n<a href='/22'>#22</a> {main}","safemode_backtrace":"<a href='/0'>#0</a> [internal function]: Piwik\\Plugins\\Cloud\\Controller->safemode(Array)\n<a href='/1'>#1</a> \/core\/FrontController.php(631): call_user_func_array(Array, Array)\n<a href='/2'>#2</a> \/core\/FrontController.php(169): Piwik\\FrontController->doDispatch('Cloud', 'safemode', Array)\n<a href='/3'>#3</a> \/core\/FrontController.php(100): Piwik\\FrontController->dispatch('CorePluginsAdmi...', 'safemode', Array)\n<a href='/4'>#4</a> \/core\/FrontController.php(140): Piwik\\FrontController::(Array)\n<a href='/5'>#5</a> \/core\/FrontController.php(190): Piwik\\FrontController::(Object(TypeError))\n<a href='/6'>#6</a> \/core\/dispatch.php(32): Piwik\\FrontController->dispatch()\n<a href='/7'>#7</a> \/index.php(25): require_once('\/c...')\n<a href='/8'>#8</a> {main}"}
Referrer:
GET: {"date":"yesterday","format":"JSON","idSite":"1","idSites":"1,2","method":"API.getReportMetadata","module":"API","period":{"$acunetix":"1"},"token_auth":"XYZANONYMIZED","filter_limit":100}
This is another issue of "improper" handling of request parameters. In this case period
is provided as an array, which we expect to be a string.
Personally I would not suggest to fix all such incorrect handling were they occur, as it consumes a lot of time and actually doesn't improve much. The result for the customer will only change from a php error to an unsupported param
exception.
We should maybe consider for Matomo 5, to introduce a proper request param handling for API methods.
Each api method could define the types of the method parameters using type hints (or maybe doc comments where multiple types are allowed 🤔). Our API request processor could then check if the provided values can be converted/mapped to the defined types. If that isn't the case a general exception like Parameter X expects type Y, but Z provided.
could be thrown.
Maybe we should create a global issue for that. (ping @justinvelluppillai)
I think a global issue could be good for this. I might be completely out of context here but ideally it would return a 422 code because it is a user correctable error and avoid any exceptions. Would likely need light validations for such a implementation though.
I think stopping such invalid input earlier might help with security too. Being able to hit methods such as preg_match etc can provide a vuln sometimes.