cereal 1,524 Nearly a Senior Poster Featured Poster

Check the settings of /etc/apache2/sites-available/default or in apache2.conf and adjust the DocumentRoot to your desired path, then reload apache.

cereal 1,524 Nearly a Senior Poster Featured Poster

Check the ownership and the permissions of the script, by writing the file into /var/www/ you probably used sudo, correct? That gave root:root to the script. Apache needs access to read and execute the file, so you can switch the group to www-data:

sudo chown root:www-data script.php

Then, if your user is part of the www-data group, you can change the permission to allow your edits without using sudo:

sudo chmod 775 script.php

The above is valid for development in localhost, not for production, in that case the rules must be more restrictive.

cereal 1,524 Nearly a Senior Poster Featured Poster

Add errorInfo() as suggested in my first post. From there you can see why the query fails.

cereal 1,524 Nearly a Senior Poster Featured Poster

@pritaeas
Whoops, I didn't saw your reply!

With Gmail you can use AUTH LOGIN, but you need an application-specific password before you can go further, read this:

Then generate the password from here:

And then embed this password in your script, as example:

<?php

    require './PHPMailerAutoload.php';

    $mail = new PHPMailer;

    $mail->isSMTP();
    $mail->SMTPDebug = 2;
    $mail->SMTPAuth = TRUE;
    $mail->Host     = 'ssl://smtp.gmail.com:465;tls://smtp.gmail.com:587';
    $mail->Username = '*******@gmail.com';
    $mail->Password = '*******';

    $mail->From = '*******@gmail.com'; # it must be the username
    $mail->FromName = 'Your Name';
    $mail->WordWrap = 50;

    # to
    $mail->addAddress('*******@domain.tld', 'Name and Surname');

    $mail->Subject  = 'Test';
    $mail->Body     = 'Hello World';

    echo ! $mail->send() ? 'Error: ' . $mail->ErrorInfo : 'Success!';

More information about Gmail SMTP here:

pritaeas commented: Thanks. Don't use it often enough to know it has changed. +14
cereal 1,524 Nearly a Senior Poster Featured Poster

Whenever someone sends an email to my websites email address it is piped to a PHP script

Ok, but I hope I can make you understand that when an email message is received by your website, in practice is received by the mail server associated with your domain name.

This does not involve the web server (Apache for example) and neither the PHP engine. So you cannot redirect directly what is received by the mail server to a PHP script.

You can only access the email account and parse the received messages.

Imap, if supported by your mail server, is a protocol that allows to easily access email accounts, otherwise you can use POP3, which is supported also by the Fetch library suggested in the previous post, as example of connection, it could start with two or three arguments:

# for imap
$server = \Fetch\Server('imap.domain.tld', 993);

# for pop3
$server = \Fetch\Server('pop3.domain.tld', 995, 'pop3');

By default the third argument is imap so it can be avoided in the first example. It is just like a connection string to a database. The second argument is the port, and the first is the server path.

If, for example, you want to parse the mails from your GMail account you would do:

<?php

    require './autoload.php';

    $server = new \Fetch\Server('pop.gmail.com', 995, 'pop3');
    $server->setFlag('novalidate-cert');
    $server->setFlag('ssl');

    # set username and password
    $server->setAuthentication('*****@gmail.com', '*******');

    # get 3 messages
    $messages = $server->getMessages(3);

    foreach ($messages as $message)
    {
        echo "Subject: " . $message->getSubject() . PHP_EOL;
        echo …
cereal 1,524 Nearly a Senior Poster Featured Poster

Maybe I didn't understood your initial request: you have a form to send an email, let's say with the mail() function, and you want also to save the input to the database, correct? Or you want to access the inbox of an email account to read the headers and the body of the received messages?

cereal 1,524 Nearly a Senior Poster Featured Poster

In addition, as example you can try imap_rfc822_parse_headers():

<?php

    $header = file_get_contents('email.txt');
    $obj = imap_rfc822_parse_headers($header);

    echo "<pre>";
    print_r($obj);
    echo "</pre>";

Where email.txt is:

Received: from outmail4.bc.edu (136.167.2.48) by BFRANKLIN04.bc.edu
 (192.168.1.34) with Microsoft SMTP Server id 14.2.347.0; Thu, 9 Jan 2014
 09:52:28 -0500
Received: from o1.outreach.nercomp.org (o1.outreach.nercomp.org
 [192.254.118.91])    by krait.bc.edu (8.14.5/8.14.5) with SMTP id s09EqQix012162
    for <bc.person@bc.edu>; Thu, 9 Jan 2014 09:52:27 -0500
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=outreach.nercomp.org;
    h=to:subject:mime-version:from:content-type:content-transfer-encoding;
    s=smtpapi; bh=DvaYBQwmkNJzfT2Ef9kY09h415E=; b=Kg0JHzVv4X8KksSDVc
    0odRBz3RwI7oT1LxX1msR92Z1ilwpcUzGxMA/2Xu74RhzSraWJsjVipE2yuQ1TiM
    lljqwwxRgxTTYxMID3kV1Ql82k/e/G+iYwb+c9VB+43D7u51IYJR9ly/iKS6Pkur
    Cnk1SQEa1esHGuZTTe2yLSb3s=
Received: by mf253.sendgrid.net with SMTP id mf253.19201.52CEB7AA5        Thu,
 09 Jan 2014 14:52:26 +0000 (UTC)
Received: from prod3.jjcbigideas.com (unknown [209.15.240.195])    by mi24 (SG)
 with ESMTP id 143777d7221.2da7.f27c    for <bc.person@bc.edu>; Thu, 09
 Jan 2014 08:52:26 -0600 (CST)
Received: from nercomp by prod3.jjcbigideas.com with local (Exim 4.82)
    (envelope-from <nercomp@nercomp.org>)    id 1W1GyA-0008Uc-2Q    for
 bc.person@bc.edu; Thu, 09 Jan 2014 08:52:26 -0600
To: <bc.person@bc.edu>
Subject: NERCOMP - Security Training and Risk Assessment - Feb 10
MIME-Version: 1.0
From: <events@nercomp.org>
Content-Type: text/html; charset="ISO-8859-1"
Content-Transfer-Encoding: quoted-printable
Message-ID: <E1W1GyA-0008Uc-2Q@prod3.jjcbigideas.com>
Date: Thu, 9 Jan 2014 08:52:26 -0600
Return-Path:
 bounces+836485-6dca-bc.person=bc.edu@outreach.nercomp.org

The example header will return an object array:

stdClass Object
(
    [date] => Thu, 9 Jan 2014 08:52:26 -0600
    [Date] => Thu, 9 Jan 2014 08:52:26 -0600
    [subject] => NERCOMP - Security Training and Risk Assessment - Feb 10
    [Subject] => NERCOMP - Security Training and Risk Assessment - Feb 10
    [message_id] => 
    [toaddress] => bc.person@bc.edu
    [to] => Array
        (
            [0] => stdClass Object
                (
                    [mailbox] => bc.person
                    [host] => bc.edu
                )

        )

    [fromaddress] => events@nercomp.org
    [from] => Array
        (
            [0] => stdClass Object
                ( …
cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, the last part of the log explains the problem:

2014-08-24 17:28:33 CLIENT -> SERVER: AUTH NTLM TlRMTVNTUAABAAAABzIAAAAAAAAgAAAAAAAAACAAAAA=
2014-08-24 17:28:38 SMTP -> get_lines(): $data was ""
2014-08-24 17:28:38 SMTP -> get_lines(): $str is "504 5.7.4 Unrecognized authentication type "
2014-08-24 17:28:38 SMTP -> get_lines(): $data is "504 5.7.4 Unrecognized authentication type "
2014-08-24 17:28:38 SERVER -> CLIENT: 504 5.7.4 Unrecognized authentication type
2014-08-24 17:28:38 SMTP ERROR: AUTH NTLM command failed: 504 5.7.4 Unrecognized authentication type
2014-08-24 17:28:38 CLIENT -> SERVER: QUIT
2014-08-24 17:28:38 SMTP -> get_lines(): $data was ""
2014-08-24 17:28:38 SMTP -> get_lines(): $str is "221 2.0.0 Service closing transmission channel "
2014-08-24 17:28:38 SMTP -> get_lines(): $data is "221 2.0.0 Service closing transmission channel "
2014-08-24 17:28:38 SERVER -> CLIENT: 221 2.0.0 Service closing transmission channel
2014-08-24 17:28:38 Connection: closed
2014-08-24 17:28:38 SMTP connect() failed.

The authentication failed because it doesn't recognize the type. The error is defined by the number, which is 504. In one of your previous posts you wrote that you got errors also from the others authentication methods, but these where of the same type or the error code was different?

Anyway to be sure, you must check the documentation of your mail server or ask to the admin.

cereal 1,524 Nearly a Senior Poster Featured Poster

Set:

$mail->SMTPDebug = 4;

It should return a verbose output of the telnet session. If it does not help you to find the error, paste the result here. By the way, you can remove this line:

ini_set("SMTP", "smtp.indonusa.net.id");

It does not affect PHPMailer.

cereal 1,524 Nearly a Senior Poster Featured Poster

But, it generates error.

Which error?

It could be the definition of the columns, for example userrole.userid here is BIGINT but in users.id is INT, the same applies to the other constraint. Then the constraint label must be unique over the database, so if you have another constraint fk_userid into another table, you have to change it.

For more information check the documentation:

cereal 1,524 Nearly a Senior Poster Featured Poster

Hi, show an html output of the page, not the PHP source, and the contents of print.css. By the way this:

<link href="print.css" rel="stylesheet">

Should be referenced as print:

<link href="print.css" rel="stylesheet" media="print" />

Unless you're using @media print inside the style.

cereal 1,524 Nearly a Senior Poster Featured Poster

Include the extras directory into phpmailer/. That solves the require_once error. Then retry.

ok, then which authentication type should I use?

If in doubt ask to the mail server admin.

cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, this is a problem:

2014-08-21 22:38:07 CLIENT -> SERVER: AUTH LOGIN
2014-08-21 22:38:12 SERVER -> CLIENT: 504 5.7.4 Unrecognized authentication type

You send AUTH LOGIN as authentication type, but there are different methods supported by PHPMailer (line 311 & 274):

PLAIN, LOGIN, NTLM, CRAM-MD5

That can be set by the AuthType property, for example:

$mail->AuthType = 'NTLM';

The default value is LOGIN, check the documentation about your SMTP server.

cereal 1,524 Nearly a Senior Poster Featured Poster

@almostbob

Usually the hosts are 'smtp.server.com' the protocol is taken care of by other declarations, what the instructions say you can and what best practice says you should are way different

You can jump off a 1000 foot cliff, but you probably shouldn't, and you cant do it twice.

Hi, you are correct, but the value refers to the socket opened by the library, which allows the above syntax.

At the end the connection will be executed by line 1332:

if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options))

This is the linked documentation:

/**
 * SMTP hosts.
 * Either a single hostname or multiple semicolon-delimited hostnames.
 * You can also specify a different port
 * for each host by using this format: [hostname:port]
 * (e.g. "smtp1.example.com:25;smtp2.example.com").
 * You can also specify encryption type, for example:
 * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
 * Hosts will be tried in order.
 * @type string
 */
public $Host = 'localhost';

Link:

Then check:

Which is where the string is verified. By using the above you override the default settings.

Maybe I'm wrong, but I think the issue here is given by the port number for the ssl connection. Bye!

cereal 1,524 Nearly a Senior Poster Featured Poster

@Borzoi

at first I thought the same, but it is not correct, check the comments in the source code:

The $mail->Host can be expressed in different ways, even multiple fallback smtp servers:

smtp.domain.tld:25
ssl://smtp.domain.tld:25
ssl://smtp1.domain.tld:465,smtp2.domain.tld:25
cereal 1,524 Nearly a Senior Poster Featured Poster

It's probably generated by:

$mail->Host = "ssl://smtp.indonusa.net.id";

does ssl listen on port 25?

cereal 1,524 Nearly a Senior Poster Featured Poster

Do you have class.smtp.php into the phpmailer directory?

cereal 1,524 Nearly a Senior Poster Featured Poster

Yes, it happens because you are linking directly to the phpmailer class, you have to require the autoload, so instead of:

require_once("phpmailer/class.phpmailer.php");

Do:

require $_SERVER['DOCUMENT_ROOT'] . '/phpmailer/PHPMailerAutoload.php';

AS written in the documentation:

PHPMailer provides an SPL-compatible autoloader, and that is the preferred way of loading the library - just require '/path/to/PHPMailerAutoload.php'; and everything should work.

cereal 1,524 Nearly a Senior Poster Featured Poster

It seems the encoding of your editor change it to UTF8, and replace ‘ and ’ with double quotes.

cereal 1,524 Nearly a Senior Poster Featured Poster

That syntax would not work with the mail() function. By using PHPMailer or SwiftMailer, then you can set username and password as it was suggested to you.

Otherwise you can use fsockopen() as in this example:

And:

Check the error log of the mail server application.

cereal 1,524 Nearly a Senior Poster Featured Poster

Check the error log of the mail server application. If the mail is not sent or it is rejected the log should have a trace of it.

cereal 1,524 Nearly a Senior Poster Featured Poster

Yes, it is possible, follow these instructions:

Download the installer from: http://php.net/downloads.php

cereal 1,524 Nearly a Senior Poster Featured Poster

Are you sure smtp2 exists? And which mail server is configured under this domain? Xampp doesn't provide a mail server. Also check the DNS records or your domain, I see:

> dig indonusa.net.id ANY

; <<>> DiG 9.8.1-P1 <<>> indonusa.net.id ANY
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10614
;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;indonusa.net.id.       IN  ANY

;; ANSWER SECTION:
indonusa.net.id.    21595   IN  MX  20 mx2.idcloud.biz.
indonusa.net.id.    21595   IN  MX  30 mx3.idcloud.biz.
indonusa.net.id.    21595   IN  MX  10 mx1.idcloud.biz.
indonusa.net.id.    3595    IN  NS  ns1.indonusa.net.id.
indonusa.net.id.    3595    IN  NS  ns2.indonusa.net.id.
indonusa.net.id.    21595   IN  TXT "v=spf1 a mx ptr=all"
indonusa.net.id.    3595    IN  A   202.93.143.59
indonusa.net.id.    3595    IN  SOA ns2.indonusa.net.id. admin.indonusa.net.id. 2014070603 7200 540 604800 86400

;; Query time: 61 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Aug 15 12:03:50 2014
;; MSG SIZE  rcvd: 230

so it seems that your mail servers are mx[1,2,3].idcloud.biz, try to connect to number 3:

telnet mx3.idcloud.biz:25

If it works, then try to configure PHP to connect directly with this server.

cereal 1,524 Nearly a Senior Poster Featured Poster

Also, if you still want one query to return them all, you could use union in a subquery:

select id, email, tablename from (select u.id, u.email, 'users' as tablename from users as u union select c.id, c.email, 'contacts' as tablename from contacts as c) as sub group by email;

It will return something like this:

+----+-------------------+-----------+
| id | email             | tablename |
+----+-------------------+-----------+
|  2 | contact2@site.tld | contacts  |
|  3 | random3@site.tld  | contacts  |
|  1 | user1@site.tld    | users     |
|  2 | user2@site.tld    | users     |
|  3 | user3@site.tld    | users     |
+----+-------------------+-----------+
5 rows in set (0.00 sec)

Avoiding duplicates between the two tables, and in case one of the two is deleted, the following query will display the result from the other table, so you don't have to keep track of changes:

delete from users where id = 1;

select id, email, tablename from (select u.id, u.email, 'users' as tablename from users as u union select c.id, c.email, 'contacts' as tablename from contacts as c) as sub group by email;

+----+-------------------+-----------+
| id | email             | tablename |
+----+-------------------+-----------+
|  2 | contact2@site.tld | contacts  |
|  3 | random3@site.tld  | contacts  |
|  1 | user1@site.tld    | contacts  | <- note the difference
|  2 | user2@site.tld    | users     |
|  3 | user3@site.tld    | users     |
+----+-------------------+-----------+
5 rows in set (0.00 sec)

Live example: http://sqlfiddle.com/#!9/c8c13/2

But I'm not sure this …

cereal 1,524 Nearly a Senior Poster Featured Poster

I'm glad it works fine. You can return the price list as an index => value array, for example:

$prices = array(
    '.com'  => '9.99',
    '.info' => '5.99',
    ...
);

so you can match them into the loop:

foreach($_POST['tld'] as $tld)
{
    $price = money_format('%n', $prices[$tld]);

Note, here I'm using the money_format() function, this requires setlocale(LC_MONETARY, 'en_US.UTF-8'); on the top of the script:

The full script now look like this:

<?php

    setlocale(LC_MONETARY, 'en_US.UTF-8');

    if (!empty($_POST['domain_name']) && !empty($_POST['tld'])){

        # get price list
        $prices = require './generate_prices.php';

        $domain_name = filter_var(trim($_POST['domain_name']), FILTER_SANITIZE_STRING, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
        $responses = array();
        $msg = '';

        foreach($_POST['tld'] as $tld)
        {
            # format the price
            $price  = money_format('%n', $prices[$tld]);
            $url    = filter_var('http://'.$domain_name, FILTER_VALIDATE_URL);

            # stop the loop
            if($url === false)
            {
                $msg .= '<h2>Domain is not valid</h2>';
                break;
            }

            switch($tld)
            {
                # white list
                case '.ac.id':
                case '.biz':
                case '.cc':
                case '.cn':
                case '.co.id':
                case '.co.in':
                case '.com':
                case '.go.id':
                case '.in':
                case '.info':
                case '.mil.id':
                case '.mobi':
                case '.net':
                case '.or.id':
                case '.org':
                case '.pk':
                case '.sch.id':
                case '.tv':
                case '.web.id':
                case '.ws':

                    $domain = $domain_name . $tld;
                    $dns = @dns_get_record($domain, DNS_ALL);

                    # available
                    if(count($dns) == 0) $msg .= "<h2 style='color:green;' >Domain $domain is available for: $price</h2>";

                    # error
                    elseif($dns === false) $msg .= "<h2 style='color:green;' >Error on domain $domain.</h2>";

                    # not available
                    else
                    {
                        $msg .= "<h2 style='color:red;'>Domain <a href='$url'>$domain</a> has taken.</h2>";
                        $responses[$domain] = $dns;
                    }

                    break;
            }
        }
    }
    else if (empty($_POST['domain_name'])) {
        $msg = "<h2 style='color:red;'>Error: Domain name can not be …
cereal 1,524 Nearly a Senior Poster Featured Poster

In the last line there's a missing semi-column:

if(isset($_POST['domain_name'])) echo $msg;

A part that, your code seems fine. Here's a live example:

Just click run for testing.

ultmt.punisher commented: Really helpfull +2
cereal 1,524 Nearly a Senior Poster Featured Poster

Yep, it works fine for me. Change your IF statement:

if (!empty($_POST['domain_name']) && !empty($_POST['suffix'])){

To:

if (!empty($_POST['domain_name']) && !empty($_POST['tld'])){
cereal 1,524 Nearly a Senior Poster Featured Poster

Change your select tag with this:

<select name="tld[]" id="suffix">

Then to avoid duplicates between the selected value and the checkboxes, you can add array_unique() right before the loop:

$_POST['tld'] = array_unique($_POST['tld']);
foreach($_POST['tld'] as $tld)
{

Othwerwise, if you choose, for example, .info from both the input fields the script will receive:

Array
(
    [domain_name] => test
    [tld] => Array
        (
            [0] => .info <- duplicate
            [1] => .org
            [2] => .net
            [3] => .info <- duplicate
        )

    [submit] => submit
)

Bye!

cereal 1,524 Nearly a Senior Poster Featured Poster

Hi,

you can try to generate an array from the checkboxes, change them like this:

<input type="checkbox" id="_org" name="tld[]" value=".org">
<label for="_org">.org</label>

Note that the id attribute of the input tag matches the label for attribute, that way the label becomes clickable, while the name attribute is the array: tld[].

The full example form is this:

<form method="post" action="">
    <input type="text" name="domain_name" />
    <table>
        <tr>
            <td colspan="2">
                <input type="checkbox" id="_org" name="tld[]" value=".org">
                <label for="_org">.org</label>
            </td>
            <td colspan="2">
                <input type="checkbox" id="_net" name="tld[]" value=".net">
                <label for="_net">.net</label>
            </td>
            <td colspan="2">
                <input type="checkbox" id="_biz" name="tld[]" value=".biz">
                <label for="_biz">.biz</label>
            </td>
            <td colspan="2">
                <input type="checkbox" id="_ws" name="tld[]" value=".ws">
                <label for="_ws">.ws</label>
            </td>
            <td colspan="2">
                <input type="checkbox" id="_mobi" name="tld[]" value=".mobi">
                <label for="_mobi">.mobi</label>
            </td>
            <td colspan="2">
                <input type="checkbox" id="_info" name="tld[]" value=".info">
                <label for="_info">.info</label>
            </td>
        </tr>
    </table>
    <input type="submit" name="submit" value="submit" />
</form>

When sending a request it will look like this:

Array
(
    [domain_name] => test
    [tld] => Array
        (
            [0] => .org
            [1] => .net
            [2] => .info
        )

    [submit] => submit
)

Now it's easy to loop the top level domains (tld). In the script you have to use a white-list approach, to avoid arbitrary values, so the script becomes:

$domain_name = trim($_POST['domain_name']);
$responses = array();
$msg = '';

foreach($_POST['tld'] as $tld)
{
    switch($tld)
    {
        # white list
        case '.org':
        case '.net':
        case '.biz':
        case '.ws':
        case '.mobi':
        case '.info':

            $domain = $domain_name . $tld;
            $dns = dns_get_record($domain, DNS_ALL);

            # available
            if(count($dns) == 0) $msg .= "<h2 style='color:green;' >Domain $domain is available.</h2>";

            # error …
cereal 1,524 Nearly a Senior Poster Featured Poster

You could use db2_fetch_row() and db2_result(), check the first example in the documentation:

But instead of the loop, that moves the internal pointer to the next row, you can use an IF statement and get only the first row:

if(db2_fetch_row($result4))
{
    $number   = db2_result($result4, 0);
    $alphanum = db2_result($result4, 1);
}

# moving to the second row
db2_next_result($result4);

# repeat the previous IF statement
cereal 1,524 Nearly a Senior Poster Featured Poster

Hi,

you have to set the namespace that defines slash, so:

<?php

$feed = file_get_contents("http://www.trenologi.com/feed/");
$xml = new SimpleXmlElement($feed);
$xml->registerXPathNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');

$result = $xml->xpath('//slash:comments');

foreach($result as $pcount)
{
    echo $pcount;
}

Documentation:

cereal 1,524 Nearly a Senior Poster Featured Poster

I made a mistake in my previous post, this:

if ($_Session['roleID'] == 1)

Should be:

if ($_SESSION['roleID'] == 1)

Uppercase! About this: Parse error: syntax error, unexpected 'if' (T_IF) in... read the full error code. It can happen because of a missing ;, for example:

<?php

echo 'hello'

if(1 == 1) echo ' world';

Will return: Parse error: syntax error, unexpected T_IF, expecting ',' or ';' in .... So check if the code in the config file is correct.

If you want to check the session status just try this in a test page:

<?php

    session_start();

    echo "<pre>";
    print_r($_SESSION);
    echo "</pre>";

It will return all the values saved in the current session.

cereal 1,524 Nearly a Senior Poster Featured Poster

The variable session must be always uppercase, so $_Session is not correct, change it to $_SESSION:

$_SESSION['roleID']

The session_start(); is included in the config file?

Also, in the IF statement you have to compare, not assign a value, so this:

if ($_Session['roleID']=1)

Becomes:

if ($_Session['roleID'] == 1)

When you're testing booleans, instead, use === as explained here:

Apply the same to the ELSEIF statement.

cereal 1,524 Nearly a Senior Poster Featured Poster

Hi, you could use the explode() function:

$data = array();

foreach($input as $key => $value)
{
    $id = explode('-', $key);
    if(array_key_exists(1, $id)) $data[$id[1]][$key] = $value;
}

print_r($data);

The array_key_exists() is used to avoid errors when processing other keys as $_POST['submit'], which doesn't have a dash character and that, otherwise, would create a notice: Notice: Undefined offset: 1 ...

cereal 1,524 Nearly a Senior Poster Featured Poster

In addition: you have two <body> tags.

And if you add event.preventDefault() to your links, the page will not move to the top each time you click:

$('a.control_prev').click(function () {
    event.preventDefault();
    moveLeft();
});
$('a.control_next').click(function () {
    event.preventDefault();
    moveRight();
});
cereal 1,524 Nearly a Senior Poster Featured Poster

Hi, it seems the problem is given the <a> tag on line 7:

<li>
    <a href="http://this-node.net/">
        <img src="http://this-node.net/This-NodeLogo.ico">

</li>

It is not closed, fix it and it should work. Here's the test on jsfiddle: http://jsfiddle.net/v5vas/1/

Bye!

cereal 1,524 Nearly a Senior Poster Featured Poster

Hi, this happens in Javascript and PHP when using float numbers, to avoid this problem you can use the BC Math library:

echo bcdiv(bcmul(47.60, 554.82), 100, 2);

Which returns 264.09, the third argument of bcdiv() is rounding to the second decimal. If you want 264 then remove the third argument:

echo bcdiv(bcmul(47.60, 554.82), 100);

For more information check this thread:

About BC Math: http://php.net/manual/en/intro.bc.php
In alternative consider also the GMP library: http://php.net/manual/en/intro.gmp.php

cereal 1,524 Nearly a Senior Poster Featured Poster

Hi, check the name index:

$_FILES['datafile']['name']

Below you can read the full array structure returned by $_FILES:

ultmt.punisher commented: thanks for the help :) +1
cereal 1,524 Nearly a Senior Poster Featured Poster

Hello,

first, are you sure your script can access the link? Because from the browser, it displays fine, but from script it returns error 503, that's due to a restriction. I had to set a user agent through a stream context to the file_get_contents():

// Create a stream
$opts = array(
        'http' => array(
            'method' => "GET",
            'header' => "Accept-language: en\r\n" .
            "User-Agent: Mozilla/5.0 (X11; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0\r\n"
        )
    );

$context = stream_context_create($opts);

$feed = file_get_contents("http://tipsorangsukses.blogspot.com/atom.xml", false, $context);

Now, the loop:

$xml = new SimpleXmlElement($feed);

foreach($xml->entry as $entry)
{
    print_r($entry);
    break;
}

If you use print_r($entry), and break;, you can see how the first entry is returned:

SimpleXMLElement Object
(
    [id] => tag:blogger.com,1999:blog-7538664413577532945.post-6420470017556836335
    [published] => 2013-05-29T07:59:00.001+08:00
    [updated] => 2013-05-29T07:59:19.588+08:00
    [category] => SimpleXMLElement Object
        (
            [@attributes] => Array
                (
                    [scheme] => http://www.blogger.com/atom/ns#
                    [term] => Bisnis
                )

        )

    [title] => Tips Membeli Emas Batangan
    [summary] => 


Emas batangan merupakan salah satu investasi cerdas dan prestisius mengingat kadar kemurniannya yang mencapai 24 karat dan sejak dahulu telah menjadi investasi bagi kalangan masyarakat menengah ke atas. Meskipun begitu, di masa ini telah banyak peluang untuk memiliki emas batangan sebagai investasi bagi masyarakat kalangan menengah ke bawah dari berat minimum 5 gram emas hingga kelipatannya 
    [link] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [rel] => edit
                            [type] => application/atom+xml
                            [href] => http://www.blogger.com/feeds/7538664413577532945/posts/default/6420470017556836335
                        )

                )

            [1] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [rel] => self
                            [type] => application/atom+xml
                            [href] …
cereal 1,524 Nearly a Senior Poster Featured Poster

If you're sure the first line is always an header then you can skip it:

$i = 0;
while()
{
    # skip condition
    if($i == 0) continue;

    # other code ...

    $i++;
}

otherwise you can check if it matches with a previously hardcoded value, for example, here the first line is an header:

column_1, column_2, column_3, column_4, column_5
aaa1,     bbb1,     ccc1,     ddd1,     eee1
aaa2,     bbb2,     ccc2,     ddd2,     eee2
aaa3,     bbb3,     ccc3,     ddd3,     eee3

And the script:

# value to match
$check = 'column_1';

while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {

    $data = array_map('trim', $data);
    $data = array_map(function($row)
        {
            return filter_var($row, FILTER_SANITIZE_STRING, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
        }, $data);

    # if you match the value, then skip this loop
    if(in_array($check, $data)) continue;

    $import->bindParam(1, $data[0], PDO::PARAM_STR);
    $import->bindParam(2, $data[1], PDO::PARAM_STR);
    $import->bindParam(3, $data[2], PDO::PARAM_STR);
    $import->bindParam(4, $data[3], PDO::PARAM_STR);
    $import->bindParam(5, $data[4], PDO::PARAM_STR);
    $import->execute();
}

This will prevent the insert of repeated headers, in case of merged files.

cereal 1,524 Nearly a Senior Poster Featured Poster

The remote server needs to be reloaded otherwise it will not read the new settings in the php.ini file. Otherwise you can use ini_set():

<?php

    ini_set('upload_max_filesize', '20M');
    ini_set('memory_limit', '128MB');
    ini_set('max_execution_time', 180); # 3 minutes

By the way, do you get errors when you try with a big file? Have you checked the error log of the server?

cereal 1,524 Nearly a Senior Poster Featured Poster

Sounds like you've reached the size limit. Check the contents of $_FILES array by placing this at the top of your upload script:

die(print_r($_FILES));

Then check the value of the index key error, if you get 0 there's no errors, so you will may want to paste your code here. If instead the value is different, for example 2 then it's a size problem and in this case you have to change some settings in your php.ini file, like upload_max_filesize, which by default is 2MB. For more information read these links:

cereal 1,524 Nearly a Senior Poster Featured Poster

No PDO::PARAM_STR for example:

$import->bindParam(2, $data[0], PDO::PARAM_STR);

is a constant that will check only if the input is a string, instead of an integer, null or a boolean, but it doesn't remove HTML or Javascript.

Prepared statements are used to prevent SQL injections, but it does nothing to remove scripts, in your loop you can add filter_var() to sanitize the array, for example:

while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {

    # removing empty spaces
    $data = array_map('trim', $data);

    # remove tags and encode special characters
    $data = array_map(function($row){
        return filter_var($row, FILTER_SANITIZE_STRING, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    }, $data);

    $import->bindParam(1, $session, PDO::PARAM_INT);
    $import->bindParam(2, $data[0], PDO::PARAM_STR);
    $import->bindParam(3, $data[1], PDO::PARAM_STR);
    $import->bindParam(4, $data[2], PDO::PARAM_STR);
    $import->bindParam(5, $data[3], PDO::PARAM_STR);
    $import->bindParam(6, $data[4], PDO::PARAM_STR);
    $import->bindParam(7, $data[5], PDO::PARAM_STR);
    $import->bindParam(8, $data[6], PDO::PARAM_STR);
    $import->bindParam(9, $data[7], PDO::PARAM_STR);
    $import->bindParam(10, $data[8], PDO::PARAM_STR);
    $import->execute();
}

Docs:

cereal 1,524 Nearly a Senior Poster Featured Poster

Yes, that's the correct and safe method to avoid SQL injections, but you always need to sanitize data because some javascript could be submitted:

...
aaa4,bbb4,,ddd4,eee4
aaa5,<script>alert('hello');</script>,ccc5,ddd5,eee5
aaa6,bbb6,ccc6,ddd6,eee6
...

and when you load it into a page it will execute.

cereal 1,524 Nearly a Senior Poster Featured Poster

Hi, try to add errorInfo(), for example:

if (!$import) {
    echo "<p>Prepared statement error:</p>";
    echo "<pre>" .print_r($dbh->errorInfo(), true) . "</pre>";
}

while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
    $import->execute($data);
    echo "<p>Execute error:</p>";
    echo "<pre>" .print_r($import->errorInfo(), true) . "</pre>";
    break;
}

The break will stop the loop after the first execution. If there are no errors, then remove break and check the full file. It could be an extra column or a non null column receiving null or an empty value, for example:

aaa, bbb, , ddd, eee

Docs: http://php.net/manual/en/pdo.errorinfo.php

cereal 1,524 Nearly a Senior Poster Featured Poster

Try with appendImages(), like in this example:

<?php

$list = array(
    './i/001.jpg',
    './i/002.jpg',
    './i/003.jpg',
    './i/004.jpg'
    );

# first image to start Imagick()
$im = new Imagick($list[0]);
$ilist = array();

# loop the others
for($i = 1; $i < count($list); $i++)
{
    $ilist[$i] = new Imagick($list[$i]);
    $im->addImage($ilist[$i]);
}

$im->resetIterator();
$combined = $im->appendImages(false);
$combined->setImageFormat("png");
header('Content-Type: image/png');
echo $combined;

To create the list you can use glob() instead of an hardcoded array:

$list = glob('./i/*.jpg');

Docs: http://php.net/manual/en/imagick.appendimages.php

Bye!

cereal 1,524 Nearly a Senior Poster Featured Poster

The salt is just an extra string used to change the output of the hash function, you can store this as a plain text string, or you can use an encrypt function like AES_ENCRYPT() in MySQL, example:

-- encrypt the salt
select HEX(AES_ENCRYPT('salt', 'encrypt key')) as encrypted_salt;
+----------------------------------+
| encrypted_salt                   |
+----------------------------------+
| CCBD9EDD8D878696FD44ED6720F7694E |
+----------------------------------+
1 row in set (0.12 sec)

-- decrypt the salt
select AES_DECRYPT(UNHEX('CCBD9EDD8D878696FD44ED6720F7694E'), 'encrypt key') as decrypted_salt;
+----------------+
| decrypted_salt |
+----------------+
| salt           |
+----------------+
1 row in set (0.00 sec)

Note that you need an encrypt/decrypt key as second argument of AES_ENCRYPT() and AES_DECRYPT(). The point is to limit damage if an hash is leaked at application level, for example: by using different salts you cannot see which users are using the same password. But if an attacker can submit arbitrary code, then you cannot do much.

For more information read these links:

cereal 1,524 Nearly a Senior Poster Featured Poster

Sorry for the mistake, in my previous example I was referring to orders.id_customer, but nevermind: I exported the schema from the workbench file and I saw a date_add column in the orders table, so try this query:

SELECT customer.id_customer, customer.firstname, customer.lastname, orders.id_order, orders.date_add FROM customer, orders WHERE customer.id_customer = orders.id_customer GROUP BY orders.id_customer ORDER BY orders.date_add ASC;

Live example: http://sqlfiddle.com/#!2/17133/1

cereal 1,524 Nearly a Senior Poster Featured Poster

Ok, then remove customer.id_customer = ? and the limit clause, and try to use GROUP BY:

SELECT customer.id_customer, customer.firstname, customer.lastname, orders.id_order, order_history.date_add FROM customer, orders, order_history WHERE customer.id_customer = orders.id_customer AND orders.id_order = order_history.id_order GROUP BY order_history.id_customer ORDER BY order_history.date_add ASC;

It should return the correct rows.

cereal 1,524 Nearly a Senior Poster Featured Poster

Hi, here you can see the database schema:

And you can also download the MySQL Workbench file. Maybe you can try something like this:

SELECT customer.id_customer, customer.firstname, customer.lastname, orders.id_order, order_history.date_add FROM customer, orders, order_history WHERE customer.id_customer = ? AND customer.id_customer = orders.id_customer AND orders.id_order = order_history.id_order ORDER BY order_history.date_add ASC LIMIT 1;

This should return the first order made by the customer, to get the last one use desc, instead of asc, in the order by clause.

Note: the question mark in the query should be replaced by the customer id number.