Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Zamujasa
Oct 27, 2010



Bread Liar

Golbez posted:

quote:

print vs. echo
Not that I'm aware of, I just have never seen people use print where echo would work.

If I remember right, "echo" is very very very very very very very slightly faster than "print" -- trivial.

There's also some other bullshit that this StackOverflow question explains.


However, in general, for basic poo poo like echo "Some poo poo here."; use whatever works best. I did a lot of stuff in QBASIC when I was younger and "print" got stuck into my brain, so it's what I end up using more often when I'm not mixing them up.


Short version: The only difference you're really likely to run into as a sane developer is that you can do "... or print('yyy')", but not "... or echo('yyy')".

Adbot
ADBOT LOVES YOU

Zamujasa
Oct 27, 2010



Bread Liar

Fleur Bleu posted:

I was browsing the mysqli function list, wondered what kill did, skimmed it's article, saw "kill process" and I thought "Thats sounds good, let's put that in.". Looking at it again, the examples use it the same way I do.

The big problem I can imagine is if you're doing something big that the script isn't blocking over (e.g., running "UPDATE bigasstable SET x = y") you can kill the thread halfway into doing something. I only kill threads when something's gone completely off the rails and is locking tables and causing huge traffic jams.


My boss did the same thing with mysql_free_result() and just started copy-pasting it after every mysql_query() (even ones that mysql_free_result() makes no sense for, like INSERT or UPDATE). Please don't be my boss.

Zamujasa
Oct 27, 2010



Bread Liar
It's also good to remember that it's not how many queries, but what type and on what data. I've written queries before that took upwards of 5 seconds to run (and were difficult as hell to debug the issue with).

You'll know when it's time to optimize.

Zamujasa
Oct 27, 2010



Bread Liar

bobthecheese posted:

The way my bank handles it, for example, is that it generates single-use keys for all actions. So, I assume, they store the "next action" key on the user's session, and attach the key into every link and form possible. If the passed key doesn't match the one in the session, then they reject the request and log the user out. On every successful request, they generate a new "next action" key.

The problem with this (like many of you will probably have realized already), is that you can't use the back-button or refresh. For a bank, that's not too bad - they provide 'safe' back and refresh buttons in the page, and I'm sure that I'm not going to accidentally trigger off multiple transactions by hitting back or refresh.

The other problem is that you can't have two browser windows open without having two separate sessions.

You can get around this by only checking the "next request" key on actions that would reliably need it. Alternatively, store a different key, that would expire after some amount of time (10 minutes?), and if that expires, then log them out.

Breaking the open-in-new-tab and such features is a terrible design flaw.

Zamujasa
Oct 27, 2010



Bread Liar

DaTroof posted:

Close. If they have the same name, the value in $_GET/$_POST will simply be the last one received; but if you bracket the end of it (e.g., <input type="text" name="website[]" />), all the values will be appended to an array.

You can also do fun things like this:

code:
<form ...>
 <input name="data[1][name]" type="text" value="Name">
 <input name="data[1][addr]" type="text" value="Address">

 <input name="data[2][name]" type="text" value="Name 2">
 <input name="data[2][addr]" type="text" value="Address 2">
</form>
It makes it a great deal easier to work with dynamic forms where you can have multiple rows or columns of input. :)



IT Guy posted:

Everything that he said ^

At any time if you find yourself storing values into a single field with a delimiter, then 99.9% of the time, your database design is wrong and you need to rethink your strategy.

You can't query off it like the above poster mentioned without doing slow string functions.

Let's say you wanted to count how many websites a user has.

code:
SELECT COUNT(*) FROM `websites` WHERE `websites`.`user_id` = :uid
is so much easier than whatever query would be needed to explode your array from the delimiter.

We have an instance which I thought was part of the 0.1%; we store a CSV-list of numbers for a set that we use when adding a new object to the database. e.g. "object_defn [ id=1, something="such and such", subobject_ids="1,2,3,4,17,18,19,20" ]". When the code creates a new object, it pulls out the list of subobjects to make (and each one of those is a new row, so the CSV is only for the definition).


After some thought, though, even that could probably be handled better, since a lot of object definitions have the same subobject_ids and we could skip the explode-insert loop in code using INSERT INTO ... SELECT. :aaa:

(The original designers used a lot of this CSV-in-a-database stuff for things that really should have been normalized, and we've fixed all but this one.)

Zamujasa
Oct 27, 2010



Bread Liar

ATM Machine posted:

I think it sounds like something is happening server side to alter the page by trying to insert something after a request for a PHP file is made, whatever its trying to insert has been removed or prevented, but whatever is doing it hasn't, so its adding in a blank newline.

Of course, maybe its something simple like a rogue php.ini file that's caused a setting to be overwritten somewhere.

If its possible, can you copy everything onto a local server like XAMPP or something similar and see if it produces the same results?

Wordpress was mentioned; I'm starting to wonder if it's possibly a rogue file somewhere that's doing it. Maybe it's something like auto-prepend-file in a php.ini or .htaccess somewhere.


Try creating a page with just <?php phpinfo(); and see if it gives you any information.


If that doesn't, try this:

php:
<?
ini_set('display_errors','1');
ini_set('display_startup_errors','1');
error_reporting (E_ALL);

header("Content-type: text/plain");
print "Test";
?>
If the blank line is coming from before this and you don't have output buffering on somewhere, it'll throw an error with what file caused it to be output. Otherwise you'll just get a text page with "Test" on it.


This is all voodoo debugging, though. Good luck finding the cause.

Zamujasa
Oct 27, 2010



Bread Liar
Be sure that you're using htmlspecialchars() when outputting because <str: might make a web browser try to interpret it as HTML.

If that doesn't help, does var_dump($_POST) show anything? What if you add other inputs to the form?

Have you checked your browser request and made sure it's going through?

Zamujasa
Oct 27, 2010



Bread Liar

duck monster posted:

Chances are if I'm the only one working on it, my language choice wont even support private variables, because there isn't a reason ever not to use python
in a situation where you have a choice 99.99% of the time. And with due respsect to where I am, given a choice on a project language , in 2013 it sure as hell it won't by PHP. Time, and sanity, is money.

edit: Oh god, magic_variables_gpc breaks mysql_escape_string and creates *double slashes* thus rending things MORE insecure.
:negative:
Burn the fields and salt the earths, I need to move this shop to either a good framework, or something not php loving pronto. The "long drop"(poo poo starts at the top and executes through the code to the bottom, then the programmer hangs himself with it in despair) method of web coding needs to die.

edit2: Oh god, I just discovered the boss who's that untrained he doesn't know how functions work codes *on the live server* using an ftp client. I was loving wondering where his copy of the code was. I have so much work to do. :(


duck monster posted:

magic_variables_gpc
:stonk: Why are you using magic_variables_gpc? Jesus Christ write a drop-in replacement using mysqli and even the most basic of prepared queries or something as soon as you can.


(Also, double slashes should theoretically still be fine, as you'd end up going from \' to \\\' (the slashes get escaped too), which is the cause of badly designed websites that output \' instead of ')


duck monster posted:

There is THIS clanger however
PHP code:
		$result = exec("/usr/bin/nslookup ".substr($email, strpos($email, "@")+1), $output); //I dont trust this at all.
		if (!substr_count(implode(",", $output), "NXDOMAIN")) { 
			create_user($email);
...

This is borked. But I need to prove it. I had him leaning over with me fuming about this insane code as I tried to exploit it using stuff like

duckmonster@magicalwebsite.com ; cat /etc/passwd > /var/www/passwds.txt

But nothing I could do could exploit this. Anyone know a good way to DEMONSTRATE that this code is insane and broken to my boss?

Something like "email=pwned@;funexploit" might work (it depends on if you can get away with using spaces)... the fact that it's blindly executing shell parameters without any sort of escaping is an absolute horror, though.

It depends on where $email is coming from. If it's being escaped by PHP's shell arg escape function you might not have much luck.

Zamujasa
Oct 27, 2010



Bread Liar
php:
<?php

function fart($array) {
  $c 0;
  foreach ($array as $node) {
    if (isarray($node)) {
      $c += fart($node);
    } else {
      $c++;
    }
  }
  return $c;
}
Note that you can make $c whatever, it doesn't have to be a count. You could put every final node's value into it and then use array_unique on the end result, for example.

Zamujasa fucked around with this message at 02:25 on Jul 20, 2018

Zamujasa
Oct 27, 2010



Bread Liar

Agrikk posted:

Can someone help me with a check to see if a row is complete?

I have a file of tab separated values, and some rows are incomplete, which breaks my processing. How can I check to see if the row is incomplete so I can do something else with it?

code:
user1 \t 123 \t data1 \t data2 \n        \\good
user2 \t 634 \t data3 \t data45 \n      \\good
\t 273 \t data7 \t data34 \n             \\bad
984 \t string1 \t string2 \n               \\bad
user3 \t 483 \t data55 \t data78 \n     \\good

I'm assuming you're using some combination of explode to break out the values; in that case you could just... check if they're broken before processing:

php:
<?php
 $data "a\tb\tc\n\tb\tc\na\tb\na\tb\tc\n";
 
 $a explode("\n"$data);
 foreach ($a as $l) {
   $la explode("\t"$a);
   if (count($la) < || $la[0] == "" || $la[1] == "" || $la[2] == "") {
     // do something else with this line, which sucks and is broken
    continue;
   }

  // do what you do for normal lines
}

This is a gross example, but it gets the job done. (* I didn't test this because I wrote it in a forum post.)


Tei posted:

After a second through. Is better to pass the id instead of the object, so the caller don't need to know about things he can live withouth knowing.
And because is good for code to be lazy and pass the buck to other code. The caller would need to do extra work.

Given a choice between "public function doThingWithBar(\Bar $bar)" and "public function doThingWithBarId($id)" I'd say you should prefer the former in all cases if only because it guards against something that isn't a Bar id getting in there.

There's other value, but that's the easiest one to explain.

Zamujasa
Oct 27, 2010



Bread Liar

rt4 posted:

Use any VPS you like. Check AwfulMart for some decent hosts with goon discounts.

PHP is not well suited to long-running processes. Writing the main app in PHP is usually not a terrible idea, but use something else for the websocket. Javascript is a popular choice, although it's a massive footgun. I'd pick Go.

Also this is way, way late, but as someone who has written several long-running processes (some that have been running for multiple months and in one case literal years): php isn't really any worse than anything else for running long-running processes, it's just that the way you build a long-running task is a lot different than the way you write normal ones.

Zamujasa
Oct 27, 2010



Bread Liar

Biowarfare posted:

I have quite a few PHP "workers" (that read off redis queues), and I don't see it being much different than node. You just have some kind of forked off child or blocking loop most of the time, instead of a top-down render resulting in stdout (to a page)

It is bizarre to start with though, as someone explicitly used to writing PHP as a "page"

I have a few that poll a database (someone else's bad decision) every second and write to some network ports, as well as another set that acts as a server/translator for some networked devices. Reads input, translates it into usable data, then pushes it out to other endpoints. Both of these tend to run for months if left undisturbed, and the only reason they don't last longer is because "make them recover from network errors" has never been in the time budget :saddowns:


I like php just because it's easy to get started with and there's no gigantic pile of dependencies or requirements just to begin. Most of it is either just built in or in one of the typically-bundled extensions. You don't need to import 20 modules just to get printf.

(I say this, then I was reviewing a new hire's 'code challenge' which involved 200 MB of php and node modules for what took about 30 lines of raw PHP :suicide: )

Zamujasa
Oct 27, 2010



Bread Liar

Good Sphere posted:

code:
<?php
// get MP4 address
$MP4Address = $_GET["MP4Address"];

// We'll be outputting a MOV
header( 'Content-Type: application/octet-stream' );

$filename = basename($MP4Address);

// Name file
header('Content-Disposition: attachment; filename="'.$filename.'"');

// Source file
readfile($MP4Address);
?>

I'm going to ignore the rest of the posts in this thread just to point out my_script.php?MP4Address=../../../../sensitive_file_you_really_dont_want_sent.

If this is what the original actually looked like, and you are not currently responsible for it: this is a trash fire, do not touch it and walk away.

Zamujasa
Oct 27, 2010



Bread Liar
you can also pare it back a bit and test if it works at all.


for example, what do you get if you run var_dump(shell_exec("echo test")); ?

Zamujasa
Oct 27, 2010



Bread Liar
i just had to change $_GET['n'] ?? "default" to an isset($_GET['n']) ? $_GET['n'] : "default", so i feel you there

Zamujasa
Oct 27, 2010



Bread Liar

Agrikk posted:

What is the best way to accomplish this programmatically?



Given a wealth level "poor, normal, rich, etc." I can RAND(1,100) to select the number of items using a SWITCH statement. Right now I solve this by creating five switch statements, one for each column, and then wrap them in an additional switch statement for the wealth level.

Is that it?

Intuitively, it seems that this can be done somehow using a multidimensional array but I can't get my head around it.

it can be:

php:
<?
    function fart($roll, $wealth) {
        $rolls = [
            20 => [0, 0, 0, 0, 0],
            40 => [0, 0, 0, 1, 1],
            55 => [0, 0, 1, 2, 2],
        
            70 => [0, 1, 1, 2, 3],
            80 => [0, 1, 2, 2, 4],
            90 => [1, 1, 2, 3, 5],
            94 => [1, 2, 3, 3, 6],

            97 => [2, 3, 4, 4, 7],
            99 => [3, 4, 5, 6, 8],
            100 => [4, 5, 6, 8, 10],
        ];

        foreach ($rolls as $max => $table) {
            if ($roll <= $max) {
                return $table[$wealth];
            }
        }
    }
?>
this works because arrays in php keep their sort order. the index/key of the array is the highest dice roll, and then the value is an array of the wealth levels.
it basically asks: "is the roll lower than 20? well, what about 40? what about 60?" etc. until it gets an answer, and then it returns the wealth level of that particular entry.

the expected inputs are 1-100 for the roll and 0-4 for the wealth level, but you can make them anything.
fart( 1 ~ 100, 0 ~ 4 )

edit: this is basically an implementation of the above poster's thought, but without the "minimum" range, since the minimums are always either infinity or the previous level's maximum.

edit 2: i would argue one benefit of the above (with the proper formatting) is that it preserves a very clear 1:1 relationship with the original chart. if you saw the chart and the code side by side it's immediately obvious what the data is and how it should work (though of course if you're using it somewhere serious please add a few comments)

Zamujasa fucked around with this message at 22:53 on Dec 29, 2023

Adbot
ADBOT LOVES YOU

Zamujasa
Oct 27, 2010



Bread Liar
it's like code golf but you're trying to hit the ball through windows :allears:

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply