Jump to content

gizmola

Administrators
  • Posts

    6,058
  • Joined

  • Last visited

  • Days Won

    153

Everything posted by gizmola

  1. Correct. That is an invalid mysql date. You can set a mode of mysql to accept that value, but that is not the way to handle this problem. Instead, make sure that the OTP expiry allows NULL. Then set the value to NULL. Personally, I would not design a system like this. Instead I would have a related table that only holds "events". I will usually have an user_event_type table that has different allowable authentication events. For example: user event type id | Description 1. Registration 2. Password Reset 3. One time Password 4. Login 5. Close account 6. Failed Login 7. Account locked etc. I don't know what your user table looks like but hopefully it has an ID other than "email". I'll assume you do. So you then have a user_event table with a structure like this: id | user_id | user_event_type_id | event_value | status | expire_date_time | created_at 100| 245 | 3 | xyzabc... | 0 | ..... | current_date There are a few reasons to do this. They include: - you have an audit trail of events - MySQL with InnoDB is optimized for insert queries, and they don't reduce concurrency unlike update queries. Instead of trying to overwrite the OTP, you can simply set the status from 0 to 1 (or whatever value you want). You could have several status values if you want fine grain control over the changes in status. Just to keep it simple, if the person logs in with the OTP, then it's used, so you set the status to 0. A subsequent query of "SELECT * FROM user_event WHERE user_id = 245 and user_event_type = 3 AND status = 0 ORDER BY created_at DESC LIMIT 1" will always find the most recent OTP request. You can then compare that with the OTP value. Making event_value a varchar of a specific length is no cost if the field is unused, as varchars will use the bytes required. So if you want to use event_value for additional data, you can do that, but if it's something simple like "login" event, you don't need to use it. Personally I would also have a client_ip field in a table like this, where I use a varbinary field to store the IP. This works for both IPv4 and IPv6 addresses, but there are some tricks to doing that, and it is not specifically related to your question. I mention it just to be complete.
  2. What do you mean it works? It's not even in the list of Access SQL keywords: https://support.microsoft.com/en-us/office/sql-reserved-words-b899948b-0e1c-4b56-9622-a03f8f07cfc8 I also never mentioned single or double quotes. You can use either when you are working with string constants, but you aren't doing that. You either use [name] or the name by itself for table and columns. So table.column or [table].[column].
  3. Microsoft access does not support Limit. It has a "TOP" keyword that does the same thing. So something like: SELECT TOP 3 * from Objects. It also does not support backtics. That is a MySQL feature. You use the square brackets, as you did in the final example. However, like MySQL's backtics you only need brackets if you have a non standard table or column name with perhaps spaces in it, or used a SQL keyword for the name. So your problem is most likely the use of LIMIT, which is not a keyword supported by Access.
  4. We had a vote that was open to any and all active users. We get a lot of reading these days, but not as many posters as in years past. I appreciate your taking the time to post, but people that bothered to post, all voted to close it, so unfortunately your opinion comes a bit too late.
  5. Yes, tcpdf does a great job and I've used it for really elaborate invoice documents and business check printing with barcodes. I didn't suggest it initially, because you indicated you wanted to try to come up with an html solution that would then be converted to pdf. I should point out the the developer of tcpdf has locked the project and has replaced it with a rewritten version with current PHP practices like namespacing. That project can be found here: https://github.com/tecnickcom/tc-lib-pdf
  6. It doesn't change the fact that the code in vsp.php at line 2392 is trying to get the value of the constant LOG_READ_SIZE and LOG_READ_SIZE is undefined. As far as I can see there is no way to look at the source code. I did see that someone dockerized the app and put the source code in github, but the actual vsp code is in some zip file that the package downloads.
  7. Suyadi's comment is factually accurate. The code expects the constant value LOG_READ_SIZE, and it is not defined. WIth that said, often utility applications come with instructions on how they should be configured, it looks like this might be the case for the application. Check instructions and see if there is a configuration file that needs to exist in a particular place. Many applications are distributed with a file with default settings that needs to be copied and renamed.
  8. When people are using tutorials to try and create PHP based features, there are pitfalls, the potential for misunderstandings and the possibility of error. We need to see what your actual code is. The only exception is in the case of passwords, keys etc. Those should be replaced. So we would need to see your code and the actual path you used in your code. The operating system, hosting location etc, is also important information in many cases. It sounds like you have error turned off at present, and for development, errors need to be turned on, so you can see what they are. It looks like your code has one or more errors in it, and that is why you are getting a blank page, but if errors are turned off, you can't see what the error message is.
  9. What's the problem with installing composer? Takes 2 seconds, and that is what PHP uses for dependency management and autoload building. Every option you have is going to start with using composer, and not using it is going back to PHP development as it was done in the bad old days of copying entire library codebases into project directories and everything that was painful, error prone and annoying with PHP library use, as of 10+ years ago. As for "best path" there really isn't one. There are different technical approaches to the problem, that tend to have different requirements, gotchas and limitations. You are best off doing a quick evaluation using the html docs you already have to explore the libraries. One up and coming option you didn't mention is gotenberg: a sophisticated go based conversion engine that has a php api. It has a lot going for it, but also has more moving parts. Here's the PHP Api that lets you talk to the Gotenberg server: https://github.com/gotenberg/gotenberg-php Puppeter (or rather the PHP api to it) takes a similar approach, in that it's a bridge to a headless browser used to render a page, which then allows you to save a pdf version. The https://github.com/zoonru/puphpeteer library is still being maintained, but already it's a fork of the original. You also have more moving parts (depending on Node, and the rialto bridge to Node). jspdf has similar issues, being a js library. For the Pure PHP library options, I'd start with dompdf and see if that works for you. Known limitations are the lack of support for flexbox or grid, so that might be a deal breaker. I probably wouldn't use mpdf, due to the age and lack of updates. It's a fork of fpdf. With that said, not unlike dompdf, if you constrain your html it might be fine for your use case, but the lack of updates is not a great sign. Along those same lines, lots of people are still using Snappy https://github.com/KnpLabs/snappy particularly with Laravel or Symfony, since there are integrations for both of those, but it does depend on a https://wkhtmltopdf.org/ which is now a dead project, even though you can still get builds of it for most linux distros.
  10. See gw1500se and mac_guyver's posts, and implement those changes. One other thing I noted in your code, is that when you mix PHP and HTML, it's best to use PHP Alternative syntax for control structures. For the if -then - else section of your code, here is how you would change that. <?php if ($isadmin): ?> <ul class="navbar-nav"> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle text-dark" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> Hello, <?= $thename ?> </a> <ul class="dropdown-menu" aria-labelledby="navbarDropdown"> <li><a class="dropdown-item" href="main.php">TLS Materials</a></li> <li><hr class="dropdown-divider"></li> <li><a class="dropdown-item" href="logout.php">Logout</a></li> </ul> </li> </ul> <?php elseif ($authenticated): ?> <img src='/files/<?=$theimage ?>' width="75px"> <ul class="navbar-nav"> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle text-dark" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"><?= $thename ?> </a> <ul class="dropdown-menu" aria-labelledby="navbarDropdown"> <li><a class="dropdown-item" href="profile.php">My Profile</a></li> <li><a class="dropdown-item" href="main.php">TLS Materials</a></li> <li><hr class="dropdown-divider"></li> <li><a class="dropdown-item" href="logout.php">Logout</a></li> </ul> </li> </ul> <?php else: ?> <ul class="navbar-nav"> <li class="navbar-item"> <a href="register.php" class="btn btn-outline-primary me-2">Register</a> </li> <li class="navbar-item"> <a href="login.php" class="btn btn-primary">Login</a> </li> </ul> <?php endif; ?>
  11. strtotime() returns a unix timestamp value. Timestamps are an integer value which is the number of seconds since the January 1, 1970 00:00:00 UTC. Helpers like "+10 minute" are nice for abstraction, but all the minute addition does is add (minutes * 60) to the value. So you might note that this code will print "Same". $t1 = strtotime("now") + 10 * 60; $t2 = strtotime("+10 Minute"); if ($t1 == $t2) { echo "Same\n"; } An important limitation of strtotime is that it doesn't have any concept of timezone, so in most cases you should use PHP DateTime classes, which do allow you to account for timezones and translate between them. You also need to be aware of what the configured locale settings of your server are. In most cases servers should be setup to be UTC, and thus datetime values set in the database will also be UTC. This is the best practice. When you develop your application you want to be aware of the server and PHP settings, and translate the date/time values at presentation time, by applying the desired timezone relevant to your server or the client.
  12. Agree strongly with this advice. I would also suggest looking at Symfony Mailer.
  13. Don't do that. Under no circumstances should the session storage location be under the web root. So first of all, the session does not "timeout" after 30 minutes. Most likely your shared host has a cron job that is going through the directories where session files are stored and deleting any session files that haven't been updated (the mtime) in over 30 minutes. Normal session file garbage collection is highly dependent on having a certain amount of requests, such that the garbage collector actually runs. You should be able to do this. If it doesn't work, then I wouldn't use the feature. Hard to say for sure, but you should check the value of gc_probability. Some OS's like Debian set it to 0, and use os level scripts to remove session files. As I stated above, it does sound like this might be the case with your host. A site with very low traffic is unlikely to run the session garbage collector in any reliable manner.
  14. This isn't directly related to your question, but you should consider using cloudflare that will give you a free CDN/Edge cache for your site, increasing performance and saving you bandwidth. Going to assume that your app is using PHP Sessions. If so, you need to review this setting as a first step. The only other thing I can suggest is that in a case like this, is that hopefully you have a mac, and can use a cable to connect to the phone and use the safari develop menu. I'd also likely open a tail on the server so I can see the requests coming into the server. You certainly want to question your assumptions as to what is happening as the app runs. The typical complaint in regards to safari is not lack of caching but the opposite -- aggressive caching that makes it hard to unload/clear the cache when developing/testing. Your server environment is also an essential component with different options that can be used to configure the server (apache/nginx/etc) in how it handles different types of files.
  15. So it's something that you put in header.php that you didn't show the code for. You need to understand that when you print something out, the browser sends an HTTP response to the request. Thus the HTTP header is composed and sent. This is not the way to do a redirect -- using meta refresh. You should be doing that in the HTTP header using a location, and that code should be followed by an exit. <?php session_start(); if (!empty($_SESSION['admin'])) { header('Location:/login.php'); exit(); } // This user is admin
  16. RewriteEngine on RewriteCond %{HTTPS} !=on RewriteCond %{HTTP_HOST} ^www.thelogos.net$ RewriteRule ^(.*)$ https://thelogos.net$1 [R=301,L]
  17. Hopefully, it's clear to you that Barand's solution and the one I presented are the same, only Barand used a 100% functional approach, and a lambda (anonymous function) passed to array_map. Compare/contrast the two solutions, and if you can understand them both, you'll have a good basis for solving future problems like this. One thing I would note about these solutions, is that any solution is only as good as its suitability to the data. For example, if the names can have suffixes like jr, sr, 3rd etc, you'll probably not get what you want. They could be improved to handle those situations, should the data you're working with warrant it. Using PHPUnit to create unit tests for code like this is a really valuable investment, if you care about testing, maintainability and quality.
  18. I strongly recommend that you change all of your tables to use the InnoDB engine. It's currently the default engine, given that it provides superior performance and features. Any aspect of a table can be changed (no dropping required) using the ALTER TABLE syntax.
  19. I really have no context with which to give you a "best solution" but a longstanding way of handling this is to have the customer website utilize an iframe that wraps your hosted site.
  20. To a degree, because you can create your desired list/count in one pass through the array. <?php $names = ['bob_jones', 'sam_smith', 'jane_doe', 'john_smith', 'jill_jackson', 'matt_jones', 'john_doe', 'emily_smith']; $lastNames = []; foreach ($names as $name) { $lname = substr($name, strpos($name, '_') +1); if (array_key_exists($lname, $lastNames)) { $lastNames[$lname]++; } else { $lastNames[$lname] = 1; } } var_dump($lastNames);
  21. From the way the question was worded, it doesn't appear that the data is in a relational database.
  22. As requinix stated, not really with css, because css "styles" markup. You could inject an additional DOM element using javascript. I'm not suggesting that is a good idea, but it would work fine, especially if this "row" is static.
  23. If the form is a "web form" then host it, and store the data within your own infrastructure, and you've accomplished SaaS, with all the benefits of code ownership we've discussed. You do need to account for the fact that you'll be paying for hosting. There are many solid/reputable hosting companies that provide a virtual server with room to grow your application, where you'll know your price in advance. You also want the server to be in a DC that is co-located near to your customer, and these mid size hosting companies tend to have that type of coverage. Linode, Vultr, Hetzner and Contabo are a few of the better known companies with track records to compare and contrast. I would highly advise against using shared hosting. Given that you will be running a monolithic architecture, I'd suggest looking at 8gb vps's to give you room to run the mysql database as well as your webserver/php stack.
  24. I don't really want to guess at what the application is, but SaaS would entail you hosting the application on your infrastructure and the customer using the functionality you provide within the app as an end user. There's no subterfuge involved in it. If there's some reason that a user would believe they were tricked in some way, then it's not SaaS.
  25. If you're developing code for someone at a cost, typically they would expect to own that code or a license to that code in return for the payment they are making to you. Generally speaking, the "data" for a system is the property of the customer/business using your system. It's not unusual for companies to provide a separate "maintenance" agreement that covers a period of time, wherein the customer would pay you an amount to enhance it and fix bugs. You also could provide the system in a Software as a Service model, where you host the system and code, and provide the customer access to the application, without otherwise providing the system level access they would need to even see the code. As far as pricing, there are many ways to estimate and cost projects. Understandably companies tend to like to know a price for something, so you need to have a decent idea of what amount of time it will take you to build the features. You make this estimation in "ideal" time, which is the amount of time any feature might take if you are head-down and fully productive. Then add a reasonable amount of overhead to your ideal estimate (anywhere from 10-35% is not uncommon). Determine a reasonable market rate for your time, and in combination, you'll have a "by feature" estimate you can utilize as a fix bid, with associated milestones. Any project like this should involve a contract.
×
×
  • 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.