We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 38878
    • 255 Posts
    I am making my first attempt (so go easy on me) at writing a custom snippet using xPDO which is basically converting a php/mysql script that was fairly raw but functional. The intent is to enable an android device to upload raw csv log data to the resource referencing the snippet below and adding the raw log data to a custom db. I have already created the tables and schema and tested them to make sure I can read. Now I'm to the point of writing the upload log file snippet.

    My first question is if this snippet is called from an anonymous user, how could the security be handled? Would it be safer to create a separate context for this that permits anonymous users access to only this resource/snippet? The data does pass device IDs that I could query and match against a pre-defined list to allow only certain IDs to post data. While this isn't the greatest security, it will at least be obscurity;)

    Secondly, my ported snippet is throwing a 500 error (I'm on modxcloud and no server errors, thus attempting modx->log entries and returns. The snippet code is:

    <?php
    $path = MODX_CORE_PATH . 'components/torque-web/';
    $result = $modx->addPackage('torque-web',$path . 'model/','torque_');
    if (! $result) {
        $modx->log(xPDO::LOG_LEVEL_ERROR, '[upLoadLogs] failed to add package!');  return "Script failed"; 
    } 
    else {
       // get all the fields in the raw_logs and set to db fields
       $dbcols = $xpdo->getFields('RawLogs');
       $count = count($dbcols);
    
       // get all the fields in the db
       if ($count > 0) {
           while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
               $dbfields[]=($row['Field']);
           }
       }
       else { $modx->log(xPDO::LOG_LEVEL_ERROR, '[upLoadLogs] no fields found in RawLogs!');  return "Script failed";  }
    
       // check through the k* _REQUEST arguments to make sure there's a field to insert into
       foreach ($_REQUEST as $key => $value) {
    	$keys[] = $key;
    	if (preg_match("/^k/", $key)) {
    		$values[] = $value;
    	} else {
    		$values[] = "'".$value."'";
    	}
    	if (!in_array($key, $dbfields)) {
    		// if the field doesn't exist, alter the table to add it.
    		$manager->addField('RawLogs', '$key');
    	}
       }
       if ((! $keys) && (! $values)) {$modx->log(xPDO::LOG_LEVEL_ERROR, '[upLoadLogs] keys and/or values arrays are empty!'); return "Script failed"; }
       // we have 2 arrays, the fields($keys) and the data($values) so throw them into the database.
       $logData = array_combine($keys, $values);
       $myLog = $xpdo->newObject('Log',array($logData));
    
       // torque expects the page to return OK! so this should be the only output
       if ($$myLog->save() == false) {
          $modx->log(xPDO::LOG_LEVEL_ERROR, '[upLoadLogs] Log file save failed!'); return "Script failed"; }
       }
       else {
          return "OK!";
       }
    }


    Again, this is my first xPDO attempt. I'm sure I'm missing something.

    TIA


      • 38878
      • 255 Posts
      Update. I've moved this resource to it's own context and given anon rights upload. Still looking for some feedback on the xPDO stuff. Am I at least in the ballpark, or am I totally whack?
        • 42602
        • 81 Posts
        One thing that for sure shines out is that the addField() method should not work as it requires the field to be defined in the rawlogs.map.inc.php file. I do not know if you have it but from how your application might work I would guess that you do not have the field in the map file.

        Also the addField() method is part of xPDOManager class so you first need to call it to script with (for example) "$manager = $modx->getManager();"

        Also the $result is not an pdo connection/statement object, to get fields from the database you need to do simple PDO query first. This for example would get you the field names:

        $tableName = $modx->getTableName('RawLogs'); // Get the real table for RawLogs
        $res = $modx->query("DESCRIBE $tableName");
        while ($row = $res->fetchAll(PDO::FETCH_ASSOC)) {
            $dbfields[]= $row['Field'];
        }


        There could be some mistakes in my code also smiley but hopefully gives some pointers where to look at. Also would not suggest creating fields in this manner at all, there is huge risk that something goes mad with the uploaded csv file or whatever where it gets the data and also there is huge risk of injections and vulnerabilities depending how the data will be used.
          • 38878
          • 255 Posts
          Thanks much. Ill try your suggestion. As for injection and security, I will be locking it down with additional security so it will not be public.


          Quote from: dunnock at Mar 18, 2013, 09:28 AM
          One thing that for sure shines out is that the addField() method should not work as it requires the field to be defined in the rawlogs.map.inc.php file. I do not know if you have it but from how your application might work I would guess that you do not have the field in the map file.

          Also the addField() method is part of xPDOManager class so you first need to call it to script with (for example) "$manager = $modx->getManager();"

          Also the $result is not an pdo connection/statement object, to get fields from the database you need to do simple PDO query first. This for example would get you the field names:

          $tableName = $modx->getTableName('RawLogs'); // Get the real table for RawLogs
          $res = $modx->query("DESCRIBE $tableName");
          while ($row = $res->fetchAll(PDO::FETCH_ASSOC)) {
              $dbfields[]= $row['Field'];
          }


          There could be some mistakes in my code also smiley but hopefully gives some pointers where to look at. Also would not suggest creating fields in this manner at all, there is huge risk that something goes mad with the uploaded csv file or whatever where it gets the data and also there is huge risk of injections and vulnerabilities depending how the data will be used.