Jump to content

kicken

Gurus
  • Posts

    4,704
  • Joined

  • Last visited

  • Days Won

    179

Everything posted by kicken

  1. You can use curl or the Guzzle library to handle making your web requests and maintaining the session. Just read the respective documentation to see how it's done, neither is very hard. Once you get the HTML you can use the DOM library to parse it and extract the information you need.
  2. If it was not being used, you wouldn't be getting an warning. Since you are getting a warning, it means something is being used incorrectly. What you need to do is figure out what is triggering the warning and why. A quick google search for that message suggestions a common cause for this is trying to concatenate strings using + (plus) instead of . (period). Using an empty string in a calculation seems to be another cause, and this may be your problem as a blank input is the empty string. You would fix this by converting those empty strings to zero prior to using them. This could be done relatively easily using array_map.
  3. Use array_filter with a custom callback function that checks the [1] value. array_filter($array, function($value){ return $value[1] != 0; });
  4. Do you mean all the items where [1] => 0, like here: [72] => Array ( [0] => 2021-06-28 [1] => 0 ) So you want to remove the entire [72] entry?
  5. That is indeed an odd issue. I can say that's not a problem I've experienced here. Like requinix I struggle to think of a way such a problem could even happen without there just being some massive data stream going on in the background. The best speculation I can come up with is something the form is doing ends up triggering some kind of rate-limiting rule on your ISP's network.
  6. On the surface, this to me does look like a project that's best done with javascript in the style of a single-page application. Once the page is loaded there would be little to no need for it to ever contact your server again as all the information and processing would be handled locally by the users client. This way they can take as much time as they need, and potentially even work offline without an internet connection at all. If you'd prefer to keep the project with PHP, say because you're not that proficient in JS but are in PHP, then what I would do is just keep the information in your form as a hidden input. For example, when rendering the form on the second step you might do: <input type="hidden" name="step1data" value="<?=htmlspecialchars(json_encode($_POST));?>"> Then when the form on step 2 is submitted you can pull the data from step one back into a PHP array by json_decoding $_POST['step1data']. By passing the data around like this you make the application stateless from your server's point of view so there's no need to mess with sessions or timeouts at all.
  7. Do you really want to keep the data in the users browser? If you do, there are other options available that would allow that. Keep in mind however that storing the info in the browser means it's only available in that browser instance. So if someone input all that data on their home desktop PC, they would not be able to pull it up later on their laptop later for example. The data would also be unavailable to you as the site owner. Good for ones privacy, bad if you want to use the data in some way. If you want it available from any browser/location then storing it on your server in a database is the best option.
  8. I had a blog post bookmarked that covered creating a tree structure from a list that I was going to link, but it seems it's no longer online. I guess maybe I should make my own some day. Transforming your list of items into a structure for your json can be done with relative ease by making use of references and a lookup table. For your particular problem, it's best broken down into two separate steps. Group your products by category. Nest your list of categories into your tree structure. Grouping your products is easy, just combine all the products with the same categorypath into an array. // First, group products into their categories. $categoryList = []; foreach ($itemList as $item){ $categoryList[$item['categorypath']][] = [ 'id' => $item['id'] , 'path' => $item['categorypath'] , 'prodname' => $item['product'] ]; } After that, you have a nice list of all your products. In $categoryList the key will be each of your unique category path's and the value will be a list of products that belong to that category. Now, you need to take that array and structure it into your tree. To do this, you create two arrays, one that will hold your final tree structure and another that you use to lookup existing entries to make modifications to them. In order for your modifications to have an effect on the tree, you need to make sure both your lookup array and tree structure array refer to the same underlying data which is accomplished via references. // Now, create a tree structure out of the categories $jsonTree = ['category'=>[]]; $lookupTable = []; foreach ($categoryList as $category=>$productList){ $componentList = explode('/', $category); $path = ''; $parent = &$jsonTree; do { $component = array_shift($componentList); $path .= $component.'/'; $entry = &$lookupTable[$path]; if (!$entry){ $entry = [ 'categoryName' => $component ]; $parent['category'][] = &$entry; } $parent = &$entry; } while ($componentList); $entry['products'] = $productList; } This loops through your list of categories and for each one does the following steps: Split the category path into it's individual components Create an initial parent reference to the root of your tree structure. Rebuild the path one component at a time. For each component during this process Combine the current component with the previous ones to get a partial path Create a reference to a key for that partial path in $lookupTable and assign the reference to $entry Check if the key already exists or not. If not: Create the category entry Assign the category to it's parent's list of sub-categories Re-assign the parent reference to the current category entry. This way on the next iteration when we assign the category to $parent['category'] it will be made a child of the category from this iteration. At the end of the path rebuild, $entry is a reference to the last category entry. Assign the product list to that entry. At the end of all that, you can then just json_encode your tree structure to get the output you want. By using references along with $lookupTable with unique index keys it's easy to find a reference to what might otherwise be a deeply nested category in your tree structure. You can then manipulate that reference as necessary to make the changes necessary to generate your tree structure. OP's SO Post, for reference.
  9. Is granting the ability for your web user to run any command as root without a password unsafe? Absolutely, you might as well just run your web server as root if your going to do that. If you're going to use sudo, then you want to limit the commands that can be run to exactly what is necessary. For example, at one point I had a page that would allow resetting an email password and the process to do so required root. I created a shell script with all steps necessary and I added this to my sudoers file: www-data ALL = NOPASSWD: /root/bin/reset-mailbox-password That allowed my public-facing web page to execute that command and only that command as root with sudo. That way if there were ever a security issue in the future that gave someone shell access as www-data they couldn't just run whatever they wanted to sudo and further compromise the machine.
  10. I am guessing by magic method you mean you are using __call to respond to calls for getSettings(). If that's the case, then you cannot use method_exists to check if that "method" is defined because PHP has no way of actually checking what __call handles and what it doesn't. You'd have to provide your own means of determining if that "method" is defined. One option is to just call it and have __call throw an exception if it's not handled. You can then catch that exception and handle it however you want. I think a better solution would be to abandon __call entirely and design your code in a way that getSettings is a real method. Perhaps you could define it as part of an interface then check whether or not your object implements that interface.
  11. It's just a normal HTTP request, just like anything else. Forms really are not anything special. It's just like a link using an <a> tag, except you can send more data by using method="post". So if your trial page outputs the form <form method="post" action="checkout.php"> <input type="email" name="Email" value="example@example.com"> <button type="submit" name="ProductId" value="1">Get trial</button> </form> When you click the button the browser will Open a connection to example.com Submit the http request POST /checkout.php HTTP/1.1 Host: example.com Content-type: application/x-www-form-urlencoded Email=example%40example.com&ProductId=1 If you don't understand the above, you should do some research on the HTTP protocol and learn how it works. As you can see though, your trial page is not referenced at all in those steps. The request is for checkout.php and the data is sent in the body of the request in the same format as a query string. This is not at all true. POST data is just as visible and open to manipulation as GET data. The only difference is where it's located in the request. This is why I said you need to get over your trust issue with $_GET. $_SESSION is the only thing you can generally trust as that data never leaves the server and cannot be manipulated directly by someone, they would have to exploit some vulnerability in your server or your code. It's a little bit of a semantics / being pedantic thing. Big picture, sure you are passing some data. Your not passing the trial pages $_POST array though. The trial page doesn't have a $_POST array unless your posting data to it in some way. By adding the action attribute pointing to checkout.php you're no longer posting any data to the trial page, your posting it to the checkout page. There's nothing wrong with using terminology like "pass the ProductId to the checkout.php page", but you should have the understanding of how that actually works. The language in your posts implied that you did not as you seemed to think that PHP was either sharing one $_POST between scripts (misunderstanding "global" I think) or somehow moving the $_POST array from one script to another which is not how it works.
  12. Based on your last post it sounds to me like you still don't really understand the process, or maybe you do but just don't articulate it well. It sounds to me like you're thinking you are defining $_POST['ProductID'] on your trial page then have to somehow transfer that variable over to the checkout page. That's not really how things work though. Your trial page doesn't have a $_POST['ProductID'] variable. It generates a form as it's output. That form is submitted to the checkout page, and that form's data contains a ProductID field which makes it so that your checkout script will have a $_POST['ProductID'] variable. Taking a step back to basics again, every request you have to look at in complete isolation. The request has to contain whatever data your script needs to get stuff done, and there are a variety of places in a request that the script can look at for data. $_GET - Data from the requested URL's query string (side note, you should get over your trust issues, $_GET is fine for something like a product ID). $_POST - Data from the request's body content, assuming the body is form data. $_COOKIE - Data from any Cookie: headers $_SESSION - Session data is handled via a slightly more complex process. When your script ends, the data stored in $_SESSION is saved to the web server somewhere and a unique identifier is then passed to the client. The client passes that identifier back to PHP on the next request (usually as a $_COOKIE value) and then the data is looked up on the server and restored. Whether you use a database or not doesn't really matter. You'd give your checkout.php page an identifier of some sort via one of the above mentioned input options. Your checkout page would then use that input to do whatever it needs to do. You can provide your identifier via $_POST if you want to checkout.php, but you're not "transferring $_POST['ProductID']" from the trial offer script to your checkout script, at least not in the way it sounds to me like you are thinking. Your trial offer script does nothing more than generate a form with whatever data you need. Once that is generated and sent to the client the trial offer script is done and is no longer relevant. When the user submits that form then the browser would take the form's data and send it directly to checkout.php, no other script is involved in the process. Now, going back to your original question, you mention having a shopping cart, so you need to split your process into two parts. Add the item to your cart. Display the items in your cart. Whether you want to do that via two separate scripts or all in your checkout.php doesn't matter too much. You could have your trial offer page post back to itself like your normally do and add the item to the cart then just redirect. In that case your checkout doesn't need to do anything other than look at the contents of the cart and display them. Otherwise you could have an input to your checkout page that identifies an item to add to the cart. You'd then just have your trial page create a form that posts directly to the checkout page with the necessary data. Your checkout page should still logically treat this as two steps and add the item to the cart, then look at the contents of the cart and display it.
  13. They are off, still happens though. It's not a big deal, just an oddity I noticed a while back.
  14. I think it may be this Firefox bug: Audio stream remains open when playback paused, preventing power saving/sleep I re-checked chrome this time actually seeing if it would sleep vs just checking for the request and it did actually sleep. It appears even though chrome causes the same audio request it does release it after a minute or so. Firefox doesn't, so the system ends up staying on. Not sure how IPB implements it's notification sound but I think it's triggering that bug. Trying to figure it out in all the minified JS is something I don't really feel like doing. I made a few attempts at re-producing it myself with <audio> or new Audio() but no luck.
  15. Anyone else noticing an issue where having the PHPFreaks forums open in the browser will prevent the computer from going to sleep with windows 10? Noticed that recently and checked with powercfg -requests and it seems whenever I have the forums open in a tab there's a request from the audio driver open that prevents sleep. I'm assuming it's related to the notifications feature, even though I have that disabled afaik. I don't use any other IPB based sites so no idea if it's just a bug with the software or what. Request shows up with chrome, firefox, and edge so I don't think it's a browser bug.
  16. If you have a SQL injection vulnerability, separate tables will not necessarily help you. Depending on the kind of vulnerability / setup you have the attacker may be able to run queries against arbitrary tables, or just drop the entire database. Aside from that, separate tables will become a maintenance nightmare when next year you need to add a few extra fields to the schema for all 10,000+ tables or whatever. Or you decide you want to be able to aggregate the data for a report and have to query every table and combine the results. Multiple tables with the same schema is the wrong solution 99.999% of the time, and you're not in that small 0.001%. Your wrong. Databases are designed to process data. They are designed to deal with tables that have many rows quickly and efficiently so long as you set them up properly. As an example, I have a table that records every login attempt to a website. It currently has about 2.2 million rows in it. I just queried it to find all my login attempts. It came back with 2976 rows. Guess how long it took the database to find those records out of the 2.2 million total records? 0.271 seconds. Yes, less than a second. If they can inject a DROP TABLE command, they can probably inject a SHOW TABLES command to get a list of all your tables then loop that list and drop each one. Your approach buys you nothing. You need to make sure you're not vulnerable to an injection attack in the first place, and then have solid backups to restore from just in case something does happen.
  17. I don't think anyone thought there was? The question is just why these dates: Instead of something else. Based on your description, $fillStartModified makes sense, it's the first thursday after $fillStart. Your $fillEndModified however does not. According to your description you want the closest date within the fill range that matches the same weekday. I interpret that as meaning that for $fillEndModified want either 2019-07-28 (first sunday after $fillStartModified/$fillStart) or 2019-09-22 (last sunday before $fillEnd). I haven't bothered to analyze your code to determine what it's doing. That's too much like work and it seems you're not sure it's even correct. A better English definition of your exact requirements/process is needed.
  18. exec()
  19. I am not familiar with vagrant, but when I setup my virtual box VM's if I want the VM accessible from the rest of the network it needs to be configured with a Bridged Adapter for the network and have an IP on the same subnet (that'd be 192.168.1.x for you presumably, unless your using a /16).
  20. You can still trigger backups whenever you want, it's just the PDO is the wrong tool for the job. Backups for mysql are typically done by using the mysqldump program to generate a SQL script containing all the database content. You would just need to execute this whenever you want a backup made. If your DB gets large, the a backup using mysqldump could take a while to run. There are other backup methods that could be explored then.
  21. Before you upload the file, $_POST["csv_upload_btn"] does not exist so the code $file = fopen("csv3.csv","r")or die("Failed to read file"); is skipped because the if condition above it fails. Since that code is skipped $file is never defined so this code print_r(fgetcsv($file))== NULL; for ($i = 0; $row = fgetcsv($file); ++$i) { } fclose($file); is now referencing a variable that does not exist. What you need to do is encase all your file processing code into a block that only runs when the file is uploaded and does not run when it has not been. There are also many other issues in your code. print_r(fgetcsv($file))== NULL; This code doesn't really make sense. print_r is for debugging, which is fine if that's what you're doing but comparing it's result to NULL means nothing, especially since you're doing nothing with the result of that comparison. So when you're debugging just call print_r with your variables, don't do a comparison too. for ($i = 0; $row = fgetcsv($file); ++$i) { } This will loop through the rest of your rows of your file, but does nothing with them. The loop body is empty. Presumably your code to echo out all your table cells should be inside this loop, not after it. You seem to have end of loop stuff commented out after the table cells so maybe you just made the loop empty for testing, but if you did that then you should be aware why it's only showing the first row (output of the print_r). //create the table in the database $sql = "CREATE TABLE IF NOT EXISTS`csvfile` ( `Test` varchar(10) DEFAULT NULL, `Test` varchar(5) DEFAULT NULL, ... ) ENGINE=InnoDB DEFAULT CHARSET=utf8; "; I don't know if this is how your code actually is or you changed it for this post to hide info, but you can't name all your columns 'Test'. Column names need to be unique. Then you will need to use prepared queries along with parameter binding rather than concatenation as you currently have in your insert query.
  22. It's not possible to target the last letter with CSS afaik. CSS generally depends on having the proper structure/markup to target things and if that's missing there's not much you can do. ::first-letter exists because stylizing the first letter is a common thing that places do so it made it into the spec as a convenience feature so authors didn't have to do <span class="first-letter">*</span> everywhere. Stylizing the last letter is not that common in my experience so it's not in there. So if you want to stylize your suffix you'll need to tag it with a span, or just remove it if all you want to do is hide it.
  23. Adding them to a date and comparing that seems fine. Otherwise you could inspect the various fields and compare those individually.
  24. Your value is just hard-coded in your index.php file, so you could just hard-code the same into your server.php file. A better approach however would be to create a third file which contains the value and include that into both your index.php and server.php files. That way there is only one place to alter the value in the future if necessary.
  25. Sounds like you forgot the leading / then. How URL's work is pretty standard. If you're on the page http://localhost/site/index.php then a relative URL resolves as: server.php => http://localhost/site/server.php site/server.php => http://localhost/site/site/server.php /server.php => http://localhost/server.php /site/server.php => http://localhost/site/server.php Using an absolute URL is fine, but generally using a root/domain-relative URL (starts with a /) is best imo.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.