-
Posts
4,704 -
Joined
-
Last visited
-
Days Won
179
Everything posted by kicken
-
No, as noted in my reply: The XModem protocol for sending wouldn't be too hard to implement, just as receive wasn't. What would be more difficult is dealing with the serial connection to your device. You'd likely have to create a script that can connect to your device and issue whatever commands are necessary to get it ready to receive. That would be a more complex task and likely have to be tailor made to your device. I don't think it's impossible to do, PHP is capable of dealing with serial connections. I simply don't currently have any xmodem capable serial devices to mess with (did the receive bit over ssh), nor do I really have much free time to continue messing with it.
-
Problem allowing users to download files from my website
kicken replied to foxclone's topic in PHP Coding Help
Flip your if statement so that it checks if the file does not exist and if that is true, exit. if (!file_exists($l_filename)){ exit; } //... While testing, it's easier if you use text files, then you can easily see the results and any potential errors directly in the browser. Once you have it working with the text files you can try binary files. As mentioned before, you also need to validate the filename selected or someone could use your code to download any of your files, not just the ones you intend. If you want to only allow the files within the folder to be downloaded, then you could use basename so the user only inputs a file name and not a directory, then combine that with __DIR__ to make a full path. $file=basename($_GET['f']); $file=__DIR__.'/'.$file; -
I was interested since I've actually used Xmodem a couple times in the last year. Implementing the protocol was easy enough, figuring how terminal settings to make it actually work was more of a pain. It's not pretty, but here's a receive implementation (with the help of this crc library) <?php class XModem { const SOH = "\x01"; const EOT = "\x04"; const ACK = "\x06"; const NAK = "\x15"; const CAN = "\x18"; const C = "C"; private $channel; private $channelBuffer; private $outFile; private $lastPacketData; /** * @param resource $channel * @param resource $file * * @return void */ public function receive($channel, $file){ $this->channel = $channel; $this->outFile = $file; stream_set_blocking($channel, false); $lastPacketNumber = 0; do { $packet = $this->readPacket(); if (!$packet){ if ($lastPacketNumber === 0){ $this->writePacket(self::C); } else { $this->writePacket(self::ACK); } continue; } if ($packet[0] === self::SOH){ $packetNumber = $this->packetNumber(substr($packet, 1, 2)); $data = substr($packet, 3, 128); $receivedCRC = substr($packet, -2); $calculatedCRC = $this->calcCRC($data); if (($packetNumber === $lastPacketNumber + 1 || $packetNumber === 0 && $lastPacketNumber === 255) && $calculatedCRC === $receivedCRC){ $lastPacketNumber = $packetNumber; $this->updateReceiveFile($data); $this->writePacket(self::ACK); } else { $this->channelBuffer = ''; $this->writePacket(self::NAK); } } else if ($packet[0] === self::CAN){ $lastPacketNumber = 0; fseek($file, 0); ftruncate($file, 0); $this->writePacket(self::C); } else if ($packet[0] === self::EOT){ $this->finishReceiveFile(); $this->writePacket(self::ACK); } } while (!feof($channel) && !$packet || $packet[0] !== self::EOT); } private function updateReceiveFile($data){ if ($this->lastPacketData){ fwrite($this->outFile, $this->lastPacketData); } $this->lastPacketData = $data; } private function finishReceiveFile(){ fwrite($this->outFile, rtrim($this->lastPacketData, "\x1a")); } private function readPacket(){ $packetType = $this->readChannelBuffer(1); if ($packetType === self::SOH){ $pn = $this->readChannelBuffer(2); $data = $this->readChannelBuffer(128); $crc = $this->readChannelBuffer(2); $packet = $packetType . $pn . $data . $crc; } else { $packet = $packetType; } return $packet; } private function readChannelBuffer($length){ $startTime = time(); while (strlen($this->channelBuffer) < $length && time() - $startTime < 10){ if (!$this->bufferInput()){ usleep(100); } } $data = substr($this->channelBuffer, 0, $length); $this->channelBuffer = substr($this->channelBuffer, $length); return $data; } private function bufferInput(){ $byteCounter = 0; do { $r = [$this->channel]; $w = $e = []; $readable = stream_select($r, $w, $e, 0, 0); if ($readable){ $dataRead = stream_get_contents($this->channel); $byteCounter += strlen($dataRead); if ($dataRead){ $this->channelBuffer .= $dataRead; } } } while ($readable); return $byteCounter > 0; } private function writePacket($data){ $total = strlen($data); $written = 0; do { $dataToWrite = substr($data, $written); $written += fwrite($this->channel, $dataToWrite); fflush($this->channel); } while ($written < $total); } private function packetNumber($pnBytes){ $n1 = ord($pnBytes[0]); $n2 = ord($pnBytes[1]); if ($n1 + $n2 !== 255){ return null; } return $n1; } private function calcCRC($data){ $o = new mermshaus\CRC\CRC16XModem(); $o->update($data); return $o->finish(); } } Requires some terminal setup to work properly. I eventually included this code in my test script to fix terminal problems, but it creates it's own problems (can't ctrl+c the script). system('/usr/bin/stty -cooked -echo'); register_shutdown_function(function(){ system('/usr/bin/stty cooked echo'); }); I'll leave implementing send and other improvements for the reader.
-
Protocol seems simple enough, you could probably create an implementation of it without a lot of work.
-
get_class_methods doesn't return all methods
kicken replied to NotionCommotion's topic in PHP Coding Help
Yea, It's briefly noted in the documentation for the Iterator class. I first noticed this behavior when working with FilterIterator. Seems kind of strange and dumb to me, but oh well. -
You could just read the results into an array, then use that for your two loops. $query = "SELECT colname FROM table"; $result1 = $db->SelectLimit($query,10,-1); $resultData=[]; while (!$result1->EOF) { $resultData[]=$result1->Fields('colname'); $result1->MoveNext(); } // 1ST RUN foreach ($resultData as $colname){ echo $colname.'<br>'; } // 2ND RUN foreach ($resultData as $colname){ echo $colname.'<br>'; }
-
Yes, you can use variables in your path, so you could define a separate prefix for each environment. However, usually it's easier to use the built in __DIR__ constant and build a path that's relative to the current file. For example: include(__DIR__.'/my_file.php');
-
If you install it on the target system with composer, then composer will install whichever version of the package is compatible automatically, just make sure you have your version constraint for the package setup correctly. If you're trying to pre-package a release and want to make a 5.6 version and 7.1 version, you could have both version of PHP installed and run composer with the appropriate version.
-
You have output before the session_start call. Probably blank lines before your <?php tag. Remember, anything outside of php tags is output sent to the browser, even blank lines/spaces.
-
if($subject='') { $error_message .= 'You must select a Category.<br />'; } This is incorrect code, as you're assigning an empty string to $subject rather than comparing to one. The if won't trigger because an empty string is a false-like value, but your subject will be blank in the email. You need to use double-equals (==) for comparison. if(($subject)!=('Questions'||'Report Problem'||'Suggestion'||'Other'||'Website Problem')) { $error_message .= 'The Category you entered is invalid.<br />'; } This is incorrect code, as you cannot compare against multiple values in that way. If you wanted to test against multiple values, you need to repeat the variable name and condition for each one, as in: if ($subject != 'Questions' || $subject != 'Report Problem' || ...){ That would be correct code, but incorrect logic as it would end up being always true. If $subject == 'Questions', then it's != 'Report problem' and the condition is true. Likewise, if $subject == 'Report Problem', it is != 'Questions' and the condition is true. The correct logic would be to use and (&&) as in if ($subject != 'Questions' && $subject != 'Report Problem' && ...){ Alternatively, in this type of situation, you can use the in_array function and check against an array of values. This is shorter and more similar to your original code. if (!in_array($subject, ['Questions', 'Report Problem', ...])){ Finally, $string_exp = "/^[A-Za-z .'-]+$/"; if(!preg_match($string_exp,$name)) { $error_message .= 'The Name you entered does not appear to be valid.<br />'; } While this is not incorrect like the others, it's generally recommended to not try and validate a persons name (beyond something like maximum length / not blank). There's really no specific format for a persons name to validate against, and doing so means you'll always end up eventually telling someone that their name is not valid.
-
source: Mysql Manual - 13.2.10.2 JOIN Clause Your query would be interpreted as if it were: select * from trk_races a inner join drivers d left outer join ( select race_winner, count(race_date) as wins from trk_races where race_winner > '' and Season='$selyr' group by race_winner ) w on w.race_winner = a.race_winner on 1=1 Essentially your left join becomes like a sub-join of the drivers table. When you do a join like that you can only reference the parent join table (d) or some same-level sibling table (none here) in your on clauses. Table a does not meet either of those conditions (it's a sibling of the parent) so it's invalid in your left join's ON clause. In case it's unclear, when I say sibling tables I mean something like this. select * from a left join b inner join c on c.Id=b.cID inner join d on d.Id=c.dID on a.Id=b.aID Table c is a sibling to table d, so it can be used in the on condition, as can table b as it's the parent table. Table a cannot because it's the parent's sibling.
-
Are you sure you're getting results from your query? Your query/code doesn't make a whole lot of sense anyway. Your querying for records where SubRenew = 30, and the only data you're using as a result of that query is the SubRenew column which is guaranteed to be 30 at that point so why bother?
-
As mentioned, you have a lot of unnecessary PHP tags. You're also missing a closing brace for your if statement and have a typo in your variable name ($results vs $result). You also don't need to recreate the mailer object on every loop iteration as you go through the query results. You can move it's creation and iteration further up the script then just send emails in the loop. <?php // Import PHPMailer classes into the global namespace // These must be at the top of your script, not inside a function use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; //Load Composer's autoloader require 'vendor/autoload.php'; require 'database.php'; $mail = new PHPMailer(true); $mail->SMTPDebug = 2; $mail->isSMTP(); $mail->Host = 'smtp.example.com'; $mail->Port = 587; $mail->SMTPSecure = 'TLS'; $mail->SMTPAuth = true; $mail->Username = 'username'; // SMTP username $mail->Password = '***'; // SMTP password (NB Dummy password) //From $mail->setFrom('username@example.com', 'User'); $mail->addAddress('username@example.com', 'User'); // Add a recipient $result=mysqli_query($conn,"SELECT * FROM customersubscriptions WHERE SubRenew =30"); if (mysqli_num_rows($result) > 0) { $i=0; while($row = mysqli_fetch_array($result)) { try { //Content $mail->isHTML(true); // Set email format to HTML $mail->Subject = 'Contact Us Message'; $mail->Body = "The new password is " . $row['SubRenew'] . "."; $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; $mail->send(); } catch (Exception $e) { echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo; } } } header('Location: tempage.php'); If you need to send mail to an email address that you pull from your database, move the call to addAddress into the loop and add a call to clearAddresses.
-
Telnet response does not output all data (using PHPTelnet Class)
kicken replied to jaybo's topic in PHP Coding Help
You'd use the same do/while loop construct to read lines from the socket, but instead of the while condition using the unread_bytes value, you test if the last line that was read is the marker you are interested in. For example: function GetResponse(&$r) { $r = ''; do { $line = fgets($this->fp); $r .= $line; } while (!preg_match('/\d{1,4} Bridge Interfaces displayed/', $line)); } -
How to call several methods of a class instance?
kicken replied to vav214's topic in PHP Coding Help
You can call two methods like that no problem. Just make sure you have the name of the method correct (sendMailToClient vs sendMailToCustomer). -
I'm getting a Forbidden error on my local server
kicken replied to foxclone's topic in Apache HTTP Server
From PHP's include_path configuration. The error message you show doesn't match the code you posted. The error shows '../php' but the code shows '../../php'. You need to get your path fixed, whatever you have is incorrect. When it comes to requiring files, it's usually best to use __DIR__ and build a path from there. For example, if your code file is /var/www/foxclone/public_html/index.php and you want to include the file /var/www/foxclone/php/PDO_Connection_Select.php, you'd do this: require __DIR__.'/../php/PDO_Connection_Select.php' -
I'm getting a Forbidden error on my local server
kicken replied to foxclone's topic in Apache HTTP Server
You probably have another/default host that is declaring the document root /var/www/html. You could either find that configuration and remove it, or create that directory. Your error log should have some indication as to what the problem is. Either in the one you defined (/var/log/apache2/foxclone-error.log), a default one (probably /var/log/apache2/error.log), or if the 500 error is related to a PHP problem then in PHP's error log. -
I'm getting a Forbidden error on my local server
kicken replied to foxclone's topic in Apache HTTP Server
Look in the error log, see if it has any additional information about why it's returning that response. Could be a file permission problem, apache might not have permission to read /var/www/foxclone/public_html. -
When daylight savings goes away
kicken replied to fastsol's topic in PHP Installation and Configuration
The DST information would be part of the timezone database. From what I can tell, PHP includes a bundled copy of this so you'd generally just update PHP to get an updated copy of the database. There is a PECL extension you can use to update the database independently. If you keep things up to date then there shouldn't be anything to worry about I believe. -
First only returns a single item, so there's no point in putting it in a collection. The collection is for methods that might return several items.
-
I'd appreciate some feedback about my website design
kicken replied to foxclone's topic in Website Critique
Your links on the upper right are easy to overlook on the home page, I didn't notice them for a bit. I agree with the color not being ideal either for having them directly on the image. I'm not sure any color would work. I would suggest keeping the black bar like you have on the other pages. It would make them more noticeable, easier to read, and the site more consistent. The home page overflows the window content for me on 1920x180 due to your copyright footer. This results in scrollbars which make the whole thing just look poor. Make your footer overlay the image rather than show below it so the scroll bars do not appear. I'd also suggest using a solid color background that spans the page width for the footer similar to the black header you have on the other pages. You have some HTML errors on various pages. I'd suggest running them all through the validator and fixing the problems found. -
Telnet response does not output all data (using PHPTelnet Class)
kicken replied to jaybo's topic in PHP Coding Help
Unless the telnet server disconnects the socket at the end of your command, feof will not be helpful as the socket does not enter an EOF state until it is disconnected. What you need to do is watch the incoming data for an input prompt or some kind of identifier that you can use to know when the command has completed. That's exactly what that newer library linked above does. My suggestion would be that you abandon the current class you're using and adapt your code to the newer library. Yes, it sucks having to update a bunch of code but sometimes it just needs to be done. If you really don't want to switch libraries, you could try modifying your class to read from the socket until a particular marker is seen. -
Varnish is a caching server. You stick it in front of your http server and it caches responses to speed things up.
-
The # just signifies an ID, like how . signifies a class. So #font would be whatever element has the attribute id="font", while .font would be any element with class="font". ID's must be unique within a document, classes can be reused any number of times. ID's also have a higher priority than classes in the case of conflicting rules. You should probably just read up on CSS Selectors and get familiar with them.
-
convert GET to POST (and AVOID $_SESSIONS !!! )
kicken replied to ChenXiu's topic in PHP Coding Help
The only way to solve that is with $_SESSION. Track the user's priced items there so the data is available regardless of how they arrive at your site. Trying to pass data from page to page via POST is just as disaster prone, if not more so, than working with sessions. It's also not friendly to multi-tabbed use of your site. For example, open several items in a new tab for comparison then add one of them to the list and close the tab, go to the next tab, add the item. The one you just added in the previous tab would be gone.