The following code should check if either a # or # symbol has been found in a string. The regex should find each and every # or # (kind of like Twitter does)and should either place each instance it found into the messages table (if it was an # symbol), or if it was a # symbol it should insert the instance into the hashtags table or update an existing record if the hashtag is already in the table.
Currently, the script itself works fine, but when using the code with javascript through AJAX, the console responds by saying the requested entity (this script) is too large (or something of that caliber). I'd assume its getting stuck in an endless loop, but so far I haven't found a (working) better way to do this. So, what would be a better way of coding this?
if (preg_match_all("/[#]+[A-Za-z0-9-_]+/i", $post, $matches)) {
for ($i = 0;$i <= $matches;$i++) {
$match = str_replace("#", "", $matches[$i]);
foreach($match as $key=>$mVal) {
$uMSQL = "INSERT INTO `messages` (`to`, `from`, `message`, `sent`) VALUES (:to, :from, '<p>tagged you in a post</p>', NOW())";
$uMQ = $con->prepare($uMSQL);
$uMQ->bindParam(':from', $author, PDO::PARAM_STR);
$uMQ->bindParam(':to', $mVal, PDO::PARAM_STR);
$uMQ->execute();
}
}
}
if (preg_match_all("/[#]+[A-Za-z0-9-_]+/i", $post, $hashtags)) {
for ($h = 0; $h <= $hashtags; $h++) {
$htMatched = $hashtags[$h];
foreach($htMatched as $key=>$htVal) {
$htCheck = "SELECT COUNT(hashtag) FROM `hashtags` WHERE `hashtag` = '$htVal'";
$htQ = $con->query($htCheck);
$htExistence = $htQ->fetchColumn();
if ($htExistence >= 1) {
$addTU = "UPDATE `hashtags` SET `used` = used+1 WHERE `hashtag` = '$htVal'";
$updateHT = $con->exec($addTU);
} else {
$htMSQL = "INSERT INTO `hashtags` (`hashtag`) VALUES (:hashtag)";
$htMQ = $con->prepare($htMSQL);
$htMQ->bindParam(':hashtag', $htVal, PDO::PARAM_STR);
$htMQ->execute();
}
}
}
}
AJAX
function sendData() {
var hr = new XMLHttpRequest();
var url = "http://localhost/NextIt/ajax/sendPost.php";
var txtField = window.frames['richTextField'].document.body.innerHTML;
var access = document.getElementById('postTo').selectedIndex;
var acc = document.getElementById('postTo').options;
var accss = acc[access].text;
var vars = "post="+txtField+"&access="+accss;
hr.open("POST", url, true);
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
hr.onreadystatechange = function() {
if (hr.readyState === 4 && hr.status === 200) {
var return_data = hr.responseText;
$('status').innerHTML = return_data;
window.frames['richTextField'].document.body.innerHTML = '';
}
}
hr.send(vars);
$('status').innerHTML = "Posting...";
}
The post_max_size is 8M.
Related
I need to send JSON data to a MySQL database, but when I am trying to do this, my code only sends "{"0":"A" to the MySQL database.
Here is my code:
JavaScript
<span id="start_button_container">Send and start</span>
const allCards = {
'0':'A ♦','1':'A ♥','2':'A ♣','3':'A ♠',
'4':'10 ♦','5':'10 ♥','6':'10 ♣','7':'10 ♠',
'8':'K ♦','9':'K ♥','10':'K ♣','11':'K ♠',
'12':'Q ♦','13':'Q ♥','14':'Q ♣','15':'Q ♠',
'16':'J ♦','17':'J ♥','18':'J ♣','19':'J ♠'
};
let userInTable = localStorage.getItem( 'saved_user' );
if (userInTable) { // Save user and find table onclick START
saveUser.style.display = 'none';
hello.textContent = "Hi " + userInTable;
start.onclick = () => {
if (userInTable) {
let x = new XMLHttpRequest();
let url = "php/findtable.php";
let data = JSON.stringify(allCards);
let params = "cards="+data+"&user="+userInTable;
x.open("POST", url);
x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
x.send(params);
x.onreadystatechange = () => {
if (x.readyState == 4 && x.status == 200) {
console.log(x.responseText);
}
}
}
}
}
Here is my PHP code:
if (isset($_POST["cards"],$_POST["user"])) {
$cards = $_POST["cards"];
$user = $_POST["user"];
$query = "INSERT INTO tables (u_1,all_cards) VALUES (?,?)";
if ($stmt = $conn->prepare($query)) {
$stmt->bind_param("ss", $user, $cards);
if ($stmt->execute()) {
print_r($cards);
}
}
}
What am I doing wrong?
The encodeURIComponent() function helped me a lot:
let data = JSON.stringify(encodeURIComponent(allCards));
If you/somebody still want to know why this happens, every ampersand (&) is a new input in a querystring. Meaning var1=value&var2=value&var3=value. Your JSON contains ampersands, so the parser thinks you are starting a new variable.
var1=value&var2={"a":"&2934;"}
^ This one starts a new variable
var2 contains {"a":"1 and processes 2934;"} as a new variable name.
encodeURIComponent escapes the ampersands, so the query string parser does not use it for division of variables.
This is a simple function that use AJAX and get information about an image in the database with id=219 when a button is clicked
Anyone loading this webpage can change the javascript code by going to the source code.
Then by clicking the button he will run the modified code (like changing image_id from 219 to 300). So he can get information about any image just by changing image_id
The question is how to protect against that client-side attack or XSS ?
function clicked () {
var xhttp = new XMLHttpRequest () ;
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200){
var obj = JSON.parse (this.responseText);
alert (obj.description);
}
};
xhttp.open ("POST","get_title_description.php", true);
xhttp.setRequestHeader ("Content-type", "application/x-www-form-urlencoded");
xhttp.send ("image_id=219") ;
}
You can use something like this for generating and validating the cookie:
define('COOKIE_TOKEN', 'my_token');
class BaseAuth
{
protected $uid;
private static function base64url_encode(string $s): string
{
return strtr($s,'+/=','-|_');
}
private static function base64url_decode(string $s): string
{
return strtr($s,'-|_','+/=');
}
// Encodes after encryption to ensure encrypted characters are URL-safe
protected function token_encode(String $string): string
{
$iv_size = openssl_cipher_iv_length(TYPE_CRYPT);
$iv = openssl_random_pseudo_bytes($iv_size);
$encrypted_string = #openssl_encrypt($string, TYPE_CRYPT, SALT, 0, $iv);
// Return initialization vector + encrypted string
// We'll need the $iv when decoding.
return self::base64url_encode($encrypted_string).'!'.self::base64url_encode(base64_encode($iv));
}
// Decodes from URL-safe before decryption
protected function token_decode(String $string): string
{
// Extract the initialization vector from the encrypted string.
list($encrypted_string, $iv) = explode('!', $string);
$string = #openssl_decrypt(self::base64url_decode($encrypted_string), TYPE_CRYPT, SALT, 0, base64_decode(self::base64url_decode($iv)));
return $string;
}
// performs log-out
public function clear_cookie()
{
setcookie(COOKIE_TOKEN, '', time() - 300, '/api', '', FALSE, TRUE); // non-secure; HTTP-only
}
private function userIP(): string
{
return $_SERVER['REMOTE_ADDR'];
}
// validates Login token
public function authorized(): bool
{
if(isset($_COOKIE[COOKIE_TOKEN]))
{
$stamp = time();
$text = $this->token_decode($_COOKIE[COOKIE_TOKEN]);
if($text != '')
{
$json = json_decode($text,TRUE);
if(json_last_error() == JSON_ERROR_NONE)
{
if($json['at'] <= $stamp AND $json['exp'] > $stamp AND $json['ip'] == $this->userIP() AND $json['id'] != 0)
{
// check if user account is still active
$res = $db->query("SELECT id,active,last_update,last_update > '".$json['last']."'::timestamptz AS expired FROM account WHERE id = ".$json['id']);
$info = $db->fetch_assoc($res);
if($info['active'] != 0)
{
if($info['expired'] == 0)
{
// extend the token lifetime
$this->sendToken($info);
$this->uid = $json['id'];
return TRUE;
}
}
}
}
}
$this->clear_cookie();
}
return FALSE;
}
public function login(String $username, String $password): bool
{
$stm = $db-prepare("SELECT id,user_name AS username,user_pass,full_name,active,last_update,COALESCE(blocked_until,NOW()) > NOW() AS blocked
FROM account WHERE user_name = :user");
$res = $stm->execute(array('user' => strtolower($json['username'])));
if($res->rowCount())
{
$info = $db->fetch_assoc($res);
if($info['active'] == 0)
{
// Account is disabled
return FALSE;
}
elseif($info['blocked'] != 0)
{
// Blocked for 5 minutes - too many wrong passwords
// extend the blocking
$db->query("UPDATE account SET blocked_until = NOW() + INTERVAL 5 minute WHERE id = ".$info['id']);
return FALSE;
}
elseif(!password_verify($password, $info['user_pass']))
{
// Wrong password OR username
// block account
$db->query("UPDATE account SET blocked_until = NOW() + INTERVAL 5 minute WHERE id = ".$info['id']);
return FALSE;
}
else
{
unset($info['user_pass']);
unset($info['blocked']);
$this->sendToken($info);
return TRUE;
}
}
}
}
If you do not need to authenticate and authorize your users and just need random unpredictable image IDs - you can simply use UUIDs.
Basically, what I'm trying to do is send a request to a separate .php file which queries my database. The problem occurs when trying to return an array as a variable type array. I need this, because I want to send it to another PHP when it is send to the HTML. In the second PHP file, I want to use a for-each-loop-statement in order to create some code, but this only takes arrays and not strings. I've tried a couple of things including the use of JSON in an attempt to fix this, but on return the array keeps turning into a string. Any help would be appreciated. Most relevant code is included below:
javascript:
function getEvents(){ //gets the events from the database
var req = new XMLHttpRequest();
var att = 1; //Just a filler because somehow this seems needed
var link = "IekjeConnector.php";
dataType:"json";
req.onreadystatechange = function() {
if(req.readyState === 4 && req.status === 200)
{
addEvents(JSON.parse(this.responseText)); //This should be a normal array
}
}
req.open("GET", link + "?att=" + att, true);
req.send();
}
function addEvents(events = ""){
var req = new XMLHttpRequest();
var link = "IekjeHome.php"; //sends to the next php
req.onreadystatechange = function() {
if(req.readyState === 4 && req.status === 200)
{ document.getElementById("event").innerHTML = this.responseText; }
}
req.open("GET", link + "?events=" + events, true); //events has the right value
req.send();
}
php:
if (filter_input(INPUT_GET, "events", FILTER_SANITIZE_STRING)) {
$events = filter_input(INPUT_GET, "events", FILTER_SANITIZE_STRING);
$length = count($events);
print_r(gettype($events));
foreach($events as $event)
{ echo $events[$count] . $events[$count+2]; }
}
The foreach returns an error that $events is a string as does the gettype().
I tried changing the way addEvents and the php-code receive the array, but i'm probably doing something wrong trying.
I think you need to change the string to array, for example using explode.
$events = filter_input(INPUT_GET, "events", FILTER_SANITIZE_STRING);
$events = explode(",",$events);
Instead of the ",", just put your event's separator.
I believe what you're looking for is JSON.parse(this.responseText).
I'm having trouble understanding with my code on how the php is actually communicate the server and pull information from the files. Because I don't really see where the full url is coming from. I'm very new to php so I'm at a loss. The code is displaying information from http://webster.cs.washington.edu/cse154/services/flashcards
but I don't really see where it goes about, specifically accessing those pathways, I don't see how to get information to create the new json and xmls. Like if I wanted to pull a txt file, let's say a made up website: http://jackson.hubert.com/coolstuff and coolstuff has the txt file how is this code getting that info? Sorry if this is a really stupid question
<?php
# Solution to CSE 154 Flashcard lab.
# generates a JSON list of categories if passed a parameter mode
# with the value of categories. Otherwise outputs a random question
# from the passed in category in XML.
$mode = $_GET["mode"];
$category = $_GET["category"];
$url = "../../cse154/services/flashcards/";
if($mode == "categories") {
outputJson($url);
} else {
outputXml($url, $category);
}
# outputs the list of available categories in JSON
function outputJson($url) {
$files = glob($url . "*");
$json = array("categories" => array());
foreach($files as $file) {
$count = count(glob($file."/*"));
$json["categories"][basename($file)] = $count;
}
header("Content-type: application/json");
print(json_encode($json));
}
# outputs a random question about the provided category in XML
function outputXml($url, $category) {
$files = glob($url . "$category/*");
$index = array_rand($files);
// this is a great place to use list!!
list($ques, $ans) = file($files[$index]);
$dom = new DOMDocument();
$card = $dom->createElement("card");
$dom->appendChild($card);
$question = $dom->createElement("question");
$question->appendChild($dom->createTextNode($ques));
$card->appendChild($question);
$answer = $dom->createElement("answer");
$answer->appendChild($dom->createTextNode($ans));
$card->appendChild($answer);
header("Content-type: text/xml");
print($dom->saveXML());
}
?>
/* javascript */
(function() {
var category = "computerscience";
var xml = null;
// sets up onclick handlers
window.onload = function() {
document.getElementById("viewAll").onclick = viewAll;
document.getElementById("next").onclick = next;
};
// sends an ajax request to the passed in address.
// calls the passed in function when the request returns.
function ajax($adress, $function) {
var request = new XMLHttpRequest();
request.onload = $function;
request.open("GET", $adress, true);
request.send();
}
// makes a request for all of the categories.
function viewAll() {
ajax("flashcards.php?mode=categories", displayAll);
}
// displays all categories in a list on the page.
function displayAll() {
$json = JSON.parse(this.responseText);
for($cat in $json.categories) {
var li = document.createElement("li");
li.innerHTML = $cat;
li.onclick = choose;
document.getElementById("categories").appendChild(li);
}
}
// sets a new category as the category all questions should come from.
function choose() {
category = this.innerHTML;
}
// displays the next question if it was last displaying an answer or nothing.
// displays the answer to the previous question otherwise.
function next() {
if(!xml) {
ajax("flashcards.php?category=" + category, displayNext);
} else {
document.getElementById("card").innerHTML = xml.querySelector("answer").textContent;
xml = null;
}
}
// displays the question that it recieved from the server.
function displayNext() {
xml = this.responseXML;
document.getElementById("card").innerHTML = xml.querySelector("question").textContent;
}
})();
I have the following AJAX code:
var ajax = new XMLHttpRequest();
axaj.open("POST", "index.php", true);
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajax.onreadystatechange = function(){
if(x.readyState == 4 && x.status == 200){
var returnVal = ajax.responseText;
}
}
ajax.send("nextMax=-1");
And pairs with some PHP that ends with:
echo json_encode(array(
'next_id' => $nextID
));
exit();
This all works, as it is. If I print out returnVal inside the AJAX call, it prints out the correct array, with the correct value:
{"next_id":"935210077606657948"}
But I cannot access the id directly. I've tried
var nextID = returnVal.next_id;
and
var nextID = returnVal['next_id'];
and other variations, but all return undefined.
How do I get the array elements from within returnVal?
Thanks in advance.
Found a solution not 30 seconds after posting the question. But for those who are in the same place:
Switch
var returnVal = ajax.responseText;
to
var returnVal = JSON.parse(ajax.responseText);
and then the call works:
returnVal.next_id;