1

You can also use a regular expression (regex), in PHP you can use regex with preg_* functions:

preg_match_all('/5/', $numberedString, $matches, PREG_OFFSET_CAPTURE);

The first argument is the pattern to search, the slashes are delimiters; the second argument is the subject to search, your string; the third argument is the array that will hold the results; the last argument is a constant to show the position of each match in the researched subject.

So, if you print it, you get:

print_r($matches);

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => 5
                    [1] => 4
                )

            [1] => Array
                (
                    [0] => 5
                    [1] => 14
                )

            [2] => Array
                (
                    [0] => 5
                    [1] => 24
                )

            [3] => Array
                (
                    [0] => 5
                    [1] => 34
                )

        )

)

About the docs: at the end of each function page, there is a list of other functions to consider as alternative. If you open php.net/strpos you get preg_match, which would return only $matches[0][0], from there you can reach preg_match_all. Once you get used, you just have to explore and test.

2

In the specific case of Twitter, there is an API that allows to search through the public tweets of a specific account:

You can check the libraries used to connect this service here and see how it is done:

If you want to check the contents of a static page and here I mean the contents generated on server side and loaded in plain HTML, you can use a library to analyze the DOM, like:

DOM libraries require valid documents, if these are malformed then the extraction can fail.

If, instead, the contents are loaded through Javascript, you need a browser engine and some javascript, see as example:

A part these, there are many other available solutions, like regular expressions or scripting with command line tools as awk or sed:

Also, if the goal is to extract data, don't limit your choices to PHP, there are excellent solutions written in other languages, see for example Scrapy:

Curious to see what the code would look like and php is capable of doing it in how many lines of code.

Hehe, I think you can try to extract the tweet through a DOM library (DOM Crawler should be easy to use), check the HTML source of the link you provided, load the page and see what you can get from there.

2

In addition: consider that a bind can be defined in the execute() method, so:

$stmt->execute([':id' => $id]);

You could change the queries to whitelist some expressions and add it as a variable, something like this should work and allow you to define multiple conditions:

$sql = "SELECT * FROM `names` WHERE %s";

if($int > 0)
{
    $condition = "`fname` = :fname";
    $data = [':fname' => 'klaus'];
}

else
{
    $condition = "`fname` IS NOT NULL";
    $data = NULL;
}

$stmt = $db->prepare(sprintf($sql, $condition));
$stmt->execute($data);

Bye!

1

Hehe, sure you can!

If you want to solve it, instead, read the notice, it says Use of undefined constant session - assumed 'session', which means you probably wrote:

$autoload['libraries'] = array(session); # without quotes

Instead of:

$autoload['libraries'] = array('session'); # with quotes

By adding quotes the value is considered a string, which is what you need in this case.

2

Have you read this? http://php.net/manual/en/language.expressions.php
Basically a statement can be an expression. And:

The simplest yet most accurate way to define an expression is "anything that has a value"

About tokens: in PHP it can be, strictly, used to define some parts of the language or used widely by the interlocutor to refer to other concepts, see:

1

Hi,

I don't want to add confusion, but I wonder if there is an open process pointing to an unlinked file in that directory. Try something like:

lsof -nP +L1 | grep '(deleted)' | grep -i ".club"

from a terminal, to see if it outputs results. To be honest, I ran a test on my system[2] and, while the file was still "existing" for the process, I was able to install Flarum through composer.

Reference:

  1. http://www.gnu.org/software/libc/manual/html_node/Deleting-Files.html
  2. http://www.linuxquestions.org/questions/linux-security-4/how-can-i-hide-a-file-from-ls-a-496229/

Anyway, instead of using composer on the server, you could install it on local and then use SFTP (Filezilla has the client too) to upload all the files to the server.

1

Hi!

In addition to previous suggestion: if the path is wrong or does not have write permissions Python would return:

sqlite3.OperationalError: unable to open database file

Instead you get:

sqlite3.OperationalError: no such table: Airports

Which can be generated if:

  1. the database file name is wrong due, for example, to the case: linux is case sensitive, Mac OS no (at least not by default)
  2. the database file or the parent directory is read-only, so you have to change the permissions
  3. the table does not exists

In the first case connect() will create the database file, but this obviously won't have the Airports table.

In the first case this:

for row in cur.execute('''SELECT "Hello"'''):
    print row

will run successfully, it will run successfully also if the file is read-only, but it will fail if there are permission issues with the parent directory. The error, however, will be related to the database file, not to the table.

3

I don't know what this is as still a beginner: var_dump($numrows);

var_dump() returns information about expressions TRUE < FALSE or variables. For example:

$stmt = TRUE === TRUE || TRUE < FALSE && TRUE === FALSE;
$str  = 'Hello';
$fp   = fopen('php://memory', 'w+');
var_dump($stmt, $str, $fp);

It will return the data type and the value:

bool(true)
string(5) "Hello"
resource(3) of type (stream)

In my previous comment, I suggested you to verify the contents of the $numrows variable, to make sure you were receiving an integer (as expected) or NULL, which would suggest an error with the query.

About the code, I understand what you want to achieve, however query to verify only if the username or the email address exists, exclude the password for now, so do:

SELECT * FROM users WHERE usernames='abc' OR emails='abc' LIMIT 1;

I'm adding LIMIT 1 here, which can be avoided if you set unique keys on usernames and emails columns.

Once you get the row, fetch the password from the result set and compare it with the one submitted in the login request.

Right now, I suppose you are saving passwords in plain text, you should use password_hash() to generate the hash to save into the database and password_verify() to verify the attemp with the hash.

Read the following tutorial by Diafol, #11 Storing and Retrieving Authentication Data, which shows exactly the same approach that I would use here:

It is developed for PDO and uses prepared statements, it can be ...

2

Hi,

what you get with var_dump($numrows);?

Besides, look at your query:

SELECT * FROM users WHERE usernames='abc' OR emails='abc' AND passwords='WRONG_pass';

Basically it is like writing:

SELECT TRUE OR FALSE AND FALSE;

Which evaluates to TRUE:

+---------------------------+
|   TRUE OR FALSE AND FALSE |
|---------------------------|
|                         1 |
+---------------------------+

In this case by knowing the username you can access without the correct password. It happens because in MySQL AND has an higher precedence than OR, so the expression is read by the database like:

SELECT TRUE OR (FALSE AND FALSE);

To avoid the issue do:

SELECT (TRUE OR FALSE) AND FALSE;

Which evaluates to:

+-----------------------------+
|   (TRUE OR FALSE) AND FALSE |
|-----------------------------|
|                           0 |
+-----------------------------+

As expected.

See: https://dev.mysql.com/doc/refman/5.7/en/operator-precedence.html

2

Has 7 made any difference to the way you code?

A bit.

To be honest, a part personal code, I have used PHP 7 only for one client's project because it was starting with that version, in that case I used strict type declarations, CSPRNG functions and Throwable to catch common errors.

For me the former and the latter were missing bits in PHP. I'm happy these were introduced. I would like to see Throwable also for warnings and notices rather than setting an error handler.

Are they massive time savers (coding-wise or run-wise)?

At the moment no, not for me.

Something I would like to see is overloading, what is currently used in PHP smells more like overriding and I find it chaotic.

Votes + Comments
About the same here, although not using CSPRNG or strict types
overloading: There isn't the concept of the "method signature" so to add overloading in PHP can be difficult
1

Hi,

at line 7 you have:

$update_id = $post_id;

while $post_id is initialized at line 68:

$post_id = $row_post['post_id'];

Which in practice depends on $edit_id defined at line 60:

$edit_id = $_GET['edit_post'];

So, it seems that you open the page like this:

page.php?edit_post=123

All you have to do is to initialize $edit_id on top, at line 4, so that is available to the POST conditional statement and to the other code.

Do not use $_GET directly, filter the variable:

$edit_id = filter_input(INPUT_GET, 'edit_post', FILTER_VALIDATE_INT, ['options' => ['default' => NULL]]);

Then replace:

$update_id = $post_id;

With:

$update_id = $edit_id;

Or simply adjust the following code to use $edit_id. Use the filter functions also for the other input coming from POST and GET requests, and use prepared statements too:

1

Hello Dani,

I don't think it's the user agent, I'm testing with Phantomjs and it uses this user agent:

Mozilla/5.0 (Unknown; Linux i686) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1

The testing script render.js:

var page   = require('webpage').create(),
    system = require('system'),
    vsize  = {width: 1280, height: 1024},
    address, output;

address = system.args[1];
output  = system.args[2];

page.viewportSize = vsize;
page.clipRect = {
  top: 0,
  left: 0,
  width: vsize.width,
  height: vsize.height
};

page.open(address, function() {
  page.render(output);
  phantom.exit();
});

Execution:

./phantomjs render.js LINK output.png

And it works fine. In this specific case Microsoft is rejecting HEAD requests, it allows GET requests, in fact, it returns 200, but the page has no contents because are loaded by Javascript: test with Postman to see how it renders. So, it seems it needs a rendering engine to show the contents.

2

Hi! You can use pathinfo() or a directory iterator:

$ext = pathinfo($file)['extension'];

BUT right now the img() function can, potentially, allow the access to the contents of any directory on the server, by adding ../ to the variable, as example you can write the following and access /etc/:

pictures.php?imageID=images/../../../../etc

It depends on the position of the document root in the file system. You could use an integer and make sure it's valid, for example:

$imageID = filter_input(INPUT_GET, 'imageID', FILTER_VALIDATE_INT, ['options' => ['default' => NULL]]);

if(TRUE === is_null($imageID))
{
    # redirect or show 404
}

# continue if $imageID is valid

See also: https://www.owasp.org/index.php/Path_Traversal

Votes + Comments
thank you @cereal
2

From the documentation:

If called from within a function, the return statement immediately ends execution of the current function, and returns its argument as the value of the function call.

It is like doing:

echo 'hello';
exit;
echo 'world';

so in your function you can store the value that you want to return into a variable, you can use the assignment operator .= and then return the variable at the end of the function execution:

function generate_list($rows)
{
    # initialize the $str variable
     $str = "
     <table>
     <tr>
         <th>Firstname</th>
        <th>Sirname</th>
        <th>Email</th>
        <th>Phonenumber</th>
        <th>Information</th>
     </tr>";

     while($row = $rows->fetch_assoc())
     {
         # append values to the $str variable
         $str .= "
         <tr>
            <td>{$row['Firstname']}</td>
            <td>{$row['Sirname']}</td>
            <td>{$row['Email']}</td>
            <td>{$row['Phonenumber']}</td>
            <td>{$row['Information']}</td>
        </tr>";
     }

     # append values to the $str variable
     $str .= "</table>";

     # finally return the contents of $str
     return $str;
}

$results = $con->query("SELECT * FROM listing");

# store the results of the function into $list
$list = generate_list($results);

# print the contents of $list when needed
echo $list;

$results->free();
$con->close();

About the connection to the database, you could set that outside of the function scope, what happens if you have 30 functions pulling results from the database and you have to change the credentials?

2

@UI

Hi!

in addition to previous comments, if you are learning PHP for work, sooner or later you will handle legacy code, you will be asked to add functionalities, not always to port it. You cannot always choose the version to work with. For example, something simple like:

$i = 1024**2*10;

returns a syntax error if you use PHP <= 5.5 and works fine when using the latest versions. To avoid issues in such case, you would write:

$i = 1024*1024*10;

Or see how list() changed the behaviour between PHP 5 and 7 when using array indices, that's just insane (it was from the beginning). IMHO, you need to know these things too, to become more efficient.

2

Hmm, the session in this case it is not, probably, the best approach: what happens if, in the current session, you open multiple tabs of A.php with different IDs?

A.php?id=123
A.php?id=124
A.php?id=125
...

It would screw up, because the session value would be rewritten by the latest loaded tab. Append the query string to B.php, so if you are using a form you can do:

<form method="get" action="B.php?id=123">

Or hide it in the input fields:

<input type="hidden" name="id" value="123">

If you want more appropriated help, share an example of what you are trying to do.

Votes + Comments
Good shout about multiple tabs +1 - a common gotcha!
2

Right now, change line 13 to:

if(mysqli_num_rows($query_run)>0)

There is also another error here:

$query_run = mysqli_query($query,$db);

The first argument of the function must be the link to the database, the second the query statement. So:

$query_run = mysqli_query($db, $query);

Regarding prepared statements you have to change the approach and use the MySQLi Prepared Statement class. You can find the documentation here:

So, define the query to perform:

$query = "SELECT * FROM `tbl_employee_information` WHERE `employeeno` = ? AND `name` = ?";

Instead of writing variables directly inside the query string, replace them with placeholders and bind the parameters through the bind_param() function.

MySQLi allows procedural and object oriented styles.

Procedural style:

$stmt = mysqli_prepare($db, $query);
mysqli_stmt_bind_param($stmt, 'is', $empNo, $name);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);

if(0 < mysqli_stmt_num_rows($stmt))
{
    # code
}

mysqli_stmt_free_result($stmt);

The object oriented style looks like:

$stmt = $db->prepare($query);
$stmt->bind_param('is', $empNo, $name);
$stmt->execute();
$stmt->store_result();

if(0 < $stmt->num_rows)
{
    # code
}

$stmt->free_result();

The is stands for i integer, s string, for the $empNo and $name variables. You can find which types you can define, inside the bind_param() function documentation.

A word on $empNo and $name, you are currently using $_POST, use filter_input(), instead, as you can sanitize the input:

$empNo = filter_input(INPUT_POST, 'employeeno', FILTER_SANITIZE_NUMBER_INT);
$name = filter_input(INPUT_POST, 'employeeno', FILTER_SANITIZE_STRING);

The docs about the filters:

Bye!

Votes + Comments
Excellent, as usual.
1

Hi,

in this case the error message is very descriptive:

PHP Parse error: syntax error, unexpected '"', expecting '-' or identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING) in /home/sn/public_html/sn/home.php on line 168

It points to a specific file and line of the code. If you don't find the error in that line then search above. On line 133 of home.php there is a backtick:

exit();` // <-- remove this

If you want to learn PHP, learn to reproduce bugs: isolate the code that generates the error and try to get the same error message:

<?php

print 'hello';`
print 'world';

Generates:

PHP Parse error: syntax error, unexpected end of file, expecting '`' in /tmp/a.php on line 5

Also the backtick operator as a specific meaning in PHP as it's an alias of shell_exec(), you can run a command like this:

$arg  = array_key_exists(1, $argv) ? escapeshellarg($argv[1]) : '';
print `find . -type f -iname "$arg" 2> /dev/null`;

> php a.php *.jpg

More info: http://php.net/manual/en/language.operators.execution.php
The comment part of the manual, sometimes, is very useful.