CodeIgniter Captcha value munged by session userdata? - codeigniter

I'm attempting to store a CodeIgniter captcha helper challenge word in a Session variable, as follows:
$cap = create_captcha($val /* array of params */); // Works fine
$this->session->set_userdata('cap-word', $cap['word']);
If I echo $cap['word'] before and after the session set, it is correct (i.e. what was displayed in the browser). If I retrieve the session variable immediately after setting it, it's also correct.
However what gets stored in the session is completely different - it's the right length (character count) but a totally different string. Hence, when I try to retrieve the userdata on the server side (captcha validation) it gets the wrong value.
(I'm configured for 'sess_use_database' and inspecting the user data values in phpMyAdmin after each page load. Cookie encryption is disabled.)
Debug attempts:
I've tried prepending / appending known strings to the captcha challenge word before storing it in the session. The known strings make it into the session user data just fine, but are prepended / appended to an incorrect captcha word.
I've tried replacing the challenge word entirely with a fixed string. This makes the round trip through the session no problem.
I've tried saving the captcha challenge word to a different string variable (rather than passing it directly from $cap['word]') with the same result; only the challenge portion gets "munged" on landing in the session.
After debugging, my code looks more like:
$cap = create_captcha($vals);
echo("<br>cap = ");
print_r($cap);
echo("<br>cap['word'] = " . $cap['word']);
$theword = $cap['word'];
echo("<br> Before theword = " . $theword);
$this->session->set_userdata('cap-word', $theword . 'abcdefg');
echo("<br> After theword = " . $theword);
echo("<br> Session output = " . $this->session->userdata('cap-word'));
This produces the following output in the browser:
cap = Array ( [word] => 5CZaDeHm [time] => 1436765602.678 [image] =>
{the image})
cap['word'] = 5CZaDeHm
Before theword = 5CZaDeHm
After theword = 5CZaDeHm
Session output = 5CZaDeHmabcdefg
However, what's stored in the session table userdata fields (and, thus, what pops out when I call $this->session->userdata('cap-word') on submit request) is:
a:2:{s:9:"user_data";s:0:"";s:8:"cap-word";s:15:"3g5hb1I3abcdefg";}
Hence, the substring '5CZaDeHm' within $theword has been seemingly replaced by '3g5hb1I3' during the call to $this->session->set_userdata. I have no idea why, or even how this is possible?!
Update 2015-07-13 07:50 EDT: As usual, Occam's Razor applies. Turns out on each page load, my controller is being called twice, generating 2 captcha images with 2 corresponding challenge words. One of these appeared in the browser, the other in the session's database row. Now to figure out why...

Turns out the CodeIgniter controller was being called twice because I used a relative path in the href parameter of a CSS tag. This resulted in the browser attempting to load the stylesheet relative to the page, which triggered a 2nd load of the page.

Related

Using JobQueue to continuously refresh a message

I'm building a Telegram bot that uses ConversationHandler to prompt the user for a few parameters and settings about how the bot should behave. This information is stored in some global variables since it needs to be available and editable by different functions inside the program. Every global variable is a dictionary in which each user is associated with its own value. Here's an example:
language = {123456: 'English', 789012: 'Italian'}
where 123456 and 789012 are user ids obtained from update.message.from_user.id inside each function.
After all the required information has been received and stored, the bot should send a message containing a text fetched from a web page; the text on the web page is constantly refreshed, so I want the message to be edited every 60 seconds and updated with the new text, until the user sends the command /stop.
The first solution that came to my mind in order to achieve this was something like
info_message = bot.sendMessage(update.message.chat_id, text = "This message will be updated...")
...
def update_message(bot, update):
while True:
url = "http://example.com/etc/" + language[update.message.from_user.id]
result = requests.get(url).content
bot.editMessageText(result, chat_id = update.message.chat_id, message_id = info_message.message_id)
time.sleep(60)
Of course that wouldn't work at all, and it is a really bad idea. I found out that the JobQueue extension would be what I need. However, there is something I can't figure out.
With JobQueue I would have to set up a callback function for my job. In my case, the function would be
def update_message(bot, job):
url = "http://example.com/etc/" + language[update.message.from_user.id]
result = requests.get(url).content
bot.editMessageText(result, chat_id = update.message.chat_id, message_id = info_message.message_id)
and it would be called every 60 seconds. However this wouldn't work either. Indeed, the update parameter is needed inside the function in order to fetch the page according to the user settings and to send the message to the correct chat_id. I'd need to pass that parameter to the function along with bot, job, but that doesn't seem to be possible.
Otherwise I would have to make update a global variable, but I thought there must be a better solution. Any thoughts? Thanks.
I had the same issue. A little digging into the docs revealed that you can pass job objects a context parameter which can then be accessed by the callback function as job.context.
context (Optional[object]) – Additional data needed for the callback function. Can be accessed through job.context in the callback. Defaults to None
global language
language = {123456: 'English', 789012: 'Italian'}
j=updater.job_queue
context={"chat_id":456754, "from_user_id":123456, "message_id":111213}
update_job = job(update_message, 60, repeat=True, context=context)
j.put(update_job, next_t=0.0)
def update_message(bot, job):
global language
context=job.context
url = "http://example.com/etc/" + language[context["from_user_id"]]
result = requests.get(url).content
bot.editMessageText(result,
chat_id = context["chat_id"],
message_id = context["message_id"])

Laravel Former input field posted with empty value shows old (original) value instead of empty input field

I'm having some trouble using the Former plugin for Laravel, to handle forms & fields.
The use-case is an "edit"-form for a given model.
Former::text('title')
->label('Title')
->value( $title );
Former::text('description')
->label('Description')
->value( $description );
Rules:
The title must always exist and be at least 10 chars long.
The description may be empty.
Expected behaviour:
When loading the edit form, I expect the form to show the values of $title and $description in the fields.
Whenever submitting a the form with invalid field-values, I expect the submitted values to be shown in the fields, instead of the values of $title and $description.
Problem:
This works only when submitting non-empty strings!
When submitting an empty-string, it's like Former handles it like the field-hasn't even been submitted, and therefore uses the value given by $title or $description instead.
I thought Former was able to do this "smart", and take the value($variable) value only if the posted data does not contain the field. But it seems Former is taking the variables value also when the submitted was empty.
Why is this a problem?
Imagine you edit both fields, and actually want to change the title and remove the description entirely, which is valid according to the rules. Then, because you entered a too short title, the validation does not pass, and title will get the new (too short) title as field-value, while the description value will fall back to the value of the $description variable, instead of showing an empty field, which was posted.
It feels like $_POST['description'] = "" is treated like $_POST['description'] = null or is not set - even though the empty field is part of the post.
In your view
//replace
Former::text('title')
->label('Title')
->value( $title );
//with
Former::text('title')
->label('Title')
... and in your controller
//add
Former::populate($model);
$model beeing the model in question :)
$model->title must ofc exist and have the same value as $title in your original code.
if you use ->value($somevalue) with Former, $somevalue will allways be used.

My FormIt hook gets cached and it's screwing up every run after the 1st

I have the following snippet code hooked up to a FormIt email form:
$tv = "taken" . (int)$hook->getValue('datetime');
$docID = $modx->resource->get('id'); //get the page id
$page = $modx->getObject('modResource', $docID);
$current = (int)$page->getTVValue($tv);
if (!$page->setTVValue($tv, $current + 1)) {
$modx->log(xPDO::LOG_LEVEL_ERROR, 'There was a problem saving your TV...');
}
$modx->setPlaceholder('successMessage','<h2 class="success">'.$current.'</h2>');
return true;`
It increments a template variable every time it is run and outputs a success message (although right now I'm using that functionality to output a debug message instead). The problem is, it only increments the TV once after saving the snippet, thereby refreshing the cache. Normally I would call the snippet without cache by appending ! to its name, but that doesn't appear to work for FormIt hooks. How can I get this code to work? Right now I'm running the entire page as uncacheable, but that is obviously suboptimal. Perhaps, there's a way to hook a snippet in an uncached manner? Call a snippet from within a snippet as uncached?
I'm doing something similar - but to count page loads, it looks to me like you are missing the last little bit: $current->save();
<?php
$docID = $modx->resource->get('id');
$tvIdm = 32;
$tvm = $modx->getObject('modTemplateVar',$tvIdm );
$tvm->setValue($docID, $tvm->getValue($docID) + 1 );
$tvm->save();
Try add this before you save $tv object
$tv->_processed = false;
It's derived from modElement's property it extends.

Ruby script for posting comments

I have been trying to write a script that may help me to comment from command line.(The sole reason why I want to do this is its vacation time here and I want to kill time).
I often visit and post on this site.So I am starting with this site only.
For example to comment on this post I used the following script
require "uri"
require 'net/http'
def comment()
response = Net::HTTP.post_form(URI.parse("http://www.geeksforgeeks.org/wp-comments-post.php"),{'author'=>"pikachu",'email'=>"saurabh8c#gmail.com",'url'=>"geekinessthecoolway.blogspot.com",'submit'=>"Have Your Say",'comment_post_ID'=>"18215",'comment_parent'=>"0",'akismet_comment_nonce'=>"70e83407c8",'bb2_screener_'=>"1330701851 117.199.148.101",'comment'=>"How can we generalize this for a n-ary tree?"})
return response.body
end
puts comment()
Obviously the values were not hardcoded but for sake of clearity and maintaining the objective of the post i am hardcoding them.
Beside the regular fields that appear on the form,the values for the hidden fields i found out from wireshark when i posted a comment the normal way.I can't figure out what I am missing?May be some js event?
Edit:
As few people suggested using mechanize I switched to python.Now my updated code looks like:
import sys
import mechanize
uri = "http://www.geeksforgeeks.org/"
request = mechanize.Request(mechanize.urljoin(uri, "archives/18215"))
response = mechanize.urlopen(request)
forms = mechanize.ParseResponse(response, backwards_compat=False)
response.close()
form=forms[0]
print form
control = form.find_control("comment")
#control=form.find_control("bb2_screener")
print control.disabled
# ...or readonly
print control.readonly
# readonly and disabled attributes can be assigned to
#control.disabled = False
form.set_all_readonly(False)
form["author"]="Bulbasaur"
form["email"]="ashKetchup#gmail.com"
form["url"]="9gag.com"
form["comment"]="Y u no put a captcha?"
form["submit"]="Have Your Say"
form["comment_post_ID"]="18215"
form["comment_parent"]="0"
form["akismet_comment_nonce"]="d48e588090"
#form["bb2_screener_"]="1330787192 117.199.144.174"
request2 = form.click()
print request2
try:
response2 = mechanize.urlopen(request2)
except mechanize.HTTPError, response2:
pass
# headers
for name, value in response2.info().items():
if name != "date":
print "%s: %s" % (name.title(), value)
print response2.read() # body
response2.close()
Now the server returns me this.On going through the html code of the original page i found out there is one more field bb2_screener that i need to fill if I want to pretend like a browser to the server.But the problem is the field is not written inside the tag so mechanize won't treat it as a field.
Assuming you have all the params correct, you're still missing the session information that the site stores in a cookie. Consider using something like mechanize, that'll deal with the cookies for you. It's also more natural in that you tell it which fields to fill in with which data. If that still doesn't work, you can always use a jackhammer like selenium, but then technically you're using a browser.

passing a large string through url in codeigniter

how do i pass a large string as a variable in codeigniter? i am trying show the user an article, if the article has more than 800 characters and less than 3044 characters i am showing it in a jquery pop up window, and if the article is more than 3044 charcters i want to pass the article body and title through the url to a controller function.
here is what i have tried:
<?php
if(strlen($home_content[1]['content'])>800 && strlen($home_content[1]['content'])<3044)
{
$substr=substr($home_content[1]['content'],0,786);
echo $substr.'<p id="button"><i>read more...</i></p>';
}
else if(strlen($home_content[1]['content'])<800)
{
echo $home_content[1]['content'];
}
else
{
$substr=substr($home_content[1]['content'],0,786);
echo $substr.'<br/>';
echo anchor('site/read_article/'.$home_content[1]['title'].$home_content[1]['content'],'<i>read more...</i>');
}
?>
and this is the url after passing the data:
http://192.168.1.111/my_project/site/read_article/title%20mid%20left%3Cp%3Etesttesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lifesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lifesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.%20True%20Mirror,%20can%20come%20to%20life.ife.%20True%20Mirror,%20can%20come%20to%20life.ife.%3C/p%3E%3Cp%3E%C2%A0%3C/p%3E%3Cp%3Etesttesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lifesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lifesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.%20True%20Mirror,%20can%20come%20to%20life.ife.%20True%20Mirror,%20can%20come%20to%20life.ife.%3C/p%3E%3Cp%3Etesttesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20lBut%20we%20have%20already%20arrivesafOnly%20True%20Light,%20reflected%20in%20a%20True%20Mirror,%20can%20come%20to%20life.ife.testtesthave%20already%20arrivesafOnly%20True%20Light,%3C/p%3E.html
and i get this error message:
An Error Was Encountered
The URI you submitted has disallowed characters.
how do i do it correctly? the url looks very messy, how do pass the string and still have a clean url? please help me with it.
Why not pass the article ID instead? You could then access the article through the controller function, count the characters and decide the method of display.
Alternatively, you could use CI's Session Flashdata to pass the article title/body to the next controller and access it that way.
The URI is failing as security is set up to deny specific characters being passed in the URL. This is for your protection, but, although not recommended, could be disabled in the config files if required.

Resources