Jump to content

ryan

Administrators
  • Posts

    17,232
  • Joined

  • Days Won

    1,699

Everything posted by ryan

  1. As far as I know, there was only that one old buggy version of MySQL, but that created problems for anything running in it, so it's kind of a rare thing to find it. I doubt the MySQL version is the problem in this case. What 3rd party modules are installed? What browser and version are you using? When you move a page, does it immediately return back to the original location, or only after you refresh/reload the page? Do you literally have pages named "page2", "page3", etc.? If so, you might want to consider different naming because that's the default naming of pagination URLs.
  2. It sounds to me like that person unintentionally edited and renamed the 404 page. The safest bet would be to just assume that is your 404 page and change the title back to "404 not found" and then lock it. But it sounds like you already found a solution there.
  3. What version of ProcessWire are we talking about here? It sounds like 2.3 based on the file names mentioned, but want to double check. That seems pretty odd that PHP is writing sessions somewhere other than where specified. But ProcessWire uses PHP's native session features, so PHP is the one ultimately reading the session file rather than ProcessWire. Meaning, it's not possible for ProcessWire to read it from the wrong place, and I doubt PHP would read it from the wrong place. The only exception would be if you are using Database sessions, which is a module included with ProcessWire 2.3–did you install that by any chance? That would change the things that we need to look at. Also, just to rule out other possibilities, disable the "session fingerprinting" option in your /site/config.php and change the default session name from 'wire' to whatever PHP's default is: $config->sessionName = session_name();
  4. Welcome @pnikosis, glad that you are enjoying ProcessWire! If you've got an external database that is still being updated than I would just query the external database rather than trying to load it into PW. On the other hand, if the database is no longer being updated (meaning, you wouldn't have to maintain two versions) then moving it into PW might make sense. But for querying the external database, you can use mysqli, but you might also want to look at switching to the PW dev branch (future version 2.4) which switches to the PDO database driver. Mysqli is still available in 2.4, so you can actually use whichever you prefer. Though mysqli will probably be dropped once we reach ProcessWire 3.0, but if it's installed in your PHP then of course it remains available for you. So if you use mysqli, probably it's better to use PHP's "mysqli" class rather than ProcessWire's extension of it, just for future compatibility.
  5. All ProcessWire fields are indexed (including datetime fields), so I don't think you'll have a problem with it being slow. But if you want to retrieve and load a 1000+ pages at a time, that could be potentially slow (and perhaps run out of memory). It's important to place limits (i.e. "limit=50") on any queries that can return huge amounts of pages, in order to ensure that everything stays running fast. I don't think that would be slow. But paginate your results by placing a limit to be sure. Also, I doubt that you need the parent=/events/ since you are already specifying a template. Though if I understand your structure right, if you did want to specify a parent, you'd probably want to use has_parent rather than parent, since the time pages live under /events/some-event/ rather than /events/. Last thing to note is that you can't have spaces before/after operators like you do in your time.date_end > $today" -- that would need to be "time.date_end>today". Btw, you can specify "today" rather than populating a $today variable, if you prefer. Actually you can do this. But note the same suggestions I had above. There would also be this alternative, which might be potentially faster because ProcessWire is a little more optimized for parent-field matching queries than children-field matching queries (given that a page can have only 1 parent, but any number of children): $pages->find("template=time, parent.on_frontpage=1, enddate>today"); When you foreach the results of that, note they are 'time' pages rather than 'event' pages, so you'd want to refer to the parent in order to get the event.
  6. Thanks, I understand now. If you look in the FormBuilderEntries.php file, you'll see this line: protected $dateFormat = 'Y/m/d G:i a'; That 'G' is actually supposed to be a lowercase 'g' for 12-hour format, as 'G' is 24-hour format. I will correct this. You can also change it yourself in that file if you'd like, or you can can do this in your foreach loop above: $e['created'] = date('Y/m/d g:i a', strtotime($e['created']));
  7. It sounds to me like an issue of case, somewhere. The skyscrapers profile field name is fieldset_meta_END (where END is uppercase). What is the case of the table in your MySQL db? I'm guessing it's got the uppercase END in it. You might try adjusting this setting in your /site/config.php to false, or rename the table in PhpMyAdmin to be all lowercase.
  8. InputfieldImage is a type of InputfieldFile, so the two should work the same for the most part.
  9. There are name collision possibilities with date/time (two being added at same exact time), but it's reasonably reliable other than that. ProcessWire actually uses microtime when creating pages internally that aren't named (or don't yet have a name), like the pages it creates for repeaters. I could see using the same method for unnamed pages anywhere.
  10. Glad you got it! I'll have to remember that one too. No doubt these CKEditor 4.1+'s ACF system is a mixed blessing. On the whole, I'm glad to have it (especially with clients that like to copy/paste from Word, etc.) but I can see it being a real bear when trying to do something out of the norm. I've gone ahead and updated the CKEditor version so that it now supports options for: Enable ACF (Advanced Content Filter)? [Yes/No] (default=Yes) Enable HTML Purifier? [Yes/No] (default=Yes, if installed) When upgrading to this version, revisit all your textarea fields using CKEditor in Setup > Fields, and see the new options on the Input tab. Hit save, even if you don't change anything, just to commit the new settings.
  11. Teppo is right that all recent versions of PW will take care of creating a name for you, so long as you've at least set a title. It will also number-increment the name (i.e. "page-name-2") if one already exists. But if you want to go with a different way of setting the name, perhaps some other format, then it's always fine to set it yourself too.
  12. Another great site–nice job! I liked reading this. Great way to put it. It's exactly what I try to do with my clients too. Though I have had a couple of clients that want the site built in ProcessWire so that they can make edits, but then continue to sending text edits to me…
  13. Just testing out HTML purifier with a /test.php in my webroot: <?php include("./index.php"); $purifier = wire('modules')->get('MarkupHTMLPurifier'); $text = "<pre class='test' onclick='alert(1)'>Test</pre><script>alert(2)</script>"; $text = $purifier->purify($text); echo htmlentities($text); Result: <pre class="test">Test</pre> I have a feeling it's CKEditor that's stripping out your <pre> class attribute. Try adding "pre[class]" or "pre[*]" or "*[*]" to your extraAllowedContent rules in the latest CKEditor inputfield to see if that corrects it?
  14. It's a pretty recent addition. I think it's in 2.3 stable. But if not, it's the same thing as implode('/', $input->urlSegments);
  15. You are right, the best bet is to make sure your PHP versions are up to date. The current version of ProcessWire is the last version that will work with PHP versions prior to 5.3.8, so it won't be an issue for much longer.
  16. Thanks for posting this Matthew. A couple things I found that I wanted to mention, since this is a front-end form: // Set a temporary upload location where the submitted files are stored during form processing $upload_path = $config->paths->assets . "files/contact_files/"; You want your temporary upload path to be a non web accessible path. Also, if you've got multiple users uploading at the same time, it seems like there is potential for filename collisions, though not sure how big of a concern that is in this case. But you can at least make the directory non web accessible by preceding it with a period, i.e. ".contact_files" rather than "contact_files". $other_photos->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif')); Keep in mind that WireUpload is only validating the extension. It is not telling you for sure that it's an image. It could very well be some kind of executable with a jpg extension. I don't necessarily know how such a thing could be exploited, other than that I'm not so comfortable with letting a front-end user upload files that end up untouched in a publicly accessible directory. What would probably be safer is to make a new copy of any uploaded images before adding them to the page, and validate the size is within allowed limits while you are at it. $error = ''; $imageInfo = getimagesize($pathname); if($imageInfo) list($width, $height) = $imageInfo; if(!$imageInfo) { $error = "Image is not valid"; } else if($width < 105 || $height < 105) { $error = "Image is too small"; } else if($width > 1600 || $height > 1200) { $error = "Image is too big"; } else { // create your own, slightly smaller copy $sizer = new ImageSizer($pathname); if(!$sizer->resize($width-10, $height-10)) $error = "Unable to resize image"; } if($error) { unlink($pathname); echo "<p>Error: $error</p>"; } else { // add image to page }
  17. I understand now, thanks So we just need to link to http://akismet.com/plans/ rather than http://en.wordpress.com/api-keys/ -- I will update.
  18. Sounds like your webhost is preventing you from using htaccess Options. The most important one from a security aspect is the "-Indexes" option. You really don't want to allow indexes, as that means anyone can browse a directory on your server just by typing in the URL. Hopefully they've got this disabled already, but I would be a little uncomfortable with the webhost not letting me specify these options.
  19. What attributes are getting stripped that you need? (other than data attributes). HTML Purifier seems to allow class attributes by default (not to mention style attributes too), so it wouldn't be the one stripping those. My understanding is that the default filters in HTMLPurifier are primarily aimed at cleaning the HTML to make it safe (i.e. removing any attributes that could introduce javascript/XSS). So things like class/style attributes don't seem to be a concern to HTML Purifier, but data-* attributes probably would. But the content filters in HTMLPurifier and CKEditor seem to have different purposes. I've been experimenting here with adding the 'extraAllowedContent' option (rather than 'allowedContent') to the CKEditor module, as it seems like this is the one designed for modifying the default behavior? (not positive on that). Though I've found the allowedContent rules string to be a little unpredictable. For instance, an extraAllowedContent string of "p[class]" should mean "Allow <p> elements with optional class attribute." But that doesn't seem to work. I can't get CKEditor to allow class attributes that way unless I manually specify the class name, like "p(test)" to allow a <p class="test"></p> Just pushed this update to CKEditor, so you should have the extraAllowedContent filter available. Let me know what else we need.
  20. Online polls and ratings are always a tricky thing just because if someone is motivated, they can manipulate it. And depending on how creative they are, there's not much you can do about it. Even PollDaddy isn't immune to this. What you did last time, by requiring a social network login, is a definitely improvement over security by IP address. But still not foolproof, and you do end up with a lot of votes coming from people that know nothing about the product, other than someone asked them to vote. But at least a social network login increases the cost to any individual trying to manipulate results. But if it were me, I would use your own custom form (or Form Builder) and place some burden of proof on the voter, like an example of a site where they have used the CMS. For example, these form fields: • How many sites have you used with this CMS? [ ] 0 [ ] 1 [ ] 2-3 [ ] More than 3 • List one example of a site you have used this CMS on? (must be currently running the CMS) [Enter the URL] • For the site you listed above, please provide one URL where we can confirm the CMS. This may be any one of the following: 1. Any URL that refers to the CMS (like a login, info or credits URL–we will keep confidential). 2. Any URL that contains a link to CMSCritic.com. 3. Any URL that references you as an employee, author, editor, designer or developer of the site. [Enter the URL] • How do you use the CMS? [ ] As a web developer [ ] As a web designer [ ] As an editor [ ] As a user [ ] I don't use it • What is your favorite feature of this CMS? [Text field] • Enter your email address (we will send you a email to confirm your vote) (confirm) I think questions like the above would really help to keep the control away from those looking to manipulate results. It would also keep the votes focused on people that actually have experience with the product. I would also include IP filtering and email verification, but not rely upon it. If there's any question of feasibility, this is all stuff that Form Builder (or other form services) can do without too much effort.
  21. There are a lot of big security considerations with forms that accept files, and what happens to those files afterwards. The scope of it is a bit beyond what I think most would want to implement and monitor for a front-end form. As a result, I recommend using something existing that can do it safely, like ProcessWire Form Builder, or an external service like WuFoo.
  22. I haven't actually tried an autocomplete in a repeater yet, but theoretically it should work. However, you may need to switch to the dev branch, since that contains an update that enabled autocomplete fields to work in tabs (which I'm hoping means they also work in repeaters). Let me know if you find it still doesn't work.
  23. Not specific to multi-language page names, but since it's in the dev branch and related, I figured I'd mention it here… Multi-language page fields inherit the default language value when they are blank. While probably a good default, sometimes this behavior is not desirable. So on the latest dev commit, you can now configure that behavior on a field-by-field basis (for any multi-language field). The screenshot below probably explains it best.
  24. One idea came up, and was just curious about the feasibility of it: What if the "active" tab was based on the current user's language? So if I had my language set as Spanish, I'd see the Spanish tabs active (rather than default language tab) when editing a page?
  25. For authors, there were only about 6 of them at import time, so I created the authors as users in PW manually. I also added the "wpid" field to the "user" template, and populated the value of that manually. That was easy to find in WordPress just by editing the author and noting the ID in the URL. The WordPress wp_posts table has a field in it called post_author, which is the ID of the author. So assuming we've got a user in ProcessWire with a "wpid" that matches up to that, it's easy for us to assign the right PW user to each post. You'll see how this takes place in the code below. Wrapping it up Here is the same "import" code as in the first post, but I added all the code accounting for authors, topics, tags, and images back into it. This all just goes in a ProcessWire template file, and viewing the page triggers the import. Because it's aware of stuff that is already imported, it can be run multiple times without causing duplication. <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Import Posts</title> </head> <body> <table border='1' width='100%'> <thead> <tr> <th>New?</th> <th>ID</th> <th>Author</th> <th>Date</th> <th>Name</th> <th>Title</th> <th>Images</th> <th>Topics</th> <th>Changes</th> </tr> </thead> <tbody> <?php // get access to WordPress wpautop() function include("/path/to/wordpress/wp-includes/formatting.php"); $wpdb = new PDO("mysql:dbname=wp_cmscritic;host=localhost", "user", "pass", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); $posts = wire('pages')->get('/posts/'); $sql = " SELECT * FROM wp_posts WHERE post_type='post' AND post_status='publish' ORDER BY post_date "; $query = $wpdb->prepare($sql); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { $post = $posts->child("wpid=$row[ID]"); // do we already have this post? if(!$post->id) { // create a new post $post = new Page(); $post->template = 'post'; $post->parent = $posts; echo "Creating new post...\n"; } $post->of(false); $post->name = wire('sanitizer')->pageName($row['post_name']); $post->title = $row['post_title']; $post->date = $row['post_date']; $post->summary = $row['post_excerpt']; $post->wpid = $row['ID']; // find the post author $author = wire('users')->get("wpid=$row[post_author]"); // if we don't have this post author, assign one (Mike) if(!$author->id) $author = wire('users')->get("mike"); // set the post author back to the page $post->createdUser = $author; // assign the bodycopy after adding <p> tags // the wpautop() function is from WordPress /wp-includes/wp-formatting.php $post->body = wpautop($row['post_content']); // give detailed report about this post echo "<tr>" . "<td>" . ($post->id ? "No" : "Yes") . "</td>" . "<td>$row[ID]</td>" . "<td>$row[post_author]</td>" . "<td>$row[post_date]</td>" . "<td>$row[post_name]</td>" . "<td>$row[post_title]</td>" . "<td>" . importImages($post) . "</td>" . "<td>" . importTopicsAndTags($wpdb, $post) . "</td>" . "<td>" . implode('<br>', $post->getChanges()) . "</td>" . "</tr>"; $post->save(); } function importTopicsAndTags(PDO $wpdb, Page $page) { // see implementation in previous post } function importImages(Page $page) { // see implementation in previous post } ?> </tbody> </table> </body> </html>
×
×
  • Create New...