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
RegExp Help
Based on the discussion on ValidPageNames, I wanted to use JavaWoman's suggestion for a robust RegExp, but I cannot get it to work:<?php
define('LCLETTER', 'a-z\xe0-\xf6\xf8-\xff');
define('UCLETTER', 'A-Z\xc0-\xd6\xd8-\xdf');
define('LETTERS', LCLETTER.UCLETTER);
define('DIGITS', '0-9');
define('ALLCHARS', LETTERS.DIGITS);
function IsWikiName($text) {
$pattern = '/^['.UCLETTER.']['.LCLETTER.']+['.UCLETTER.DIGITS.']['.ALLCHARS.']*$/';
return preg_match($pattern, $text);
}
$x = "ThisTest";
if (IsWikiName($x)) {print("<p>YES!</p>");}
else {print("<p>NO!</p>");}
$y = "ThisÜbertest";
if (IsWikiName($y)) {print("<p>YES!</p>");}
else {print("<p>NO!</p>");}
?>
define('LCLETTER', 'a-z\xe0-\xf6\xf8-\xff');
define('UCLETTER', 'A-Z\xc0-\xd6\xd8-\xdf');
define('LETTERS', LCLETTER.UCLETTER);
define('DIGITS', '0-9');
define('ALLCHARS', LETTERS.DIGITS);
function IsWikiName($text) {
$pattern = '/^['.UCLETTER.']['.LCLETTER.']+['.UCLETTER.DIGITS.']['.ALLCHARS.']*$/';
return preg_match($pattern, $text);
}
$x = "ThisTest";
if (IsWikiName($x)) {print("<p>YES!</p>");}
else {print("<p>NO!</p>");}
$y = "ThisÜbertest";
if (IsWikiName($y)) {print("<p>YES!</p>");}
else {print("<p>NO!</p>");}
?>
This should be YES YES output but it outputs YES NO. Using PHP 5.03 and Apache 2.0.52 serving as UTF-8 by default. Any ideas what is wrong here? --IanAndolina
- Color me confused... I grabbed the code and save it to my test server, ran it, and it prints YES! YES! That's with PHP 5.0.3 on Apache 2.0.52 and default charset UTF-8, running on Win2K. Eh??? --JavaWoman
- OK, here is the issue, I normally save my files as utf-8 locally. Now Ü is 00DC and I assumed that was the same for iso-8859-1 as for utf-8 - so saving Ü in a utf-8 file kept it as DC (unicode latin-1-supplement. But I realise it is my ignorance of how utf-8 actually works. If I save as ANSI-windows I get YES YES. BUT I'm now worried, as I assumed even if the file is stored using two bytes for Ü it should still be processed as unicode intends it to be - 00DC - but it appears that PHP does not intepret it as 00DC when stored as UTF-8 (even if any other UTF-8 aware app displays it as Ü). I feel I'm being dumb and missing something fundamental; can someone please enlighten me! ;)
EDIT: OK, answering myself: I assumed too much of PHP, that it would automagically convert the two bytes of utf-8 to the correct single byte. To do that I need utf8-decode() - but that breaks anything saved as ANSI - even though I imagined it should be 1byte safe. What are the easiest solutions? --IanAndolina
- I had to refresh my memory about UTF-8 here a bit. While at first sight you might think the Ü would be encoded simply as 00DC, when you think about it, this can't be true: how would we know whether to read that sequence of bytes as a two characters, or as a single double-byte character? UTF-8 takes care to avoid such ambiguities, and Ü is actually encoded as C39C; this very nicely explained in this article (if you convert DC and C39C to binary, it's easy to see how C39C actually encodes the Ü).
- The second problem is the UTF-8 encoded files as seen from the PHP perspective. First, under Windows, the "byte order mark" at the start of the file causes no problems, but on older (Unix) systems this may not be the case. (PHP does break when the source file is encoded as "Unicode" or UCS-2 to be precise: the browser simply shows the source code.)
- The third problem is the biggest: the preg_xxx() functions, based on the PCRE library, are not designed to handle UTF-8. So the preg_match() in this bit of code simply sees two bytes (C3 and 9C), where the second one (9C) is not an allowed character, and the match fails.
- PHP can be "taught" to handle multi-byte encoded strings, but it's not simple. First, it will need the (non-default) multi-byte string extension to be configured when compiling PHP; the documentation states:
" When you manipulate (trim, split, splice, etc.) strings encoded in a multibyte encoding, you need to use special functions since two or more consecutive bytes may represent a single character in such encoding schemes. Otherwise, if you apply a non-multibyte-aware string function to the string, it probably fails to detect the beginning or ending of the multibyte character and ends up with a corrupted garbage string that most likely loses its original meaning."
- Then, with mbstring support, a number of functions can be "overloaded" as listed on the documentation page - note that the ereg[-xxx]() functions are there, but not preg_xxx(). The page documenting the Perl-Compatible Regular Expression Functions refers to http://www.pcre.org/pcre.txt for its limitations. Effectively, that page states that UTF-8 support maybe compiled in (but isn't necessarily). And as a user comment by Ned Baldessin on the PHP documentation states, you need to take extra steps to ensure PHP is working with the proper assumptions as to the encoding used before applying the multi-byte variants of the ereg[-xxx]() functions.
- I guess the first lesson is to not encode your source files as UTF-8. Set the locale, if needed, to make preg_xxx() functions work properly (especially needed for instance when using case-insensitive matching: the engine must know the locale to know which lower and uppercase characters correspond) - that way single-byte languages can be handled nicely. Where you truly must deal with UTF-8, I think only the mb_ereg[-xxx]() functions can be safely used - provided multi-byte string capability is compliled into PHP and enabled in php.ini.
- Finally, with the preg_xxx() functions you may try the u (PCRE_UTF8) modifier which makes use of a PCRE library that has UTF-8 support built-in: This modifier is available from PHP 4.1.0 or greater on Unix and from PHP 4.2.3 on win32.
- All of this obviously makes UTF-8 support highly dependent on the PHP version and platform available.
Not the final word, this just represents the current state of my knowledge... :) --JavaWoman
- JavaWoman — ¡you rock! — thank you for this information. It is quite a disappointment to realise how flaky PHP is when handling UTF-8 strings, but at least thanks to you I now have a clearly defined understanding of such flakiness! --IanAndolina
Hyperlink containing wikka page id
Can anyone tell me how I can write a hyperlink in an Action which includes (dynamically) the wikka page id.The hyperlink has to look something like this
http://www.mysite.co.uk/fpdf/wikka_pdf.php?id= Link Name
where ?id=page_id
This is similar to the WikkaMenulets code. I just don't know how to echo the page_id
--JamesMcl
- James, you obtain the page tag by echoing $this->tag -- DarTar
- Thanks DarTar. Would you mind giving an example so that I can get the syntax correct.
- James, need more context to provide an example; how is your code producing the 'http://www.mysite.co.uk/fpdf/wikka_pdf.php' bit? --JavaWoman
- JavaWoman Here is what I am trying to do. I am trying to create a pdf file from the wiki page by using the FPDF class. To do this, you create a script which includes the class and defines your mySQL query to extract the information from the database. In this case it would be something like, select * from wikka_pages where tag=$tag. The wikka page needs to have a hyperlink or button that will submit the tag to the script. It will result in something like http://www.domain.co.uk/fpdf/wikka_pdf.php?tag=SandBox. The class will then, depending on your script format, produce a pdf file in the layout that you have defined. The next step will be to filter the wikka formatting and convert it back to html for things such as bold text etc. DarTar answered my question with echoing $this->tag . This gives me the correct page tag, it's the script that I now need to correct in order to display the content. --JamesMcl
Embedding decoded image into wikka
If I open the following script directly (as a file) it shows a small "you've got mail" sort of image. But, if I "call it" as an action in wikka it just shows the raw GIF89a image code content. What do I need to do to show the image on the wiki page calling the file as an action? Thanks.
<?
echo base64_decode(
'R0lGODlhHAASALMPAP+qKv+/v/yOkc6c//40LWRmYv8MA87//2'.
'MAnM7O/83NzQ8MZP/MM5mZmf///wAAACH5BAEAAA8ALAAAAAAc'.
'ABIAAASv8MlJq71W4M3NK0gojiRSTEIgCUazFMohz/S8IFNgEA'.
'HhL4OFwkEsGhWLA25CMDgBhkUiODQWkQklRccAdKUOqtWhKCQc'.
'2lXTy2CAw8KjmZh2EtjtN7xaPtOXDwJrbW5+DgVUfQVFaRJcXg'.
'Bvi3BzDgt/FE1PUWeTRAOGlmiAOjw+BFKVY0UFjSkrBgIvCbS1'.
'trYgGC0FC72+v8AvGAoNxcbHyMYbCszNzs/OHNIcEQA7'.
'');
?>
echo base64_decode(
'R0lGODlhHAASALMPAP+qKv+/v/yOkc6c//40LWRmYv8MA87//2'.
'MAnM7O/83NzQ8MZP/MM5mZmf///wAAACH5BAEAAA8ALAAAAAAc'.
'ABIAAASv8MlJq71W4M3NK0gojiRSTEIgCUazFMohz/S8IFNgEA'.
'HhL4OFwkEsGhWLA25CMDgBhkUiODQWkQklRccAdKUOqtWhKCQc'.
'2lXTy2CAw8KjmZh2EtjtN7xaPtOXDwJrbW5+DgVUfQVFaRJcXg'.
'Bvi3BzDgt/FE1PUWeTRAOGlmiAOjw+BFKVY0UFjSkrBgIvCbS1'.
'trYgGC0FC72+v8AvGAoNxcbHyMYbCszNzs/OHNIcEQA7'.
'');
?>
- Mike, if it displays as an image, use it like an image! In other words, use the file just like you would use an image file in an image action or directly in a (double-double quoted) img tag. But why not save it as an image file and use that? That will save the extra decoding step. --JavaWoman
- I was trying to have the "image" show up in the header to indicate if a user had a private message a la WikkaMail. I could get it to work fine in a "static" sense....as you navigated around if someone sent you a private message then a little colourful graphic showed up. Better not "edit" a page tho'....as soon as you did that I'd get an error (generating the same image twice using a function call was the overall meaning of the message). Anyhow, I was just playing....I was trying to ease distribution of packages that used graphics. I guess I've decided overall that providing a letter graphic is the easier way to go. Thanks. --GmBowen
Spam repair and defense
Copied from RichardBerg hoping it might get more exposure here -- JavaWoman(Moved to WikkaSpamFighting now (where all Spam-related issues are being gathered) - I realise it's asking for help, but we'll need to have facilities like these in Wikka!)
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
Moving Java Variables to PHP
That's a pretty weak description, but it's the best I've got. I'm beginning to play with adapting Tom's Corkboard so that it'll work in wikka as a brainstorming/project development tool. Ultimately, if the problem here is solvable, it'll be usable to enter series (and threads) of notes that you can move around and locate near other related ones...or filter by color, box outline, or word search. The problem I'm trying to address (seen here) is that I can move around the boxes (at this point IE only, although I hear there's other drag & drop code around that'll work w/ firefox, but I couldn't find it anywhere...ideas?) but cannot see a way of "obtaining" the new top corner x,y coordinates....does anybody know of any way to do this? (when I look at the source code, no matter where the tables are, the x-y coordinates haven't changed) When I figure THAT out then I'll want to figure out how to write them to the database so that clusterings of the boxes is permanent...again, ideas? Thanks. -- GmBowen- I assume you mean JavaScript, Mike, not Java? I looked briefly at that "CorkBoard" but it doesn't seem like there's any Java involved. (I could not move anything around either, and wondered what the use of it was... even the arrange button leaves notes overlapping each other.) But what would you want the coordinates for? It all happens in the visitor's browser anyway, that seems to be the point - Java might be able to send something back to the server but JavaScript *should not* even be able to do this - that would be a major security hole! --JavaWoman
- Oops, you don't use IE.....right now the drag & drop only works with IE. Okay....I put things badly. I think it's javascript that needs to be used to "get" the x/y coordinates after dragging the boxes around (see the code here) cuz that's what's dragging the boxes around & then php will have to be used to write to the database by sending variables back (by the unique ID identifier for each box). On the system I'm using arrange doesn't leave any overlap. Basically it's that "proof of concept" stuff....can I write the x/y coordinates back to the server for each box after moving them around, and if so how?? If I can solve that, then it makes sense to work on other compatibility issues (otherwise, it doesn't make any sense to work on them at all). Webnote does this using python....I'm interested in seeing if it's possible using php & java/script. --GmBowen
- Mike, "can I write the x/y coordinates back to the server for each box after moving them around?" -- No you can't, that's what I'm saying. It's all in the visitor's browser and JavaScript cannot communicate anything back to the server. I don't see why you would want to do so here anyway: the whole point of the dragging interface (if it works :)) is that it's up to the visitor where to place what - you don't even want to know that, merely provide the functionality. BTW, I looked at the CorkBoard example page: you get overlapping boxes when they don't all "fit" in the browser window. --JavaWoman
- Hmmm, okay. Guess I'll stew on that one. Webnote stores locations somehow, but I can't figure out how. Any insights into why when I hack Tom's script into wikka as an action that it places all the boxes in one place overlapping (seen here)?? The "arrange" rearranges them fine, but the initial placement is all at the same x/y (same in firefox and IE on a xp machine). -- GmBowen
- Yes, Mike, sorry - I looked at the Webnote code yesterday and was quite stunned to see it's JavaScript actually posting back to the server... apparently possible, but I still think it shouldn't be possible. I'm far from being a JavaScript expert though - I dislike the language ;-) --JavaWoman
Resolved Issues
regexp
I want to replace the following :// but can't find a regexp doing this :( --NilsLindenberg- Why do you want to replace it? State the problem, rather than the proposed solution... --JavaWoman
- Solved now. It was the one we talked about on irc. Just wrong function --NilsLindenberg
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
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
Parsing Dates
Is there a simple way to parse a data string in the database that is structured like this...."20050128002912"....so that is shows "January 28, 2005. 00:29" ? I've tried all sorts of things with no success. I've tried parsing the line using the following.... $mysqltime=$row[SentDate];
$hour = substr($mysqltime, 8, 2)*1;
if (strlen($hour)==1) {$hour="0".$hour;}
$min = substr($mysqltime, 10, 2)*1;
if (strlen($min)==1) {$min="0".$min;}
$sec = substr($mysqltime, 12, 2)*1;
if (strlen($sec)==1) {$sec="0".$sec;}
$month = substr($mysqltime, 4, 2)*1;
$day = substr($mysqltime, 6, 2)*1;
$year = substr($mysqltime, 0, 4);
$datetime=$hour.":".$min.":".$sec." ".$month."-".$day."-".$year;
echo $datetime;
$hour = substr($mysqltime, 8, 2)*1;
if (strlen($hour)==1) {$hour="0".$hour;}
$min = substr($mysqltime, 10, 2)*1;
if (strlen($min)==1) {$min="0".$min;}
$sec = substr($mysqltime, 12, 2)*1;
if (strlen($sec)==1) {$sec="0".$sec;}
$month = substr($mysqltime, 4, 2)*1;
$day = substr($mysqltime, 6, 2)*1;
$year = substr($mysqltime, 0, 4);
$datetime=$hour.":".$min.":".$sec." ".$month."-".$day."-".$year;
echo $datetime;
Is this the best way of doing this? It seems awfully server intensive. Ideas? -- GmBowen
- Sorry, don't have time for an extensive answer, but I have two ideas: 1) store the data in the database either in MySQL date format or as a unix timestamp (why don't you?); then 2) you can use standard functions for parsing and displaying dates. The whole thing should take no more than 2-3 lines of code using standard data types and built-in functions. --JavaWoman
- Well, I would have thought so too. However, the PHP function that causes dates to be output in that format does not in actuality have a "reverse" function....believe it or not, there is apparently no standard PHP functions for doing that reversal.....I now realize there's lots of really snarky commentary in forums to that effect (I was originally searching for help using inappropriate terminology which is why I wasn't finding anything...once I started using the right buzz words I found lots). The reason the two sets of code I'm working with use that time stamp is because the string is easily sortable across records...but getting time/dates out of it is kinda inefficient (as the code above illustrates). Changing how the date was input would mean changing lots of other code for the sorts, so I'm just going to use the above. At first I thought I was just missing something, but lots of snooping around suggests that what I'm doing above is what is necessary. Sheesh. I was just now hoping that somebody had a more efficient way of coding that. Thanks. -- GmBowen
- What do you mean by "reverse"? If you store dates in a date format (MySQL or Unix) then the formatting function need only handle how you present a date. I don't see where any "reverse" comes into it. You don't need a non-standard format to sort stored dates - both the standard MySQL and Unix format will sort perfectly (MySQL is essentially ISO, Unix is just a number). You don't want a non-standard format to store dates precisely to avoid these problems of doing your own parsing while PHP and MySQL already have functions built in to handle dates in standard format. So: don't work with code that was written to make things difficult! - start by changing that code to make sure your dates are stored in standard format; if you want MySQL to do manipulation, then the MySQL date type is best; if you need PHP to do a lot of manipulation, the Unix timestamp (put in a sufficiently long integer type) is bet. The wheels have been invented long ago - and become part of the language. :) --JavaWoman.
- The problem arose because the original script programmer designated the database field as being "text" instead of "DATETIME". As JW points out, there seems little reason to do that as all the sorts etc will work the same. I created a new field as a DATETIME field, read the old values from the original string and wrote them to that directory (see the conversion script at WikkaMail for the details), and then had much more formatting control on the output from the DATETIME field. --GmBowen
Designing mass action
To realize the ACL mass-action, in the page admin tool, I have two possible solutions. First after choice the ACL action in the combobox, I can open a small form under the combo box, to add the needed data. Or Second I open a new page to enter the needed Data and after that than comes the action for the before selected pages. What do you prefer? --AndreasTengickiUnresolvable Issues
Javascript Help
I know v. little about using javascript, but thought that the following code snippet might be a useful addition to one of my wiki's (making it easy to increase/decrease font size) in the header....but I can't get it to work. (I snitched the code from here.) Any ideas? I keep getting "error on page" when I stick it in the header.php file. Thanks. --GmBowen
<a href="javascript:cF(-1,0);" class="uImg" title="decrease body text to the default size"><img src="http://z.about.com/f/bt/tfm.gif" alt="decrease font size" border="0" /></a> <a href="javascript:cF(1,0);" class="uImg" title="increase body text to the largest size" ><img src="http://z.about.com/f/bt/tfp.gif" alt="increase font size" border="0" /></a>
- Well, this can't be complete... cF() apparently is a function, and it needs to be defined to be able to use it. So at least you must also (in the head section of the document) include a link to the source file that defines that function. (Of course, you should also use your own copy (or version) of the images, and not link externally. :)) --JavaWoman (who is not a JavaScript expert)
- Ya, I was going to use my own local version of the images if I got it working...no sense going to the effort if I can't get the code working, as seems to be the case. --Mike
- Also, if your CSS is properly coded you should be able to let users resize text using browser mechanisms. Most importantly, use relative font sizes to allow the users default to be used as the base size for a page. Depending on javascript to overcome design limitations is far from ideal IMO --IanAndolina
- Hmm, well, like I said, I don't know much about javascript. I thought it was a function, but cannot see one in the full page code, nor a url reference to one. I don't doubt there's a CSS way of doing this (what can't be done with CSS??{grin}) but as y'all know I don't understand CSS worth a darn, but this seemed like a simple way of playing with providing the option to resize text easily (then, when I interview a group of students at the end of the year I can find out IF they used it....part of a small usability project I'm running). Thanks for the input. --Mike
- Well on the page you referred to there are 9 (!) script elements in the head section (horrible HTML...); I'd bet on one, but you may need others as well, it's all a bit messy in there. :) --JavaWoman
Embedding HTML for VML successfully in Wikka?
Although I KNOW this is for IE only (and thus many of you can't help me), I came across this open source drawing package that works nicely (see http://www.foundmyself.com/paintboard/editor.php) and which generates html code that you can use to re-create the image....as an example....
<html>
<head>
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v"/>
<style type="text/css">
v\:* { behavior: url(#default#VML);}
</style>
</head>
<body>
<?xml:namespace prefix = v /><v:shape id=nr1 style="LEFT: 0px; WIDTH: 803px; POSITION: absolute; TOP: 0px; HEIGHT: 563px" coordsize = "803,563" filled = "f" strokecolor = "black" strokeweight = "8.25pt" path = " m204,221 l204,221,188,230,189,232,196,238,207,247,221,259,242,275,267,294,292,313,313,331,334,347,342,358,350,369,361,378,373,387,386,393,398,396,406,397,415,397,422,395 429,391,434,387,438,382,442,376,444,369,445,361,447,352,448,342,449,333,450,325,453,316,455,309,459,303,465,298,471,294,480,291,488,288,497,286,506,284,514,284 521,284,526,284,527,284,528,284,529,284,529,283,529,281,529,276,528,271,526,265,523,258,522,251,522,244,523,237,528,230,534,225,542,220,552,216,564,215,576,215 588,216,599,217,610,223,621,228,630,236,641,246,649,255,656,266,659,274,662,282,663,286,663,287,663,286,663,285,663,279,662,270,659,258,656,246,652,234,647,222 639,208,630,197,619,186,605,174,588,164,573,157,553,149,529,144,504,141,476,139,455,139,437,140,421,144,408,150,397,155,388,162,380,171,374,179,367,186,362,194 356,203,349,212,342,221,334,231,325,240,314,248,309,256,303,261,291,266,274,270,253,272,228,275,200,277,176,277,157,278,141,281,127,284,115,286,106,290,96,294 87,299,79,304,72,309,66,314,60,318,58,318,54,320,53,321,51,320,49,316,48,309,48,299,51,287,56,272,63,254,75,234,87,214,100,194,115,176,126,163 136,152,145,144,153,138,157,136,159,137,163,140,166,146,170,153,172,163,175,175,176,189,176,202,176,215,176,229,176,242,176,253,176,262,178,272,179,281,180,288 183,295,186,302,188,308,192,314,194,318,196,324,200,329,201,335,203,342,206,348,209,353,214,361,220,369,230,375,242,382,257,389,277,395,285,398,309,404,345,411 383,413,418,414,446,416,468,418,478,418,486,418,487,418,488,418,489,418,489,417,490,417 e"><v:path></v:path><v:fill></v:fill><v:stroke></v:stroke></v:shape>
</body>
</html>
<head>
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v"/>
<style type="text/css">
v\:* { behavior: url(#default#VML);}
</style>
</head>
<body>
<?xml:namespace prefix = v /><v:shape id=nr1 style="LEFT: 0px; WIDTH: 803px; POSITION: absolute; TOP: 0px; HEIGHT: 563px" coordsize = "803,563" filled = "f" strokecolor = "black" strokeweight = "8.25pt" path = " m204,221 l204,221,188,230,189,232,196,238,207,247,221,259,242,275,267,294,292,313,313,331,334,347,342,358,350,369,361,378,373,387,386,393,398,396,406,397,415,397,422,395 429,391,434,387,438,382,442,376,444,369,445,361,447,352,448,342,449,333,450,325,453,316,455,309,459,303,465,298,471,294,480,291,488,288,497,286,506,284,514,284 521,284,526,284,527,284,528,284,529,284,529,283,529,281,529,276,528,271,526,265,523,258,522,251,522,244,523,237,528,230,534,225,542,220,552,216,564,215,576,215 588,216,599,217,610,223,621,228,630,236,641,246,649,255,656,266,659,274,662,282,663,286,663,287,663,286,663,285,663,279,662,270,659,258,656,246,652,234,647,222 639,208,630,197,619,186,605,174,588,164,573,157,553,149,529,144,504,141,476,139,455,139,437,140,421,144,408,150,397,155,388,162,380,171,374,179,367,186,362,194 356,203,349,212,342,221,334,231,325,240,314,248,309,256,303,261,291,266,274,270,253,272,228,275,200,277,176,277,157,278,141,281,127,284,115,286,106,290,96,294 87,299,79,304,72,309,66,314,60,318,58,318,54,320,53,321,51,320,49,316,48,309,48,299,51,287,56,272,63,254,75,234,87,214,100,194,115,176,126,163 136,152,145,144,153,138,157,136,159,137,163,140,166,146,170,153,172,163,175,175,176,189,176,202,176,215,176,229,176,242,176,253,176,262,178,272,179,281,180,288 183,295,186,302,188,308,192,314,194,318,196,324,200,329,201,335,203,342,206,348,209,353,214,361,220,369,230,375,242,382,257,389,277,395,285,398,309,404,345,411 383,413,418,414,446,416,468,418,478,418,486,418,487,418,488,418,489,418,489,417,490,417 e"><v:path></v:path><v:fill></v:fill><v:stroke></v:stroke></v:shape>
</body>
</html>
I thought if I just escaped it it might embed images in wikka, but no luck (including removing the body/html stuff). Anybody have any ideas on whether/if/how to embed this code into wikka so it would show up (of course, knowing this will only work in IE). --GmBowen
- Just what is "VML"? From your code it looks like something Microsoft-specific - is it? Do you have a reference for this language (if it is a language)? What does the acronym stand for? Anyway - if it's an an XML application it doesn't look like your embedding is valid XML. (XHTML 1.x isn't that extensible yet, actually - that will come with XHTML 2.0.) --JavaWoman
- Looks like an ancient precursor of SVG (Scalable Vector Graphics) which, as opposed to VML which never made it past the draft proposal phase (dead duck), is a web standard. (In fact people from Microsoft, Macromedia and Visio also are among the authors of SVG.) Some browsers can show that natively, others by means of an (Adobe) plugin. --JavaWoman
- Now for the "real" answer... If markup isn't embedded in double-double quotes, the formatter with "escape" it. If it is embedded in double-double quotes, it is fed through SafeHTML. That means SafeHTML would have to be taught about languages that can be embedded in XHTML (SVG, MATHML...) - and have been embedded according to XML standards. Of course that can be done by extending the class (not changing it!). You'll then also have to do your own research as to which elements (and attributes) of the embedded language might constitute a security risk, and filter those...
- So you have these tasks:
- (Optionally) translate your VML to the standard SVG (that will ensure wider though not complete browser support)
- Make sure it's embedded according to the rules of XML (the SVG standard gives good examples); this also entails changing the header.php in Wikka (currently misplaced in actions) to define the namespace to be used by the embedded language in the html element
- Research the language (completely) to determine what security risks there might be - similar to what Roman Ivanov has done for us all with respect to HTML (+ JavaScript)
- As you can imagine, that's a major job - not one I would like to tackle any time soon... --JavaWoman
- Yeah, way more work than I thought. I'll look for other solutions. Thanks for the framework tho'. -- Mike
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