cereal 1,524 Nearly a Senior Poster Featured Poster

Or, instead of:

if($width > 2896) return false;
if($height > 2896) return false;

You could use:

if($width * $height > 8388608) return false;

Where 8388608 is 32*1024*1024/4 and allows much more flexibility, because we are going to check the total number of pixels instead of the single sizes, and so a user can upload an image of 3000x1000...

cereal 1,524 Nearly a Senior Poster Featured Poster

It seems fine, but I would fix few things.

Change line 84 and 85 with these:

$temp_image_path = $_FILES[$field]['tmp_name'];
if( ! array_key_exists($field, $_FILES)) return false;
$image_name = sha1($_SESSION['username']);

With the IF condition we check if the $field is defined in the $_FILES array, currently seems safe and process_image_upload() returns false, but only because getimagesize() fails.

Also, you shouldn't need the strip_tags() function with sha1() because it will generate an hash and if you get the data from $_SESSION it should be already safe. But you can use it if you prefer it. Mine is just a suggestion.

If you want to use the GD library then you have to check the pixels of the original image, I see you have defined the sizes of the thumbnail but the problem is that the GD library assigns 4 bytes for each pixel of the image (RGB + Alpha channel) and if the user sends an image of 3000 pixels per side you get:

((3000 * 3000 * 4)/1024)/1024

which returns 34MB, if 8000 per side you get 244MB. In these cases if the memory limit is low the script will be interrupted. To check the current limit use:

echo ini_get('memory_limit');

You get the value in bytes, if you get -1 there is no limit and so the script will not crash. If instead there is one, calculate the maximum pixels you can support and use them as hard limit, for example if the memory limit is 32MB:

echo floor(sqrt((32*1024*1024)/4)); …
cereal 1,524 Nearly a Senior Poster Featured Poster

No problem, I'm referring to this:

I'm sorry I cannot help much on this, but I don't have a Windows box right now, so I cannot test an installation with your MySQL version.

cereal 1,524 Nearly a Senior Poster Featured Poster

You can use Imagick:

$tmpfile = $_FILES['user_profile_image']['tmp_name'];
$dest = './images/'.sha1($_SESSION['username']).'.png';

$img = new Imagick();
$img->readImage($tmpfile);
$img->stripImage();
$img->scaleImage(100, 100, true);
$img->writeImage($dest);
$img->clear();
$img->destroy();

Where the first parameter in the scaleImage() method is for the width, and the second for the height. The third parameter is used in case the uploaded images is under the defined sizes, for example here we have 100x100, while the uploaded image is 80x80, this will be resized to 100x100, if you set false then you get 80x80.

By using the temporary file in the $_FILES array, you can avoid to use move_uploaded_file() unless you want to store the original file somewhere.

Since you're using the username as filename you can, also, avoid to store it into the table database, just use the hash of the username. In my example I'm using sha1() which will return a 40 hexadecimal string, so the range will be based on a-f0-9 (i.e. 16 alphanumeric characters). When you want to display the avatars you do:

# from session
echo '<img src="/images/'. sha1($_SESSION['username']) .'.png" />';

# manually
echo '<img src="/images/'. sha1('Eagle.Avik') .'.png" />';

# or from query result set in while loop
echo '<img src="/images/'. sha1($row['username']) .'.png" />';

About Security. I don't know the contents of the included file (loginssn.php) nor I see how $rooturl is defined, as far as I see the script is enough secure. I would add a check to verify if user_profile_image exists in the $_FILES array, because if a client sends a cURL request with …

cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, I got it, it happens because you have to encode & in the query string, try with:

echo rawurlencode("http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");

It should work fine.

cereal 1,524 Nearly a Senior Poster Featured Poster

You're welcome!

Yes, because the update query would return only the affected rows. So, the complete version would be:

$stmt = $mysqli->prepare("UPDATE brick FROM goodship WHERE name = ?");
$stmt->bind_param('s', $_SESSION['id']);
$stmt->execute();

if($stmt->affected_rows() > 0)
{
    # continue
}

Where the s in the bind_param method stands for string, if the id is a digit, then change it to: i for integer, d for double.

Bye!

cereal 1,524 Nearly a Senior Poster Featured Poster

You can limit the access to the file by saving it outside the webroot, or if you cannot, by applying an .htaccess rule to limit the access to a path directory or to a specific filetype. A part this, there are some chipers for sqlite files, for example:

But you have to install and enable the module.

cereal 1,524 Nearly a Senior Poster Featured Poster

I don't know if there is anything in PHP, but there is a tool written in Python:

Otherwise you can check the SQLite library, it's used with sqlite files:

But files and sqlite are, generally, good to save little data, if your application will be used by multiple users and deal with many MB of data then it's better to use a relational database. In alternative take a look at NoSQL solutions:

cereal 1,524 Nearly a Senior Poster Featured Poster

You're using an array, so you have to surround it with parentheses, otherwise you have to escape the single quotes:

mysqli_query($con,"UPDATE goodship SET brick=brick+1 WHERE id = {$_COOKIE['id']}");

In addition, use prepared statements, otherwise a user can push in arbitrary code:

cereal 1,524 Nearly a Senior Poster Featured Poster

In the link above there are few workarounds to override the issue, try to edit Windows register as explained and if it does not work wait for other answers, I have not found anything useful, bye!

cereal 1,524 Nearly a Senior Poster Featured Poster

IF you're using Windows, the mail() function will not parse emails in format Name <email@domain.tld>.

Second use double quotes:

$email = "{$_REQUEST['email']},{$_REQUEST['email2']}";

Otherwise you have to escape the array keys quotes.

Third: avoid using $_REQUEST and filter the input, currently this makes your script attackable.

cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, as you see you got the $_FILES array and the validation went through. Now this is yours:

<?php

if($_FILES)
{   
    $uploaddir = "./images";
    $userfile = $_FILES['user_profile_image'];
    $allowed_filetypes = array('.jpg', '.jpeg');
    $maxsize = 2097152;
    $upload_path = $uploaddir;
    $filename = $_FILES['user_profile_image']['name'];
    $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1);

    if(!in_array($ext,$allowed_filetypes)){
        echo 'Opps! Image Format not allowed!';
        exit;
     }

    echo 'POST:<pre>';
    print_r($_POST);
    echo '</pre>';

    echo 'FILES:<pre>';
    print_r($_FILES);
    echo '</pre>';

}

?>

<form method="post" action="" enctype="multipart/form-data">
    <input type="file" name="user_profile_image" />
    <input type="submit" name="submit" value="upload" />
</form>

The only adjustment I had to make was in the $allowed_filetypes array, by adding the dots to the values.

This is the version with my suggestions:

<?php

if($_FILES)
{

    $uploaddir = "./images";
    $userfile = $_FILES['user_profile_image'];
    $allowed_filetypes = array(
        'jpg',
        'jpeg',
        'jpe',
        'png'
    );
    $maxsize = 2097152;
    $upload_path = $uploaddir;
    $filename = $_FILES['user_profile_image']['name'];
    $ext = strtolower(pathinfo(parse_url($filename, PHP_URL_PATH), PATHINFO_EXTENSION));

    if(!in_array($ext,$allowed_filetypes)){
        echo 'Opps! Image Format not allowed!';
        exit;
     }

    echo 'POST:<pre>';
    print_r($_POST);
    echo '</pre>';

    echo 'FILES:<pre>';
    print_r($_FILES);
    echo '</pre>';

}

?>

<form method="post" action="" enctype="multipart/form-data">
    <input type="file" name="user_profile_image" />
    <input type="submit" name="submit" value="upload" />
</form>

If you still don't get it to work, post your updated version of the script.

cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, check it, in the meantime this is my test:

<?php

if($_FILES)
{

    $filename = $_FILES['user_profile_image']['name'];
    $allowed_filetypes = array(
        'jpg',
        'jpeg',
        'jpe',
        'png'
    );

    $ext = strtolower(pathinfo(parse_url($filename, PHP_URL_PATH), PATHINFO_EXTENSION));

    if( ! in_array($ext, $allowed_filetypes)) { echo 'not allowed'; }
    else { echo $filename . "<br />"; }

    echo 'POST:<pre>';
    print_r($_POST);
    echo '</pre>';

    echo 'FILES:<pre>';
    print_r($_FILES);
    echo '</pre>';

}

?>

<form method="post" action="" enctype="multipart/form-data">
    <input type="file" name="user_profile_image" />
    <input type="submit" name="submit" value="upload" />
</form>

And works fine. Try it by yourself, and check what you get in the $_FILES array, you can paste the result here.

cereal 1,524 Nearly a Senior Poster Featured Poster

Do you mean you get the same error or is different? Can you show the name of the file? E.g.: image.jpg.

Also, if this file is a PNG add the extension to the array:

$allowed_filetypes = array(
    'jpg',
    'jpeg',
    'jpe',
    'png'
);

Otherwise the script will continue to accept only files with jpg or jpeg extension.

cereal 1,524 Nearly a Senior Poster Featured Poster

It's seems a permission error. If the folder already exists make sure the read-only flag is unchecked. This bug seems related to your case:

Can you try a newer version?

cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, in practice at line 10 you get the extension with the dot (.jpg), you can add them to the array values:

$allowed_filetypes = array(
    '.jpg',
    '.jpeg'
);

Or you can change line 10 with this:

$ext = strtolower(pathinfo(parse_url($filename, PHP_URL_PATH), PATHINFO_EXTENSION));

In case the file submitted is without an extension, the above will return an empty string. While the original script you are using, will return part of the file name.

Try with this modification and then, if you have still difficults to solve the problems, let us know.

Docs about pathinfo(): http://www.php.net/manual/en/function.pathinfo.php

Note for the record: there are few typos in my previous post, the name of the program was jpegtran, neither jpetran nor jpeptran...

cereal 1,524 Nearly a Senior Poster Featured Poster

It seems your SSL domain is not well configured, if you browse to the root https://nadim.org/ you get the default page. The index.php page is missing, the new2 directory is missing as well.

By the way, even switching from HTTPS to HTTP it does not work, you need to complete the query string with &prodid=132&cat=1.

cereal 1,524 Nearly a Senior Poster Featured Poster
Regarding your script

There are some variables that are not set, for example at line 10:

$upload_path = $uploaddir;

Where is the value of $uploaddir?

At line 3, instead:

$userfile = $_POST['user_profile_image'];

You're expecting a value from POST, but in the form this input field is file type:

<input type="file" name="user_profile_image">

So, it will be handled by the $_FILES array, check these examples:

At line 12:

$filename = $_FILES['userfile']['name'];

But the form will send user_profile_image.

At line 16, you have another missing variable $allowed_filetypes which should be an array like this:

$allowed_filetypes = array('jpg', 'jpeg');

Read the above link with the examples and try to rewrite your script.

Regarding security

The only method to be sure, is to remove the code. When there is an embedded script, in case of a jpeg file, this is written in the FF FE bytes block, which is the area used by the softwares to save comments, metadata and other stuff:

An easy method is to use commands like jpetran:

jpeptran -copy none original.jpg > new.jpg

Otherwise, you could read the file, byte per byte and remove all the contents from FF FE to the next marker.

A part this, place the original file inside a directory that is not accessible to the user. Serve a resized image, the resizing process most of the times will remove the comment block, but pay attention to this:

convert -thumbnail …
cereal 1,524 Nearly a Senior Poster Featured Poster

Use mysql_affected_rows() instead of mysql_num_rows($num_rows). Also use MySQLi or PDO libraries, since the MySQL library is going to be removed.

Docs: http://php.net/mysql_affected_rows

cereal 1,524 Nearly a Senior Poster Featured Poster

It means you got this virus from a website you visited with Google Chrome, in this case the PHP script is embedded in a JPEG file, if you open it with an hex editor you will see the code. In this case just empty the cache, this kind of "virus" runs on the webserver and gets executed when the client opens the file only if the file can be handled by the PHP engine.

If you can, try to understand which website was the source and send a report to the owner.

P.S. I tried the script, it's the WSO 2.5 shell.

cereal 1,524 Nearly a Senior Poster Featured Poster

There are two small errors here:

FOREIGN KEY (student) REFERENCES student(name),
foreign key (student_id) references student(student_id))

The name of the referenced table is students, so change it to:

FOREIGN KEY (student) REFERENCES students(name),
foreign key (student_id) references students(student_id))

The other problem is given by the first of these two constraints, in order to work you have to create a unique index for students.name, so:

CREATE TABLE students (
    student_id varchar(225),
    name varchar(225) unique,
    gender varchar(225),
    course varchar(225),
    PRIMARY KEY (student_id)
 ) ENGINE=InnoDB;

And it will work fine. Bye!

cereal 1,524 Nearly a Senior Poster Featured Poster

You can loop 3 times:

foreach($_POST['attr'] as $k1 => $v1)
{
    foreach($v1 as $k2 => $v2)
    {
        foreach($v2 as $k3 => $v3)
        {
            echo $v3['name'];
            echo $v3['price'];
        }
    }
}

An alternative is to use an iterator:

$arr = array();
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($_POST['attr']));

foreach($iterator as $key => $value)
{
    $arr[$key][] = $value;
}

for($i = 0; $i < count($arr); $i++)
{
    echo $arr['name'][$i];
    echo $arr['price'][$i];
}
cereal 1,524 Nearly a Senior Poster Featured Poster

Try with $row[0] and $row[1], the fetch row method returns a numeric array, use fetch_assoc() if you want to use the column names:

cereal 1,524 Nearly a Senior Poster Featured Poster

Multiple foreign keys are possible, show your create statements and the full error message.

cereal 1,524 Nearly a Senior Poster Featured Poster

You can use file_get_contents() to get the link contents, and curl to upload the file and receive the response. Here's a rough example:

<?php

$fast = json_decode(file_get_contents('http://www.multiup.org/api/get-fastest-server'));

if($fast->error !== 'success') die('Error!');

$url = file_get_contents('http://upload.wikimedia.org/wikipedia/commons/a/ac/SubtractiveColorMixing.png');
$tmpfile = tempnam("/tmp", "FOO");
$filearray = array('files[]'=>'@'.$tmpfile);

$handle = fopen($tmpfile, "w");
fwrite($handle, $url);
fclose($handle);

$file = array('files[]'=>'@'.$tmpfile);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$fast->server);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $filearray);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
curl_close ($ch);

$return = json_decode($result, true);

print_r($return);
echo $return[0]['url'] . PHP_EOL;

This will return an array, from this you can access to the download page:

echo $return[0]['url'];

An example of output:

Array
(
    [0] => Array
        (
            [name] => FOONS4eNq
            [hash] => 565aea34369244f52ab108c12f98300f
            [size] => 7276
            [type] => application/octet-stream
            [sid] => 
            [hashUpload] => 
            [md5] => .
            [sha] => .
            [user] => 
            [url] => http://www.multiup.org/download/565aea34369244f52ab108c12f98300f/FOONS4eNq
            [delete_url] => http://squeeze.multiup.org/upload/?file=FOONS4eNq
            [delete_type] => DELETE
        )

)

But this will not return the links of the mirrors, to get those you need an account and you have to use their Grabber utility:

I don't know if this works along with their API. If yes, then the response should return those links and from there you can use adf.ly and linkbucks APIs, I cannot test because I don't have an account in those services. Try to create it and if you have problems post your code here.

Docs:

cereal 1,524 Nearly a Senior Poster Featured Poster

So, in your pages you have:

/images/image.png

But you need to change everything to:

/public/images/*

And the same goes for css and js, correct? In this case you don't need mod_rewrite because this won't redirect the request to the correct path, you need mod_alias. There are different directives that you can use, for example Alias that rule works like this:

Alias /url/segment /directory/path

So, in your case you would use this setup:

Alias /images /public/images
Alias /css /public/css
Alias /js /public/js

Whenever you access to http://localhost/images/image.png the server will search the file inside /public/images/.

This solution does not work in .htaccess context, you can apply it at server config or virtual host config.

Otherwise you can use the Redirect directive, this can be applied in .htaccess context:

Redirect /images /public/images
Redirect /css /public/css
Redirect /js /public/js

As you see, the first parameter is the url segment, the second the real path. There are also RedirectMatch and RedirectPermanent, this last is used to send a 301 header status, that will inform spiders and browsers that the redirect is permanent.

The difference between Alias and Redirect directives is that the former will be transparent to the client, he won't see the real path, the latters instead will redirect the requests to the real path.

Documentation: http://httpd.apache.org/docs/2.2/mod/mod_alias.html

cereal 1,524 Nearly a Senior Poster Featured Poster

Good, if we are done, please mark the thread as solved. Bye! :)

cereal 1,524 Nearly a Senior Poster Featured Poster

It seems there's an extra space near the end of the filename, run the trim function against the $file variable: $file = trim($file); before populating the $sql variable.

cereal 1,524 Nearly a Senior Poster Featured Poster

Try with ls -lh it will return the sizes and some other information.

The uploaded file seems regular to me, it is a jpg, this is the output of the ImageMagick identify tool:

identify feb.jpg 
feb.jpg JPEG 1920x1080 1920x1080+0+0 8-bit DirectClass 332KB 0.000u 0:00.019

If you still get empty files in tmp directory, then try to change the $url as I suggested in my previous post, change also:

$path = 'tmp/';

to:

$path = $_SERVER['DOCUMENT_ROOT'].'/tmp/';

To be sure all the directories are correctly identified. When I first tried your code I got empty files too, but changing the $url I fixed that issue. I do not other ideas, sorry!

cereal 1,524 Nearly a Senior Poster Featured Poster

I think, most of the times, it is better to save the files to directories or to an external CDN (Content Delivery Network) because it is static data and the request can be executed without involving the PHP engine and MySQL server.

If you're not using a CDN service, you can set up few subdomains to multiply the downloads of the files: when you open a page the browser downloads only two images for each domain, so if you set four subdomains as:

  • img001.domain.tld
  • img002.domain.tld
  • img003.domain.tld
  • img004.domain.tld

Your website delivers up to 8 images at the same time. This can be done without involving Apache, PHP and MySQL, but using a load balancer with thttpd or directly the nginx server. You gain in performance.

Regarding the space occupied, it depends: if the database is in the same partition of the webserver, then it will occupy the same space as you save the file into a directory, there is almost no difference, maybe just few bytes more into the database.

If the database is external, then obviously the space will be occupied only for the time needed to upload the file and save it to the database, then it will use the disk space of the database server. But in this case you have to check some limitations about the size of the query you can perform: if I'm not wrong the default is about 1024 bytes, and needs to be pushed up if you want to insert or select …

cereal 1,524 Nearly a Senior Poster Featured Poster

You're welcome, I'm glad it works all fine.

can rename the phpmyadmin-4.0.4-all-languages without problem???

You can rename it without any problems.

in cpanel we have a option for protected directory to put user and password

Do it. Most scanners will try to find /phpmyadmin-* or strings like /pma, /mysql, /db or /database so if you can add an extra layer it won't hurt.

chrisschristou commented: help full thank so much friend +2
cereal 1,524 Nearly a Senior Poster Featured Poster

I don't have much experience on Mac, but I can suggest to perform few tests, the first is a php script to display the signature of the file:

<?php

$f = "./tmp/124file.jpg";
$fp = fopen($f, "r");
$r = fread($fp, 10);
fclose($fp);
echo substr(chunk_split(bin2hex($r), 2, ":"), 0, -1) . PHP_EOL;

If the first 3 bytes are ff:d8:ff:... then it's jpeg. You can run this on server and in the local machine to see if something is corrupting the files. You can also check with an hex editor or with the file command in the Mac OS terminal, the correct command should be this:

file -m mime-type 124file.jpg

Some applications do not use the same methods to determine the mime type, but with the above you should get a correct result.

Here's a list of signatures:

I can only think that some of these files were renamed to jpg and instead are png or gifs. Most browsers can recognize the correct mime and display the file correctly, but the operative systems can act differently.

Hope it helps.

cereal 1,524 Nearly a Senior Poster Featured Poster

I think this is what you're searching for:

But at this time it requires an approval by the FB team, it cannot be used by everyone.

cereal 1,524 Nearly a Senior Poster Featured Poster

Set the handler to curl_init() function, I did a test and by serving the file like this, the first part of the script worked fine:

$url = "file://{$_SERVER['DOCUMENT_ROOT']}/{$filename}";

Now it depends on the contents of $row['loc'], if you're already including the full path, then just add file:// or http:// if this is remote.

cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, sorry for previous suggestions about the Authentication method, I was a bit asleep and I confused the options :D

So, if you don't use the config mode, do not fill username and password fields.

For now use cookie or http modes. In both cases, you do not need to fill anything else in those forms, there are some extra options, but you can skip them for now. With these modes you will get a form to insert the database credentials.

The signon method is used to unify the login, for example: you have a login script to access the admin pages, through this method you can start a session that gives you access also to PHPMyAdmin (PMA). Check examples/signon.php to see a demo script, this expects that your login credentials matches with the MySQL account, but you could encrypt them into a table and extract them when you start the session... anyway, this is a bit tricky and if you don't have special requirements go straight to the cookie or http methods.

cereal 1,524 Nearly a Senior Poster Featured Poster

Good! Click on New Server then as:

  • Verbose name of this server: choose something of your choice, in my previous example, the name were local1 and local2, this is related only to PHPMyAdmin;
  • Server hostname: is the same hostname you use in your scripts to connect to the database, so it can be something like an IP, it can be localhost or a domain name as db001.oneandone.com;
  • Server port: the default listening port for MySQL servers is 3306, so you can leave it blank, if you have another setting then fill the field;
  • Server socket: this is a file in the filesystem, it's used when the database is in the same box of the web server, in practice the socket overrides the network layer and gives much speed between the server and the web application, I don't know if you can use it with your current hosting plan, I don't have experience with 1and1;
  • Use SSL: as the previous it depends on your configuration, if your plan provides SSL connection to the database then use it, otherwise leave it empty;
  • Connection type: is used to switch between TCP (given by hostname:port) and socket connections, you'll probably need TCP;
  • PHP extension to use: if your current version of PHP supports MySQLi then select it, the requirements are MySQL 4.3.1 and PHP 5.*, if you have doubts create a file with phpinfo() inside to check your PHP configuration;

After you've done with this form, go to the Authentication tab …

cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, alternative solutions:

  • install on local, and create the config file, then upload it to the server;
  • manually create config.inc.php, I've created two generic connections.

Here's the template:

<?php
/*
 *  Generated configuration file
 *  Generated by: phpMyAdmin 4.1.0 setup script
 *  Date: Sat, 14 Dec 2013 22:12:01 +0100
 */

/* Servers configuration */
$i = 0;

/* Server: local1 [1] */
$i++;
$cfg['Servers'][$i]['verbose'] = 'local1';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['port'] = '';
$cfg['Servers'][$i]['socket'] = '';
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['extension'] = 'mysqli';
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = 'root';

/* Server: local2 [2] */
$i++;
$cfg['Servers'][$i]['verbose'] = 'local2';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['port'] = '';
$cfg['Servers'][$i]['socket'] = '';
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['extension'] = 'mysqli';
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = 'root';

/* End of servers configuration */

$cfg['blowfish_secret'] = 'place a very random string here'; # change this
$cfg['DefaultLang'] = 'en';
$cfg['ServerDefault'] = 1;
$cfg['UploadDir'] = '';
$cfg['SaveDir'] = '';
?>

Set your connections, upload it to /phpMyAdmin-4.0.4-all-languages/ and then remove setup and config directories. For more options check the PHPMyAdmin documentation linked in one of the previous posts.

cereal 1,524 Nearly a Senior Poster Featured Poster

it folder when you say directory??? right???

Yes :) Folder is the name of the graphical representation (the icon) of the directory. You can try with 777, but this is not the best setting, so: check if with 777 the error message disappears, then setup PHPMyAdmin, check if it works fine and then try to set config permissions back to 644.

Hope it works, I don't have other ideas.

cereal 1,524 Nearly a Senior Poster Featured Poster

I would go reverse: a table for students, another for professors, a single language table and then a language_skills table for students and another for professors. For example:

create table students(
    id int unsigned not null auto_increment primary key,
    fname varchar(100),
    ...
)

create table student_language_skills(
    student_id int unsigned not null primary key,
    language_id tinyint unsigned not null,
    writing tinyint not null default 0,
    reading tinyint not null default 0,
    speaking tinyint not null default 0,
    listening tinyint not null default 0,
    ...
)

create table languages(
    id tinyint unsigned not null auto_increment primary key,
    name varchar(100) not null,
    ...
)

create table professors(
    id int unsigned not null auto_increment primary key,
    fname varchar(100),
    ...
)

create table professor_language_skills(
    professor_id int unsigned not null primary key,
    language_id tinyint unsigned not null,
    writing tinyint not null default 0,
    reading tinyint not null default 0,
    speaking tinyint not null default 0,
    listening tinyint not null default 0,
    ...
)

An example:

Then you could also use UNION to create a single result set.

cereal 1,524 Nearly a Senior Poster Featured Poster

I think one of the problems is given by:

MID(tgl_periksa,6,2)='$dataBulan'

Because $dataBulan is set like this:

$dataBulan = isset($_POST['cmbBulan']) ? $_POST['cmbBulan'] : date('m');

And the select tag cmbBulan sets a number as value, not a string:

echo "<option value='$bulanke' $cek>$bulannm</option>";

And so $dataBulan will always be a number, not a string. Now if you echo date('m') you receive 12 and if you perform mid():

> select mid(12, 6, 2);
+---------------+
| mid(12, 6, 2) |
+---------------+
|               |
+---------------+
1 row in set (0.00 sec)

You get an empty string, for this reason the query at line 108 will return an empty set. What kind of values do you have in tgl_periksa column: strings, integers, datetime?

cereal 1,524 Nearly a Senior Poster Featured Poster

i contacted 1and1 support they told me it is not possible

Ok, it means the database server accepts connections only from allowed IP, as your server IP, so it won't work from your PC.

Regarding 755 and 644 these are system permissions, 644 equals to read + write for the user that runs Apache (usually named www-data) and ownes the files in the server, if this does not work try with 755 that equals to read + write + execute.

If you're using Filezilla or another FTP client, right click the config folder and choose File Permissions, from there you can set the correct setting. Otherwise check the help center, I've found this:

It may be useful.

cereal 1,524 Nearly a Senior Poster Featured Poster

Use select:

<select name="action">
    <option>update</option>
    <option>delete</option>
</select>

Then:

if($_POST['action'] == 'update')
{
    # run update query
}

elseif($_POST['action'] == 'delete')
{
    # run delete query
}

else
{
    # return error: no allowed action was selected
}

If, instead, you want to update and delete within the same request then paste your script and give us more information.

cereal 1,524 Nearly a Senior Poster Featured Poster

Also, you could try with insert ... select ... on duplicate key, an example query:

insert into table1 (user, score) values(1,2);

insert into table2 (user, total_score) select user, score from table1 where id = last_insert_id() on duplicate key update total_score = total_score + score;

The conditions are:

  • you cannot use group by on the select segment
  • you need an auto increment key in table1 to get the last_insert_id()
  • you cannot perform multiple inserts into table1 like this:

    insert into table1 (user, score) values(1,7), (1,3), (1,4);

because last_insert_id() will refer only to the first of these and the second query will continue to add 7.

An example: http://sqlfiddle.com/#!2/7e6e58/1

Ref. http://dev.mysql.com/doc/refman/5.5/en/insert-select.html

cereal 1,524 Nearly a Senior Poster Featured Poster

Can you avoid running phpmyadmin from accessible docroot? It may be better to run from cPanel/Plesk only.

Chris in addition to diafol's suggestion, if you can connect to the database from your localhost installation (XAAMP or WAMP), then install PHPMyAdmin in your computer, so you can manage it without exposing your web space.

cereal 1,524 Nearly a Senior Poster Featured Poster

Follow these steps:

  • delete config.inc.php file;
  • under www.myadomainname.com/phpMyAdmin-4.0.4-all-languages/ create the directory config;
  • change permissions of this new directory to 644 or, if it does not work, to 755;
  • then reload the setup page, the red message will disappear, after that just click on Add new server to insert the credentials to your databases.

Once you have finished remove the setup directory, otherwise anyone can browse there and change the settings.

cereal 1,524 Nearly a Senior Poster Featured Poster

Show the code of this page if you want, we can suggest you what to fix.

In general the rule is: whenever the script receives data from $_POST, $_GET, $_REQUEST, $_COOKIE or any external source (as a file), then filter and validate it.

Additional documentation: http://php.net/filter

cereal 1,524 Nearly a Senior Poster Featured Poster

Also, browse to the setup directory, you can use the wizard:

www.myadomainname.com/phpMyAdmin-4.0.4-all-languages/setup/

Before doing this, I suggest to change the name of phpMyAdmin-4.0.4-all-languages to something less predictable and searchable by the web spiders. Other information here:

cereal 1,524 Nearly a Senior Poster Featured Poster

Standing at their Help Center, PHPMyAdmin is already available from your control panel:

cereal 1,524 Nearly a Senior Poster Featured Poster

In both cases it means that the application does not filter the data received from the clients, and so an attacher can enter additional statements to the query, for example, you receive a GET request on this link:

and the script does not filter:

$id = $_GET['id'];

$query = "delete from articles where id = $id";

now, imagine if the attacker enters something like this:

?id=17 and id between 1 and 1000&action=delete

It will delete 1000 articles. To mitigate these problems you should use prepared statements and sanitize all data received by the clients. If you're using the MySQL library consider to switch to PDO:

For more information about that kind of attack check this article:

cereal 1,524 Nearly a Senior Poster Featured Poster

I agree, IMO urtrivedi's suggestion is the only pratical solution.

Otherwise, if you can use MariaDB in the local installation, you could use the Connect storage engine, this enables you to create connections with remote sources, as concept it's similar to the federated engine: