<?php
defined( 'ABSPATH' ) or exit;   // show a blank page if try to access this file directly

require_once( EWZ_PLUGIN_DIR . '/classes/ewz-base.php' );
require_once( EWZ_PLUGIN_DIR . 'classes/ewz-exception.php' );

/**
 * @param  string  $val
 *
 * @return  boolean
 */
function ewz_is_valid_ewz_path( $val ) {
   $info = pathinfo( $val );
   // strncmp returns 0 if strings are equal
   return( strpos( $info['dirname'], EWZ_IMG_UPLOAD_DIR ) === 0 );
}

/**
 * @param  string  $val
 *
 * @return  boolean
 */
function ewz_is_valid_ewz_url( $val ){
    return( strpos( $val, EWZ_IMG_UPLOAD_URL ) === 0 );
}

/***********************************************************************/
/* strip all html tags except what wp allows in comments, plus <br>    */
/* remove other line breaks, tabs and extra white space, strip octets. */
/***********************************************************************/
/**
 * @param   string  $string
 *
 * @return string
 */
function ewz_safe_tags( $string ){

    global $allowedtags;
    $allowed_html = $allowedtags;
    $allowed_html['br'] = array();

    $escval =  wp_kses( $string, $allowed_html );

    return $escval;
}

/*****************************************************/
/* Return the error message for a file upload error  */
/*****************************************************/
/**
 * @param  mixed  $code
 *
 * @return string
 */
function ewz_upload_errmsg($code){

    $message = "";
    if( is_int($code) ){
        switch ($code) {
        case UPLOAD_ERR_INI_SIZE:
            $message = "The uploaded file exceeds the upload_max_filesize directive in php.ini";
            break;
        case UPLOAD_ERR_FORM_SIZE:
            $message = "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form";
            break;
        case UPLOAD_ERR_PARTIAL:
            $message = "The uploaded file was only partially uploaded";
            break;
        case UPLOAD_ERR_NO_FILE:
            $message = "No file was uploaded";
            break;
        case UPLOAD_ERR_NO_TMP_DIR:
            $message = "Missing a temporary folder";
            break;
        case UPLOAD_ERR_CANT_WRITE:
            $message = "Failed to write file to disk";
            break;
        case UPLOAD_ERR_EXTENSION:
            $message = "File upload stopped by extension";
            break;

        default:
            $message = "Unknown upload error";
            break;
        }
    } else {
        $message = $code;
    }

    return $message;
}


 /**
  * Append a number to the filename to make it unique in its directory.
  *
  * @param  string $filepath
  *
  * @return  string
  */
function ewz_uniq_fname( $filepath  )
{
    clearstatcache();
    if( file_exists( $filepath ) ) {
        $parts = pathinfo( $filepath );
        $basepath = $parts['dirname'] . '/' . $parts['filename'];
        $ext = $parts['extension'];
        $newfilepath =  $basepath . Ewz_Settings::get_ewz_option('spec_char_replace') .
                       count( glob( "$basepath*.$ext" )) . '.'. $ext;
        return $newfilepath;
    } else {
        return $filepath;
    }
}

/**
 * Return a string used to display a stored item field in read-only fashion
 *
 * For text fields, just return the text.  For drop-down items, return the option display label.
 *
 * @param  Ewz_Field   $field
 * @param  string      $value    stored value for this field
 * @return string used to display the value
 */
function ewz_display_item( $field, $value ) {

    if(  'opt' == $field->field_type ){
        foreach( $field->fdata['options'] as $n => $opt ){
            if( $opt['value'] == $value ){
                return $opt['label'];
            }
        }
    } elseif( 'rad' == $field->field_type ){
        if ( $value  ) {
            if( isset( $field->fdata['radlabel'] ) ){
                return $field->fdata['radlabel'];
            } else {
               return 'checked';
            }
        } else {
            if( isset(  $field->fdata['xradlabel'] ) ){
                return $field->fdata['xradlabel'];
            } else {
                return  '-';
            }
        }
    } elseif( 'chk' == $field->field_type ){
        if ( $value  ) {
            if( isset(  $field->fdata['chklabel'] ) ){
                return $field->fdata['chklabel'];
            } else {
                return  'checked';
            }
        } else {
            if( isset(  $field->fdata['xchklabel'] ) ){
                return $field->fdata['xchklabel'];
            } else {
                return  '-';
            }
        }
    } elseif( 'lab' == $field->field_type ){
        return $field->fdata['showlabel'] ? $field->fdata['label'] : '';
    } else {
        return $value;
    }
    return '';
}

/**
 * Get rid of dangerous special characters in a string to be used as part of a file path
 *
 * replace all special chars with '_' ( or Ewz_Settings::get_ewz_option('spec_char_replace') )
 * replace all but last dot with '_'   ( or Ewz_Settings::get_ewz_option('spec_char_replace') )
 * append '_' to base name if name ends in a digit ( so wp's added numbers can be seen, and so
 *      no filename is completely numeric -  wp does odd things if filename is just a number )
 *
 * @param   string  $string
 * @param   boolean $appendU
 * @return  string
 */
function ewz_to_valid_fname( $string, $appendU )
{

    $replacement = Ewz_Settings::get_ewz_option('spec_char_replace');
    // replace all non-alphanum chars except '_', '-', '.' with $replacement
    $string0 = preg_replace( '/[^a-zA-Z0-9_\-\.]/', $replacement, $string );

    // replace any initial _, since Windows hides such files, and they may be downloaded.
    // Replace with A to ensure something is there.
    $string1 = preg_replace( '/^_/', 'A', $string0 );

    // replace all but last dot -- otherwise, a file with more than one dot fails
    $numdots = substr_count( $string, '.' );
    $string2 = preg_replace( '/\./', $replacement, $string1, $numdots - 1 );

    if( $appendU && Ewz_Settings::get_ewz_option('terminal_underscore')){
        // append $replacement if name ends in digit, so wp's added numbers can be seen,
        // and so no filename is completely numeric (wp does odd things if filename is just a number)
        $string2 = preg_replace( '/(\d)\./', '${1}'.$replacement.'.', $string2 );
    }
    return $string2;
}


/**
 * Recursive version of wp function esc_html
 *
 * @param  mixed  $data
 * @return mixed
 */
function ewz_html_esc( $data ) {
    if ( is_array( $data ) ) {
        foreach ( $data as $key => $value ) {
            $data[$key] = ewz_html_esc( $data[$key] );
        }
    } elseif ( is_object( $data ) ) {
        foreach ( $data as $key => $value ) {
            $data->{$key} = ewz_html_esc( $data->$key );
        }
    } elseif  ( is_string( $data ) ) {

        $data = esc_html( $data );
    }
    return $data;
}


/**
 * Generate an html option list from an array, escaped for display
 *
 * @param   array<int,array<string, mixed>>    $opts each element being an array of the form
 *                   ('value'=>XXX, 'display'=>YYY, ['selected'=>true/false])
 * @param   boolean  $none_if_only1    if true, return an empty string if there is only one option
 * @return  string   html option list
 */
function ewz_option_list( $opts, $none_if_only1 = false ){
    $return = '';
    if( $none_if_only1 && count( $opts ) < 2 ){
        return '';
    }
    foreach( $opts as $option ){
        $return .= '<option value="' . esc_attr( $option['value'] ) . '"';
        if( isset( $option['selected'] ) &&  $option['selected'] ){
            $return .= 'selected="selected"';
        }
        $return .= '>' . esc_html( $option['display'] ) . '</option>';
    }
    return $return;
}


/**
 * Generate a name for the thumbnail file from the filename
 *
 * Replace .ext with  something like "-200x150.ext", following
 *              the convention used by Wordpress
 * @param   string  $fpath  input filename ( full path )
 * @return  string  $fname with .ext replaced by -thumb.ext
 */
function ewz_thumbfile_path( $fpath ){
    if( ! ewz_is_valid_ewz_path( $fpath ) ){
        throw new EWZ_Exception( __("Invalid file path '$fpath'", 'entrywizard') );
    }

    $ext = pathinfo( $fpath, PATHINFO_EXTENSION );

    $dim =  ewz_thumbfile_dimensions();

    return preg_replace( "/\.$ext$/", "-{$dim['w']}x{$dim['h']}.$ext", $fpath );
}
/**
 * Return the dimension array matching WP's 'thumbnail' size options
 *
 * @return  array<mixed> ( 'w'=>thumbnail width, 'h'=>thumbnail height )
 */
function ewz_thumbfile_dimensions(){

    $w = intval( get_option( 'thumbnail_size_w' ) );
    if( !$w ){ $w = 128; }
    $h = intval( get_option( 'thumbnail_size_h' ) );
    if( !$h ){ $h = 96; }

    return array('w'=>$w, 'h'=>$h);
}

/**
 * Generate a url from a path in the uploads directory
 *
 * @param  string  $fname  input filename, must be in the uploads directory
 * @return string  url
 */
function ewz_file_to_url( $fname ){
    if( ! ewz_is_valid_ewz_path( $fname ) ){
        throw new EWZ_Exception(  __("Invalid file path '$fname'", 'entrywizard' ) );
    }

    $uploads = wp_upload_dir();

    if( strncmp( $fname, $uploads['basedir'], strlen($uploads['basedir']) ) ){
        throw new EWZ_Exception( "Input filename $fname is not in the uploads path" );
    }
    return str_replace( $uploads['basedir'], $uploads['baseurl'], $fname );
}

/**
 * Generate a filename from the url of a file in the uploads directory
 *
 * @param   string  $url  input url, must be in the uploads directory
 * @return  string  filename
 */
function ewz_url_to_file( $url ){
    if( ! ewz_is_valid_ewz_url( $url ) ){
        throw new EWZ_Exception( __("Invalid url '$url'", 'entrywizard' ));
    }

    $uploads = wp_upload_dir();
    $starts_with = ( strpos( $url, $uploads['baseurl'] ) === 0 );
    if( !$starts_with ) {
        throw new EWZ_Exception( "Input url $url is not in the uploads path" );
    }
    return str_replace( $uploads['baseurl'], $uploads['basedir'], $url );
}

/**
 * Return the html for displaying a fixed-text label field
 *
 * @param   string    $ename       escaped js name of field
 * @param   string       $id       id to use for the field
 * @param   string    $savedval    data currently stored for the field
 * @param   Ewz_Field $field       field info
 * @return  string   -- the html
 */
function ewz_display_lab_form_field( $ename, $id, $savedval, $field )
{
    $val_to_save = $field->fdata['label'];

    $val_to_display =  ( isset($field->fdata['showlabel']) && $field->fdata['showlabel'] ) ? $val_to_save : '';
    return '<input type="hidden"  name="' . esc_attr( $ename ) .
                       '" id="' . $id .
                       '" value="' . esc_attr( $val_to_save ) .
                '">'.
            $val_to_display;
}
/**
 * Return the html for displaying a single text-input field
 *
 * @param   string      $ename       escaped js name of field
 * @param   string         $id          id to use for the field
 * @param   string      $savedval    data currently stored for the field
 * @param   Ewz_Field   $field       field info
 * @return  string   -- the html
 */
// NB: rating code assumes the first occurrence of '>' in the returned value is the one closing '<textarea' or '<input'
function ewz_display_str_form_field( $ename, $id, $savedval, $field )
{
    if( !isset( $field->fdata['textrows']  ) ){
        $field->fdata['textrows'] = 1;
    }
    if( $field->fdata['textrows'] > 1 ){
        return '<textarea class="ewz_area" autocomplete="off" name="' . esc_attr( $ename ) .
            '" id="' . esc_attr( "$id" ) .
                       '" cols="' . esc_attr(  $field->fdata['fieldwidth']  ) .
                       '" rows="' . esc_attr(  $field->fdata['textrows'] ) .
                       '" maxlength=' . esc_attr(  $field->fdata['maxstringchars'] ) .
            '>' . esc_attr( $savedval ) . '</textarea>';

    } else {
        return '<input type="text" autocomplete="off" name="' . esc_attr( $ename ) .
                       '" id="' . $id .
                       '" size="' . esc_attr( $field->fdata['fieldwidth'] ) .
                       '" maxlength="' . esc_attr( $field->fdata['maxstringchars'] ) .
                       '" value="' . esc_attr( $savedval ) .
                '">';
    }
}

/**
 * Return the html for displaying a single image field
 *
 * @param   string      $ename       escaped js name of field
 * @param   string         $id
 * @param   string      $savedval    data currently stored for the field
 * @param   Ewz_Field   $field       field info
 * @param   int         $webform_id
 * @return  string   -- the html
 */
function ewz_display_img_form_field( $ename, $id, $savedval, $field, $webform_id )
{
    $esc_wid = esc_attr( "$webform_id" );
    $esc_id =  esc_attr( "$id" );
    if ( $savedval ) {
        $ret  = '<input type="hidden" name="' . esc_attr( $ename ) . '" value="ewz_img_upload" >';
        $ret .= '<img id="' .$esc_id . '" src="' . esc_url( $savedval ) . '">';
        return $ret;
    } else {
        $qname = "'" . $esc_id . "'";
        $esc_fid = esc_attr( "$field->field_id" );
        $imginfo = '<input type="file"  name="' . esc_attr( $ename ) .  '" id="' . $esc_id .
            '" onchange="fileSelected(' . $esc_fid . ', ' . $qname . ', ' . $esc_wid . ' );">';
        // watch no spaces here - they put newlines between the divs
        $imginfo .= '<div id="dv_' .$esc_id . '" style="display:none">';
        $imginfo .= '<div id="nm_' .$esc_id . '"></div>';
        $imginfo .= '<div id="sz_' .$esc_id . '"></div>';
        $imginfo .= '<div id="tp_' .$esc_id . '"></div>';

        $imginfo .= '<div id="cs_' .$esc_id . '"></div>';

        $imginfo .= '<div id="wh_' .$esc_id . '"></div>';
        $imginfo .= '</div>';
        return $imginfo;
    }
}

/**
 * Return the html for displaying a single option field
 *
 * @param   string $ename       escaped js name of field
 * @param   string    $id
 * @param   string  $savedval    data currently stored for the field
 * @param   Ewz_Field  $field       field info
 * @param   boolean $fixed
 * @return  string   -- the html
 */
// NB: rating code assumes the first occurrence of '>' in the returned value is the one closing '<select'
function ewz_display_opt_form_field( $ename, $id, $savedval, $field, $fixed )
{
    $_disable = $fixed ? ' disabled="disabled"' : '';
    // to handle older version of ewz-rating
    if( !isset($field->fdata['selecttext']) ){
        $field->fdata['selecttext'] = '';
    }

    $txt = '<select  autocomplete="off" name="' . esc_attr( $ename ) . '" id="' . esc_attr( "$id" ) .'">';
    $txt .= '  <option value="" ' .  $_disable . '>' . $field->fdata['selecttext'] . '</option>' ;
    foreach ( $field->fdata['options'] as $n => $dataval ) {
        $txt .= '<option value="' . esc_attr( $dataval['value'] ) . '"';
        if ( $dataval['value'] === $savedval ) {
            $txt .=         ' selected="selected" ';
        } else {
            $txt .= $_disable;
        }
        $txt .= '>' . esc_html( $dataval['label'] ) . '</option>';
    }
    $txt .= '</select>';
    return $txt;
}

/**
 * Display a radio button
 *
 * Radios in the same column must have the same name, so use the field id for that.
 * Give the button a value equal to the name we would normally have used.
 * If it is checked, when submitting, Javascript disables it and creates a new hidden
 * input with name equal to the value of the radio button and value '1'.
 *
 * @param  string     $ename
 * @param  string        $id
 * @param  string     $savedval
 * @param  Ewz_Field  $field
 * @return string
 */
// NB: rating code assumes the first occurrence of '>' in the returned value is the one closing '<input'
function ewz_display_rad_form_field( $ename,  $id, $savedval, $field )
{
    return '<input  autocomplete="off" type="radio"  name="radio' . esc_attr( "$field->field_id" ) . '"' .
        ' id="' .  esc_attr( "$id" ) . '"' .
        ' value="' .  esc_attr( $ename ) .'" ' .
        ($savedval ? ' checked="checked" ' : '') .
        '>';
}


/**
 *  NB: rating code assumes the first occurrence of '>' in the returned value is the one closing '<input'
 *
 * @param string  $ename
 * @param string     $id
 * @param string     $savedval
 *
 * @return string
 */

function ewz_display_chk_form_field( $ename, $id, $savedval )
{
    return '<input  autocomplete="off" type="checkbox"  name="' .  esc_attr( $ename ).
                   '" value="1"  id="' . esc_attr( "$id" ) . '"' .
          ( $savedval ? ' checked="checked" ' : '' ) .
            '>';
}
