Revision [5040]
This is an old revision of ProgrammingHelp made by MovieLady on 2005-01-24 08:15:07.
Programming Help
See also:
Many people work at developing various aspects of code for wikka and yet we often struggle for hours, or even days, to solve programming problems that others in the wikka community know the answer to. Even more of an issue, sometimes coding problems aren't rectified until after initial code releases and feedback from other members lead to new code being posted (which means that the old code might now be running on others' wikka implementations) because the initial developer could not figure out how to solve a problem. To reduce these problems, this page is intended for people to be able to pose programming issues they've encountered and have the opportunity to draw on the knowledge of others' in our community as to how to resolve those issues. There are two sections...."Issues Needing assistance" & "Solved Issues". When a user has either solved an issue on their own that they've posted, or received help on the issue that satisfactorily addresses it, then the solution should be posted and it should be moved from the first to the second category.
Issues Needing Assistance
Spam repair and defense
Copied from RichardBerg hoping it might get more exposure here -- JavaWoman1/22/05 - Spam help! I have apparently been attacked by an army of spam bots. Has this happened to anyone else? For now, I am asking for your help with:
- a SQL command that will delete all of these edits
- a SQL command that will change all of my ACLs to '+' for writing and commenting (I've modified the config file but that only affects new pages AFAIK)
Whatever script they used (on multiple machines, no less) could certainly be used against any Wakka-like site with minimal modifications, so something has to be done...I will do what I can to help you guys combat future attacks as well as implement the new HTML attribute you've probably all heard about. --RichardBerg
- Richard: here's the sql to update all your current ACLs (I'm using mysql 4.0.22):
UPDATE acls SET comment_acl="+" WHERE comment_acl="*";
UPDATE acls SET write_acl="+" WHERE write_acl="*";
UPDATE acls SET write_acl="+" WHERE write_acl="*";
- You'll need to change the table name (acls) to match whatever your table is named. Give me a few to look at the pages table and your site and I should have the sql for removing the edits. :) -- MovieLady
- Since Richard has already changed his default ACLs in the configuration, that would apply to any page that did not have ACLs different from the original default (not merely new pages!); your SQL code should take care of any pages that had ACLs different from the original default (because only those would have a record in the ACLs table).
See also JsnX's suggestion about "Clearing ACLs" on the SuggestionBox which explains how this mechanism works. Thanks, MovieLady! --JavaWoman
- Correct. Both statements will change only the entries that had the default ACL from his config file in that field. (What the statements are looking for can, of course be changed, as can what the field is being set to. I used it when I went back and changed my default ACLs on all pages that had ACLs to disallow all banned users from writing or commenting after adding ACLsWithUserGroups.) --MovieLady
- There is a relevant link to an action at wikini for removing additions by particular IP's or users at CommunityNotes.--GmBowen
- Thanks for the link! I've translated and made minor changes to the code, and posted everything to DeleteSpamAction. He's got a very good starting point, I think. One could adapt the code (fairly easily) to allow you to look at all the revisions on a page instead of by user/IP and then delete the histories you don't want to keep, for whatever reason. --MovieLady
ShowCsv
I haven't tried out much, but since the content of the *.csv file is put into the hmtl-code of the page, it is possible to enter own code through the file (html is possible and php/javscript perhaps). I am not sure if the output of actions runs through safehtml. If not, would that be the best solution for the problem? Or find and replace of every < and >? --NilsLindenberg- did you try strip_tags? (or, you could replace < and > with other characters, like [ and ] so code could be there but "inactive", There's a suggestion for ...."while($input != strip_tags($input)) {$input = strip_tags($input);}" that might be pertinent. --GmBowen
- Output of an action is not automatically fed through SafeHTML - in other words, it's the responsibility of the action itself to consider whether the user's input (through a file, or parameter values) may contain HTML. The next thing to consider is whether you want (or even need) to allow HTML content; if not, strip_tags() on the input might be sufficient; if so, the action will have to apply SafeHTML to make sure that only safe HTML makes it through. Whether you apply this to the input, to the whole output, or to individual cell content (when a table is produced) depends on what is most efficient. The general security principle applies: NEVER trust your user's input! --JavaWoman
2 Dimensional Array Sort
another issue: is it possible to sort an array[x][y] the following way: you choose an [y] after which the [x] are sorted? --NilsLindenberg- All sorts of array are possible, but not always with a simple function call. Have a look at asort and its sister arsort (and related functions linked to from there) and don't miss the User Contributed Notes which often give valuable hints for solutions (but do test - they are not always entirely correct or robust!). --JavaWoman
Resolved Issues
Replace
How would you replace every 2nd occurence of a "needle" in a haystack string? I'm sure you can see where I'm going with this, I want to parse output from a table read so that **'s and //'s are replaced alternately withFinding a function that replaces only the first occurence in the string led me to the solution. I've coded 3 functions that can be included to turn bold & italics wikka code into html tags for output into a table (such as in my scheduler & wikka forum). Code below....
function str_replace_once($needle, $replace, $haystack) {
// Looks for the first occurence of $needle in $haystack
// and replaces it with $replace.
$pos = strpos($haystack, $needle);
if ($pos === false) {
// Nothing found
return $haystack;
}
return substr_replace($haystack, $replace, $pos, strlen($needle));
}
function bold_formatting_replace($haystack) {
//replaces bold wikka formatting (**) with html bold tags
$needle="**";
$count=(int)(substr_count($haystack, $needle)/2);
$replace="<strong>";
$replace2="</strong>";
while ($counter<$count)
{
$counter++;
$haystack=str_replace_once($needle, $replace2, str_replace_once($needle, $replace, $haystack));
}
return $haystack;
}
function italics_formatting_replace($haystack) {
//replaces italics wikka formatting (//) with html italics tags
$needle="//";
$count=(int)(substr_count($haystack, $needle)/2);
$replace="<em>";
$replace2="</em>";
while ($counter<$count)
{
$counter++;
$haystack=str_replace_once($needle, $replace2, str_replace_once($needle, $replace, $haystack));
}
return $haystack;
}
// Looks for the first occurence of $needle in $haystack
// and replaces it with $replace.
$pos = strpos($haystack, $needle);
if ($pos === false) {
// Nothing found
return $haystack;
}
return substr_replace($haystack, $replace, $pos, strlen($needle));
}
function bold_formatting_replace($haystack) {
//replaces bold wikka formatting (**) with html bold tags
$needle="**";
$count=(int)(substr_count($haystack, $needle)/2);
$replace="<strong>";
$replace2="</strong>";
while ($counter<$count)
{
$counter++;
$haystack=str_replace_once($needle, $replace2, str_replace_once($needle, $replace, $haystack));
}
return $haystack;
}
function italics_formatting_replace($haystack) {
//replaces italics wikka formatting (//) with html italics tags
$needle="//";
$count=(int)(substr_count($haystack, $needle)/2);
$replace="<em>";
$replace2="</em>";
while ($counter<$count)
{
$counter++;
$haystack=str_replace_once($needle, $replace2, str_replace_once($needle, $replace, $haystack));
}
return $haystack;
}
- Actually, from your description I did not see what you were aiming at ... looking at your code I get an idea now - but still don't get the context. Yes, you can do it this way. But you can also do it much simpler. Remember: the Formatter does exactly this - and it doesn't use a load of extra functions for it. ;-) So: the first question is: can you smply feed the code through the formatter?
$string = Format($string);should probably do it. If not, please explain the context (and why this doesn't work) and I should be able to give you much simpler code. --JavaWoman
- Well, for starters, I want to allow users to put only 'minimal' formatting (bold, italics, underline....for starters) in their message content in wikkaforum....and I wanted to use strip_tags on the input for security. I didn't want full wikka formatting in there tho' (and I certainly never thought that $string=format($string) would work anyways) I thought the above would allow me to replace $this->text with bold_formatting_replace(italic_formatting_replace($this->text)) in the Show_SForum_Threads function (line 17 of that function in wikkaforumfunctions.php) to format the output in the table.
- So tell me why my solution doesn't work: we already have a formatter that can do exactly what your functions do. Whatever you feed your functions you can feed the Format() function and get the same result. - I guess still don't get what your problem is... context needed... If you want to ignore any other formatting, just strip it before feeding the Format() function. (BTW, please add one indent when replying to an inline comment!) --JavaWoman
- Uh, it could just be my lack of understanding re: functions. Can I call wikka functions "in" other functions that I've written and included in a script?
- Sure, you can. How you do that depends no the context (scope) from where you're calling. Have a look at how actions call Wikka functions, and how the Formatter (wakka.php) calls Wikka functions for instance. --JavaWoman
- I didn't know that....I'll give it a try. Then I guess I just strip un-wanted wikka formatting out using a replace? Okay, if I can get the first bit working I'll try that too. (A good exercise for me anyways "writing" a completely new function....those above are the first I've done from scratch...learned ya GOTTA put a "return" statement in...took AGES to figure that out). I'll get back to you if I cannot make this approach work. --M
- Hmm, okay, using format($this->text) on line 17 of the Show_SForum_Threads function doesn't work at all (the output is only partial and all wiki headers/footers etc disappear), but, sigh, my functions don't work either if I use them in the same place. I don't have time to play with them more today to figure out why.....they work on strings "independent" of wikka (if I hard code a string into a file with just them in it and process the string) the output looks correct (see http://gmbowen.educ.unb.ca/test2/rename.php)...but see the note there...maybe there's a problem with output (like I have to do something for the html tags to be picked up... if you go to the root of that directory you can get to a copy of the file with a txt extension you can download). Anyhow, I've mucked with it and calling the wikka function (I looked at how actions & the wikka formatter do it as you suggested) and tried $this->format($this->text) instead on line 17 and that didn't work either....same output format as above using $this->format($this->text) as format($this->text). -m
- okay, I played with it more. Yup, I can use wikka formatter BUT I have to declare global $wakka; (darn those globals) in the function I'm using it in and then use $wakka->format($this->text);. I still have to strip out other wikka tags (I'll keep underlining, bold, italics, center, highlight text, strikethrough & lists) & I don't want actions to work...but I'll continue to play with this. Thanks for the help so far. -- mike
$printtext = (stripslashes($row['for_text']));
$brackets = Array ('/{{/i', '/}}/i');
$changeto = '|.|';
$printtext = preg_replace($brackets, $changeto, $printtext);
$remove = array('#%', '======', '=====', '====', '===', '==', '[[', ']]', '||', '% %', '<<', '>>', '::c::', '""');
$printtext = str_replace($remove, '', $printtext);
$printtext = $wakka->format($printtext);
$brackets = Array ('/{{/i', '/}}/i');
$changeto = '|.|';
$printtext = preg_replace($brackets, $changeto, $printtext);
$remove = array('#%', '======', '=====', '====', '===', '==', '[[', ']]', '||', '% %', '<<', '>>', '::c::', '""');
$printtext = str_replace($remove, '', $printtext);
$printtext = $wakka->format($printtext);
(except for the spaces between the percent signs)
Multiple copies of actions
Not being able to put multiple copies of an action on a page. Can be caused by multiple copies of the same functions being loaded. Solution: have the functions "included" from a separate file using include_once() which stops repeated loading of the functions. Example where implemented: WikkaForumOnly single copies of generated images on a wikka page
In developing my WikkaGrapher action I have it both generating an image and wikka code (that calls an action) that can be placed on a page to place the graph on the page. The action is below (saved as graph.php) and examples of the code are at http://gmbowen.educ.unb.ca/wiki/wakka.php?wakka=Sandbox5 (the code generating interface is at SandBox6). Only the code for the first image is processed for some reason (as can be seen at Sandbox5). Not surprisingly, I'd like users to be able to place more than one graph on a page. Ideas? The graphing engine is at http://www.phpclasses.org/browse/package/1993.html.<?php
echo '<img src="./scripts/graphmaker.php?'.$code.'><br \>';
?>
echo '<img src="./scripts/graphmaker.php?'.$code.'><br \>';
?>
- Three problems with that code:
- the break tag should be written as <br /> (note the forward slash)
- just like the break tag the img tag should be closed - but isn't: - you need ' />' at the end (not just '>');
- once you do that the main problem causing only one image to appear becomes more visible: the src attribute has only an opening " but not a closing one
- Change the code as follows:
<?phpBTW, why not use the nice features of class.graphic.php to let the user specify the data it needs as separate action parameters and let the class generate the query string? That would be much more user-friendly. That's what OO is all (well, mostly) about: hiding the complexities... (The form is horribly messy though...)--JavaWoman
echo '<img src="./scripts/graphmaker.php?'.$code.'" /><br />';
?>
- you should *blush* again....look at SandBox6 and you'll see I am essentially using his interface....I spent 2 days adapting it so it'd work in wikka & give a preview of the graph. A "save" feature is next (Carlos sent me a copy of his code with that incorporated). And perhaps a series of "if" statements so parameters that are blank are not added onto the string -- GmBowen
- Yes, I commented on that messy form, didn't I? (I even updated the link to it. ;-)) What I meant is that your action (apparently) isn't using the class interface to generate the query. Which makes the action hard to use. You could still have it accept the $code paramater, but at the same time have it accept the actual parameters the class can use to generate the query, so it's easier to directly create and/or update the action as embedded in a page. --JavaWoman
- Well, I couldn't use his interface directly in wikka because it was non-compatible. But I'm generating his code in almost exactly the same way he did (but w/o java scripts), I'm just using post instead of get. In addition, and I'm sure you'll :) at this, I removed the code that was non-compliant (I had a computer science major looking over my shoulder at one point when I was working on this who pointed out what the compliance problem was). It's quite possible that I'm missing your point here, because I do think I'm doing what you're saying I'm not. Hmmmm.... --GmBowen
- How is it not compatible? A class is about the easiest to integrate, I would think. Anyway, show us your action code then so we can see what you are actually doing... --JavaWoman
- Now at GraphMaker. His class had embedded formatting all over the place that threw-off wikka....I'm not sure it's a "true" class in the sense of what one of those is (easily embeddable)....it's more like a single-script standalone program.--GmBowen
- Mike, it's definitely a valid class, but the html() method is producing a whole page rather than just body content, so you'd need to subclass the class and override the html() method at least. That makes it somewhat harder to use in an application like Wikka, or anything that needs body content only instead of a whole page, but it doesn't mean you can't use it. (The html() method should be refactored though, so it uses a body() method to only generate that part.) Like I said, if you want to use classes, learn how to use classes - sorry. It's the way you are using the file in this context that is causing the problems; it comes with a bunch of examples how to use it - have you tried any of those before even trying to integrate with Wikka? I'd advise you to do that sso you get a feel for how to interface with the class in general, and what it's capable of. --JavaWoman
- I could tell it was something with the closing tags (by looking at properties there were things at the end of the code that shouldn't be) but I couldn't figure out what. I tried multiple things, and obviously one resulted in the loss of the end '>'. Why does it have to be '/>' and not just '>'?? (there are vagaries to php that vary from html that I'm not clear on). Thanks JW. Works like a charm now.
- Because the html-syntax is <tag></tag> (opening tag - closing tag). There was (and is) no </image> or </br>, and it wasn't necessary in older html-standards, so they defined the form <tag /> for this cases, which opens and closes the tag. --NilsLindenberg
- Hmmm, okay. I'll have to work at remembering that...ugh. Thanks Nils. (Now off to bed). -- GmBowen
- Actually there is a closing tag for every opening tag in XHTML, so </img> exists, and so does </br>. And in XHTML every tag needs to be closed - which implies that every tag also has a closing tag. However when a tag is empty, you can "shortcut-close" it by ending the tag with '<tag/>' instead of closing it with '<tag></tag>'. That's less to type - but an additional advantage is that some browsers (still) don't support the "full" form but do support the "shortcut" form - especially if you use "compatibilty mode" by putting a space before the slash: <tag />. The latter form is what we use in Wikka , to ensure compatibilty with many browsers. --JavaWoman
- Another note: it's probably wise not to have the action accept the $code value blindly; at the very least first build the URL and then URL-encode it to prevent any attacks. Without that, the code is a security risk. (Isn't it surprising how many problems there can be with a single short line of code? ;-)) --JavaWoman
- I need more guidance on this I'm afraid (my non-programming background leaping to the fore ;-) )....do you mean do a urlencode($code) in the graph.php file before the "<img src" statement, or alter the output from graphentry.php somehow, or process it through urlencode before being generated by graphentry.php? (these files now at GraphMaker) -- GmBowen
- No I mean first build the full URL to be used for the src attribute (first part concatenated with $code), then urlencode() that, then use the result for the img src attribute. The $code is not necessarily generated by the class (you don't know that it is!) - it's accepted blindly by this action without checking.
- Okay. I tried this...
- $url="./scripts/graphmaker.php?".$code;
- $url=urlencode($url);
- and then echoed it, and it didn't work. So I played around some and found that even if I entered http://gmbowen.educ.unb.ca/wiki%2Fscripts%2Fgraphmaker.php (with the / replaced with % 2 F) then it didn't work. No surprise then that the urlencoded output didn't work. So, I encoded and then decoded it and that seemed to solve the problem (and, I'm assuming, the security issue). Is this acceptable?
- Exactly what do you mean by "didn't work"? What happens when you use a URL-encoded URL for the img src attribute? --JavaWoman
- I mean I got a little box with a red x on the wiki page. I played with it lots in the graph.php file and only got the same. So I echoed the code out and it looked fine (both before and after the urlencode was done) so I placed the imgsrc reference in the URL bar....still nothing...didn't generate a graph (or anything). So I took only the http://gmbowen.educ.unb.ca/wiki%2Fscripts%2Fgraphmaker.php bit and still nothing was generated....it should have given me the graph form at least. So, I tried replacing more and more of the %2F's with a slash (in the URL bar) and when they were all replaced THEN it generated the graph form (which my class has been changed to do by default). So I went to php.net and looked to see if there was a way to urlunencode & found there was. So I changed the line (urlencode($code)) (which was generating encoded img src reference to (urldecode(urlencode($code))) and it worked just fine. I subsequently changed it to (urldecode(urlencode(strip_tags($code)))) so that it wasn't possible to put tags into what was being passed at all and that generated graphs too. Because of both striptags and the urlencoding I think I've addressed your concern because urldecoding shouldn't affect the effect of urlencoding should id?
- Well, urlencoding a URL and then immediately decoding it before passing it on, just gives you back the original, so that's no security at all. :) Just using strip_tags() on the $code parameter would give a reasonable protection though. I'll have to play with the class myself to see why it doesn't work with an encoded URL - it should, I think. --JavaWoman
- The problem might be the server. It doesn't recognize http://gmbowen.educ.unb.ca/wiki%2Fscripts%2F either...so clearly not a problem with the class. Weird. --GmBowen
- Hmm - that URL gives me a 404 error: "The requested URL /wiki/scripts/ was not found on this server." Clearly is is interpreting the %2F correctly as a / . --JavaWoman
- But if I just copy that line, try it....it doesn't work. If I then edit the url bar and replace %2F with / then it does.
- Copy the encoded URL is just what I did, and what generates the 404. Must be your browser that's having a problem with it, I think; try Firefox! (I must be tired...) Indeed, if I replace %2F by / it does work, and I get a directory listing (oops, another security hole); but actually, an encoded URL should be used within HTML only; the browser then takes care of sending the correct request to the server. IOW, if you use it as the href attribute of an a tag, it should work, but not when you paste it into the browser's address bar. --JavaWoman
- I was accessing the graph class directly to see how it looked/worked while I was developing the wikkagrapher, that's why that dir is accessible. I've noticed in the past that some servers you can send encoded statements to in the url bar and it works, and others not. What you say is interesting tho'...I wonder why the encoded stuff isn't working in this case because with the usage you describe it should.
- Well, actually I think it should work from the address bar, too. (yaaawwn - it's late; can't quite remember now.) Strange, though. What server are you using?
- A linux red-hat variant intended to be a small to medium business server called sme-server (www.contribs.org) that's a much modded version of Redhat 7.2. It's got secure information bays (individual root directories essentially) etc. that variables won't pass across and are not cross-browsable for instance. Plus bays are individually controllable for running scripts, access etc. -- mike
- BTW, thanks for your help on this. You know a million resources...any idea where I'd find code that would allow me to parse the action statement in the textarea box back IN to variables/values? (then a user could re-edit the graph parameters using the form by placing it in the textarea box and "submitting" it).
- Have a look at what I conconcted on your GraphMaker page ;-) Not quite what you're asking, but it could easily be extended with a custom form. --JavaWoman
- ya, I'll look at it tomorrow. Got some course-related web developing to do for tomorrow. -- m
- I've looked at the code & it works nicely....I see what you're talking about now re: parameters vs. a string.....I'll first work at re-doing the form output so that it generates that sort of parameter output. --m
Unresolvable Issues
Double-Click Edit
Is there any way to insert code into an action that disables the double-click editing on a page? I thought I saw something on this site but cannot find it anymore.- Not per page, and not as an action - but each registered user can enable/disable it in their own user settings. --JavaWoman
Not tried this but if you where to change the ondbclick event to a call function, say dbClickEdit(), instead of inlining the javascript code. You could then create an action to null the function.
<script language="javascript"> dbClickEdit = function () {} </script>
Bit of a nasty polymorphic hack mind you. The other option would be to create a JS object to handle the event, and the action could then set a property to turn the event off.
var dbClickEdit = new Object(); dbClickEdit.enabled = true; dbClickEdit.clicked = function() { if (this.enabled) location.href=location.href+'/edit'; }
--DaveBradshaw
CategoryUserContributions