0

I am using parse_ini_file to parse an ini file using PHP.

Now I first upload an INI file to my server then open it and allow user to mak custom changes to the file.

Now once users has edited the file i get the data from post and save the file back to server. But Now i dont get my sections. INIdetails,Dialplan in the updated file so when i also want to write that to file how to do that?

This is the code :

$this->data['parameters'] = parse_ini_file($path.$filename,true);

    /*Getting Our POST DATA from View*/
        $data = array(
                        'SipUserName' => $this->input->post('SipUserName') , 
                        'SipAuthName' => $this->input->post('SipAuthName'), 
                        'DisplayName' => $this->input->post('DisplayName'),
                        'Password' => $this->input->post('Password'), 
                        'Domain' => $this->input->post('Domain'), 
                        'Proxy' => $this->input->post('Proxy'),
                        'Port' => $this->input->post('Port'), 
                        'ServerMode' => $this->input->post('ServerMode'),
                        'Param_1' => $this->input->post('Param_1'),
                        'Param_2' => $this->input->post('Param_2')
                    );


        /*Creating New file with the name of customer loggedin*/


        $name = $this->session->userdata('username');
        $ext = $this->session->userdata('extension');       
        $custom_file = fopen('uploads/'.$name.'_'.$ext.'.ini', 'w');




        fwrite($custom_file, "[INIDetails]\n");

        foreach ($data as $key => $value) 
        {
            fwrite($custom_file, "    $key = $value\n");
        }



        fclose($custom_file);   

        /*Setting path to New CUSTOM file with customer name as prefix*/
        $file = $path.$custom_file;


        function write_php_ini($array, $file)
        {
            $res = array();
            foreach($array as $key => $val)
            {
                if(is_array($val))
                {
                    $res[] = "[$key]";
                    foreach($val as $skey => $sval) $res[] = "$skey = ".(is_numeric($sval) ? $sval : '"'.$sval.'"');
                }
                else $res[] = "$key = ".(is_numeric($val) ? $val : '"'.$val.'"');
            }
            safefilerewrite($file, implode("\r\n", $res));
        }

        function safefilerewrite($fileName, $dataToSave)
        {    if ($fp = fopen($fileName, 'w'))
            {
                $startTime = microtime(TRUE);
                do
                {            $canWrite = flock($fp, LOCK_EX);
                   // If lock not obtained sleep for 0 - 100 milliseconds, to avoid collision and CPU load
                   if(!$canWrite) usleep(round(rand(0, 100)*1000));
                } while ((!$canWrite)and((microtime(TRUE)-$startTime) < 5));

                //file was locked so now we can store information
                if ($canWrite)
                {            fwrite($fp, $dataToSave);
                    flock($fp, LOCK_UN);
                }
                fclose($fp);
            }

        }

        /*Creates ini file, dumps array to string and creates .INI file*/
        write_php_ini($data,$file);
Rajan
  • 2,427
  • 10
  • 51
  • 111
  • Why are you using `parse_ini_file` to write to the ini file? That makes no sense. The purpose of `parse_ini_file` is to allow you to read the structured data in the ini file from code. Not the other way around. – Sherif Feb 29 '16 at 06:56
  • the function below writes the ini file] – Rajan Feb 29 '16 at 07:10
  • I wasn't confused about what your function did. My question was ***Why are you using `parse_ini_file` to write to the ini file?***. That's not what `parse_ini_file` is for. It's for **reading** values from the ini file **into** your _code_ and not meant for **writing** values into the ini file. – Sherif Feb 29 '16 at 07:14
  • i am not using parse_ini_file to write the ini file. I have a function write_php_ini that writes .ini files – Rajan Feb 29 '16 at 07:15
  • Then why are you using `parse_ini_file` at all? Your question is confusing, because the function you have here takes an array as input, which makes no sense. Why is the user uploading an ini file as input and you're writing a function that takes an array as input to write to an ini file? – Sherif Feb 29 '16 at 07:19
  • Then what do you suggest how should i be doing this? i first upload that file then read that file and allow user to edit that file and want to save it how to do this what should be the correct method then – Rajan Feb 29 '16 at 07:22
  • I guess the part that makes this question so incredibly nonsensical is that you've neglected to mention how you're letting the user edit the file. I was under the impression that the user was uploading the ini file, in which case I could not understand how uploading a file required you to have to _write_ to the file at all, since a file upload is essentially just writing to a file. If this is not the case then we have come full circle to why doesn't the user just upload the file and there is nothing left for you to do? – Sherif Feb 29 '16 at 07:26
  • @Sherif User upload a file, it has parameters initially blank. After uploading i let user to edit that file and put the values he want to for those parameters and save the file. When the file is uploaded its name and path are stored in database. also i have added what i get and what i want in outut so u might get my concern – Rajan Feb 29 '16 at 07:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/104851/discussion-between-rajan-and-sherif). – Rajan Feb 29 '16 at 11:28

2 Answers2

1

The culprit from your previous code is that your array is not formatted correctly, it should be array of arrays to achieve what you want.

Try below code:

// First read the ini file that the user was editing
// Your idea to read the existing ini file is good, since it will generate you the structured array
$previous_data = parse_ini_file($path . $filename, true);

// Overwrite/edit the previous_data using user's post data
$previous_data['INIDetails']['SipUserName'] = $this->input->post('SipUserName');
$previous_data['INIDetails']['Password']    = $this->input->post('Password');
$previous_data['INIDetails']['Domain']      = $this->input->post('Domain');
$previous_data['INIDetails']['Proxy']       = $this->input->post('Proxy');
$previous_data['INIDetails']['Port']        = $this->input->post('Port');
$previous_data['INIDetails']['SipAuthName'] = $this->input->post('SipAuthName');
$previous_data['INIDetails']['DisplayName'] = $this->input->post('DisplayName');
$previous_data['INIDetails']['ServerMode']  = $this->input->post('ServerMode');
$previous_data['INIDetails']['UCServer']    = $this->input->post('UCServer');
$previous_data['INIDetails']['UCUserName']  = $this->input->post('UCUserName');
$previous_data['INIDetails']['UCPassword']  = $this->input->post('UCPassword');

$previous_data['DialPlan']['DP_Exception'] = $this->input->post('DP_Exception');
$previous_data['DialPlan']['DP_Rule1']     = $this->input->post('DP_Rule1');
$previous_data['DialPlan']['DP_Rule2']     = $this->input->post('DP_Rule2');

$previous_data['DialPlan']['OperationMode']   = $this->input->post('OperationMode');
$previous_data['DialPlan']['MutePkey']        = $this->input->post('MutePkey');
$previous_data['DialPlan']['Codec']           = $this->input->post('Codec');
$previous_data['DialPlan']['PTime']           = $this->input->post('PTime');
$previous_data['DialPlan']['AudioMode']       = $this->input->post('AudioMode');
$previous_data['DialPlan']['SoftwareAEC']     = $this->input->post('SoftwareAEC');
$previous_data['DialPlan']['EchoTailLength']  = $this->input->post('EchoTailLength');
$previous_data['DialPlan']['PlaybackBuffer']  = $this->input->post('PlaybackBuffer');
$previous_data['DialPlan']['CaptureBuffer']   = $this->input->post('CaptureBuffer');
$previous_data['DialPlan']['JBPrefetchDelay'] = $this->input->post('JBPrefetchDelay');
$previous_data['DialPlan']['JBMaxDelay']      = $this->input->post('JBMaxDelay');
$previous_data['DialPlan']['SipToS']          = $this->input->post('SipToS');
$previous_data['DialPlan']['RTPToS']          = $this->input->post('RTPToS');
$previous_data['DialPlan']['LogLevel']        = $this->input->post('LogLevel');

// Set Name of New file with the name of customer logged in
$name        = $this->session->userdata('username');
$ext         = $this->session->userdata('extension');
$custom_file = "$name_$ext.ini";
$new_filename        = $path . $custom_file;

// Write the INI file
write_php_ini($data, $new_filename);

function write_php_ini($array, $new_filename)
{
    $res = array();
    foreach ($array as $key => $val) {
        if (is_array($val)) {
            $res[] = "[$key]";
            foreach ($val as $skey => $sval) {
                $res[] = "$skey = " . (is_numeric($sval) ? $sval : '"' . $sval . '"');
            }

        } else {
            $res[] = "$key = " . (is_numeric($val) ? $val : '"' . $val . '"');
        }

    }
    safefilerewrite($new_filename, implode("\r\n", $res));
}

function safefilerewrite($new_filename, $dataToSave)
{
    if ($fp = fopen($new_filename, 'w')) {
        $startTime = microtime(true);
        do {
            $canWrite = flock($fp, LOCK_EX);
            // If lock not obtained sleep for 0 - 100 milliseconds, to avoid collision and CPU load
            if (!$canWrite) {
                usleep(round(rand(0, 100) * 1000));
            }

        } while ((!$canWrite) and ((microtime(true) - $startTime) < 5));

        //file was locked so now we can store information
        if ($canWrite) {
            fwrite($fp, $dataToSave);
            flock($fp, LOCK_UN);
        }
        fclose($fp);
    }
}

From your previous code, there are bunch of inappropriate codes which I remove. Also, too many inconsistencies like Method naming, variable naming etc.

If your function was named Camel cased then through out your code it must be named as camel-cased. If your variables are with underscore, then through out your code, they must have underscore for two or more worded variable.

I didn't edit the naming convention of your code so you won't be confused but i suggest to have a consistent naming convention through out your project.

UPDATED:

based on your answer, it seems like you changed your whole code. I would like to provide another way using nested foreach and passing by reference that save couple of lines:

$this->data['params'] = $this->parameter_m->get();

$this->data['parameters'] = parse_ini_file($path . $filename, true);

foreach ($this->data['parameters'] as $key_header => &$value_header) {
    foreach ($value_header as $key_item => &$value_item) {
        $value_item = $this->input->post($key_item);
    }
}

$this->load->helper('file');

$this->load->library('ini');

$file = $path . $filename;

$ini = new INI($file);
$ini->read($file);
$ini->write($file, $this->data['parameters']);
Ceeee
  • 1,392
  • 2
  • 15
  • 32
  • yes i have changed the code because i have checking for each POST value with multple lines of code so – Rajan Mar 02 '16 at 05:25
  • can you help me with this:http://stackoverflow.com/questions/36052603/how-to-create-a-file-based-on-database-values – Rajan Mar 17 '16 at 05:51
  • please help me with this :http://stackoverflow.com/questions/36591037/write-database-values-to-a-ini-file-using-php-codeigniter – Rajan Apr 13 '16 at 07:11
1

Finally i got an answer:

I will loop through what i get from POST and will get each array's key. And then i will give the resultant to my Write Method

$this->data['params'] = $this->parameter_m->get();

        /*Getting the parameters to display on view*/

        $this->data['parameters']  = parse_ini_file($path.$filename,true);




        while (current($this->data['parameters']) ) 
        {
            $param_set = current($this->data['parameters']);
            $param_type = key($this->data['parameters']);

                foreach ($param_set as $key =>$value) 
                {

                    $this->data['parameters'][$param_type][$key] = $this->input->post($key);

                } 

                next($this->data['parameters']);
        }




        $this->load->helper('file');

        $this->load->library('ini');

        $file = $path.$filename;

        $ini = new INI($file);
        $ini->read($file);
        $ini->write($file, $this->data['parameters']);  
Rajan
  • 2,427
  • 10
  • 51
  • 111
  • Seems like this is completely different from the code in your question, but I updated my answer just incase you wanted another way to achieve this :) good luck mate – Ceeee Mar 02 '16 at 05:22
  • 1
    @Ceeee your code is correct, but i just did not want to write for each POST value i get so i just used loop, Thanks a lot for ur help – Rajan Mar 02 '16 at 05:24
  • No worries. Always here to help :) Your code right now is better than the previous. You are right about looping through the items dynamically instead of editing them one by one :) – Ceeee Mar 02 '16 at 05:27
  • @Ceeee Please help me with this:http://stackoverflow.com/questions/36052603/how-to-create-a-file-based-on-database-values – Rajan Mar 17 '16 at 05:51