public function indexAction() { $this->fa->readOnly(); $this->fa->fileReadOnly(); $form = new \FA\Form($this->current_module_config->forms->avatar); // Handle new avatar upload. if ($_POST && $this->request->hasFiles() && $form->isValid(array_merge($_POST, $_FILES))) { $files = $form->getFiles($this->request); $file = $files['avatar'][0]; if ($file->isUploadedFile()) { $source_path = $file->getTempName(); $art_dir = $this->config->application->art_path; // Clean up original filename for destination filename. $source_info = pathinfo($file->getName()); $dest_filename = preg_replace("/[^A-Za-z0-9_]/", '', substr($source_info['filename'], 0, 30)) . '.gif'; $dest_path = $art_dir . '/' . $this->user->lower . '/avatars/' . $dest_filename; // Create resized image for avatar. $imagine = new Imagine(); $size = new Box(100, 100); $mode = ImageInterface::THUMBNAIL_INSET; $imagine->open($source_path)->thumbnail($size, $mode)->save($dest_path); // Set as default avatar also. $this->user->setAvatar($dest_path); $this->alert('<b>New avatar uploaded!</b><br>The avatar has been set as your default.', 'green'); return $this->redirectHere(); } } $this->view->form = $form; $this->view->gravatar = $this->_gravatar; $this->view->avatars = $this->_avatars; }
public function editAction() { $comment_id = (int) $this->getParam('id'); $form_config = $this->current_module_config->forms->upload_comment; $form = new \FA\Form($form_config); $form->populate($_POST); if ($_POST && $form->isValid($_POST) && $this->csrf->verify($form->getValue('csrf'), '_upload_comments')) { // TODO: Check comment edit rate limit here! $comment = UploadComment::find($comment_id); if (!$comment instanceof UploadComment) { throw new \FA\Exception('Comment not found!'); } if (!$comment->canEdit($this->user)) { throw new \FA\Exception('Unable to edit comment!'); } $upload = $comment->upload; // Prevent posting if comments are locked if ($upload->comments_locked) { throw new \FA\Exception('Comments are locked on this Upload!'); } // Verify the user can even progress further self::_userCheck($upload); // Update the comment's text $comment->message = $form->getValue('JSMessage'); $comment->save(); // Redirect to the Upload page to our comment! // TODO: Add a way to auto-lock on to the comment. Maybe a perma-link style approach? return $this->redirectToName('upload_view', array('id' => $upload->id)); } }
public function indexAction() { // TODO: Use variable for this setting. $per_page = 48; $form_config = $this->current_module_config->forms->browse->toArray(); if (!$this->fa->canSeeArt('mature')) { unset($form_config['elements']['rating'][1]['options'][Upload::RATING_MATURE]); unset($form_config['elements']['rating'][1]['options'][Upload::RATING_ADULT]); } elseif (!$this->fa->canSeeArt('adult')) { unset($form_config['elements']['rating'][1]['options'][Upload::RATING_ADULT]); } $form = new \FA\Form($form_config); if ($this->request->isPost() && $form->isValid($_POST)) { $filters = $form->getValues(); } else { $filters = $form->getDefaults(); } // Force form to default to page 1, so that if filters change, the page will reset. $form->populate(array('page' => 1)); $this->view->form = $form; // Create query builder. $qb = $this->em->createQueryBuilder(); $qb->select('up')->from('Entity\\Upload up'); if (!empty($filters['category']) && $filters['category'] != 1) { $qb->andWhere('up.category = :category')->setParameter('category', $filters['category']); } if (!empty($filters['theme']) && $filters['theme'] != 1) { $qb->andWhere('up.theme = :theme')->setParameter('theme', $filters['theme']); } if (!empty($filters['species']) && $filters['species'] != 1) { $qb->andWhere('up.species = :species')->setParameter('species', $filters['species']); } if (!empty($filters['gender']) && $filters['gender'] != 0) { $qb->andWhere('up.gender = :gender')->setParameter('gender', $filters['gender']); } if (isset($filters['rating'])) { $qb->andWhere('up.rating IN (:ratings)')->setParameter('ratings', (array) $filters['rating']); if (in_array(Upload::RATING_MATURE, $filters['rating']) || in_array(Upload::RATING_ADULT, $filters['rating'])) { $this->fa->setPageHasMatureContent(true); } } $query = $qb->orderBy('up.created_at', 'DESC')->getQuery(); $pager = new \FA\Paginator\Doctrine($query, $filters['page'], $per_page); $this->view->page_current = $filters['page']; $this->view->page_count = $pager->getPageCount(); $this->view->pager = $pager; $this->view->thumbnail_size = $this->user->getVariable('thumbnail_size'); }
public function verifyAction() { if (!$this->hasParam('code')) { throw new \FA\Exception('No verification code was provided! Your e-mail should have included a verification code.'); } $code = $this->getParam('code'); $rr = RegistrationRequest::validate($code); if (!$rr instanceof RegistrationRequest) { throw new \FA\Exception('Your verification code could not be validated. The code may have expired, or already been used.'); } $form = new \FA\Form($this->current_module_config->forms->register_complete); $form->setDefaults(array('username' => $rr->username, 'email' => $rr->email)); if ($_POST && $form->isValid($_POST)) { $data = $form->getValues(); $bday_timestamp = strtotime($data['birthday'] . ' 00:00:00'); $bday_threshold = strtotime('-13 years'); // Rebuild the birthday into this format (in case it wasn't provided this way by the browser). $data['birthday'] = date('Y-m-d', $bday_timestamp); if ($bday_timestamp == 0) { $form->addError('birthday', 'We could not process your birthday as specified. Please try again.'); } if ($bday_timestamp >= $bday_threshold) { $form->addError('birthday', 'Our site cannot accept users under 13 years of age due to United States federal law, 15 USC 6501-6506.'); } if (!$form->hasErrors()) { $user = new User(); $user->fromArray(array('username' => $rr->username, 'password' => $data['password'], 'birthday' => $data['birthday'], 'fullname' => $data['fullname'], 'email' => $rr->email, 'regemail' => $rr->email, 'regbdate' => str_replace('-', '', $data['birthday']))); $user->save(); $rr->is_used = true; $rr->save(); // Create "skeleton" art folder. $app_cfg = $this->config->application; $user_art_dir = $app_cfg->art_path . '/' . $user->lower; @mkdir($user_art_dir); foreach ($app_cfg->art_folders as $art_folder) { $art_folder_path = $user_art_dir . '/' . $art_folder; @mkdir($art_folder_path); } // Log in the user. $this->auth->setUser($user); $this->alert('<b>Welcome to FurAffinity!</b><br>Your account has been created, and you are now logged in to the web site.', 'green'); return $this->redirectHome(); // return $this->view->pick('register/welcome'); } } $this->view->title = 'Complete New Account Creation'; return $this->renderForm($form); }
public function viewAction() { $id = (int) $this->getParam('id'); $record = TroubleTicket::getRepository()->findOneBy(array('id' => (int) $id, 'user_id' => $this->user->id)); if (!$record instanceof TroubleTicket) { throw new \FA\Exception('Trouble ticket not found!'); } $this->view->ticket = $record; // Create reply form. $form_config = $this->current_module_config->forms->ticket_reply->toArray(); if (!$record->is_resolved) { unset($form_config['elements']['reopen']); } $form = new \FA\Form($form_config); if ($this->request->isPost() && $form->isValid($_POST)) { $this->fa->readOnly(); // Handle reply to the ticket. $data = $form->getValues(); // Reopen ticket if indicated. if ($data['reopen']) { $data['message'] .= "\n\n[system]: User reopened the ticket."; $record->is_resolved = false; } $record->replies += 1; $record->last_reply_date = time(); $record->save(); // Add note to message for note sharing. if ($data['share_notes']) { $data['message'] .= "\n\n[system]: Granting admins the permission to read user notes for the duration of the ticket."; } $comment = new TroubleTicketComment(); $comment->ticket = $record; $comment->is_staff = false; $comment->user = $this->user; $comment->fromArray($data); $comment->save(); // Store note sharing information in user variable. if ($data['share_notes']) { $ticket_id = $record->id; $this->user->setVariable('RO.adminsCanSeeNotes', $ticket_id); } // Notify and redirect user. $this->alert('<b>Reply posted!</b>', 'green'); return $this->redirectHere(); } $this->view->form = $form; }
public function editAction() { $this->fa->readOnly(); $form_config = $this->current_module_config->forms->journal->toArray(); $form = new \FA\Form($form_config); $record = null; $edit_mode = false; $id = (int) $this->getParam('id'); if ($id != 0) { $record = Journal::getRepository()->findOneBy(array('id' => $id, 'user_id' => $this->user->id)); if (!$record instanceof Journal) { throw new \FA\Exception('Journal entry not found!'); } $record_info = $record->toArray(FALSE, TRUE); if ($this->user->getVariable('featured_journal_id') == $id) { $record_info['is_featured'] = 1; } $form->populate($record_info); $edit_mode = true; } if ($this->request->isPost() && $form->isValid($_POST)) { if (!$record instanceof Journal) { $record = new Journal(); $record->user = $this->user; } $data = $form->getValues(); if ($data['is_featured']) { $this->user->setVariable('featured_journal_id', $id); } elseif ($this->user->getVariable('featured_journal_id') == $id) { $this->user->deleteVariable('featured_journal_id'); } $record->fromArray($data); $record->save(); if ($edit_mode) { $this->alert('<b>Journal edited!</b>', 'green'); } else { $this->alerT('<b>New journal posted!</b>', 'green'); } return $this->redirectFromHere(array('action' => 'index', 'id' => NULL)); } $this->view->edit_mode = $edit_mode; $this->view->form = $form; }
public function indexAction() { $form = new \FA\Form($this->current_module_config->forms->recover); if ($_POST && $form->isValid($_POST)) { $data = $form->getValues(); $data['email'] = mb_strtolower($data['email'], 'UTF-8'); $user = User::getRepository()->findOneBy(array('username' => $data['username'], 'email' => $data['email'])); if ($user instanceof User) { $user->lostpw = \FA\Legacy\Utilities::uuid(); $user->save(); \FA\Messenger::send(array('to' => $user->email, 'subject' => 'Password Recovery Code', 'template' => 'account_recover', 'vars' => array('id' => $user->id, 'code' => $user->lostpw))); $this->alert('<b>A password recovery link has been sent to your e-mail address.</b><br>Click the link in the e-mail to reset your password.', 'green'); return $this->redirectHome(); } else { $form->addError('username', 'We could not locate an account with this username and e-mail address in our system. Please try again!'); } } $this->view->setVar('title', 'Forgot My Password'); return $this->renderForm($form); }
public function profileAction() { $form_config = $this->current_module_config->forms->settings_profile->toArray(); // Populate the submission selection dropdowns. $submissions = $this->em->createQuery('SELECT s.id, s.title, s.is_scrap FROM Entity\\Upload s WHERE s.user_id = :user_id')->setParameter('user_id', $this->user->id)->getArrayResult(); $submission_select = array('featured' => array('' => 'Disabled'), 'profile_pic' => array('' => 'Disabled')); foreach ($submissions as $submission) { $group = $submission['is_scrap'] ? 'profile_pic' : 'featured'; $submission_select[$group][$submission['id']] = $submission['title']; } $form_config['groups']['featured_items']['elements']['featured'][1]['options'] = $submission_select['featured']; $form_config['groups']['featured_items']['elements']['profile_pic'][1]['options'] = $submission_select['profile_pic']; // Initialize the form. $form = new \FA\Form($form_config); // Set form defaults based on current user database records. $contact = $this->user->contact; if (!$contact instanceof UserContact) { $contact = new UserContact(); $contact->user = $this->user; $contact->save(); } $form->setDefaults(array_merge($this->user->toArray(FALSE, TRUE), $contact->toArray(FALSE, TRUE))); if ($_POST && $form->isValid($_POST)) { $data = $form->getValues(); // Load data directly into DB models using the fromArray helpers. $this->user->fromArray($data['user']); $this->em->persist($this->user); $contact->fromArray($data['contact']); $this->em->persist($contact); // Push any model changes to the DB. $this->em->flush(); $this->alert('<b>Profile Updated!</b><br>Your changes have been saved.', 'green'); return $this->redirectHere(); } $this->view->form = $form; }
public function editAction() { $types = $this->config->fa->upload_types->toArray(); $id = (int) $this->getParam('id'); if ($id !== 0) { // Edit existing record. // TODO: Reimplement administrator access. $record = Upload::getRepository()->findOneBy(array('id' => $id, 'user_id' => $this->user->id)); if (!$record instanceof Upload) { throw new \FA\Exception('Submission ID not found!'); } $edit_mode = true; $type = $record->submission_type; } else { // Create new submission. $type = $this->getParam('type'); // Show type selector if no type is specified. if (empty($type) || !isset($types[$type])) { $this->view->types = $types; return $this->view->pick('uploads/select'); } $edit_mode = false; $record = NULL; } $type_info = $types[$type]; $form_config = $this->current_module_config->forms->uploads_edit->toArray(); // Create mode changes if (!$edit_mode) { $form_config['groups']['files']['elements']['submission'][1]['required'] = true; unset($form_config['groups']['files']['elements']['submission'][1]['description']); unset($form_config['groups']['files']['elements']['rebuild_thumbnail']); } // Changes to the form based on submission type. if (isset($type_info['category'])) { $form_config['groups']['metadata']['elements']['category'][1]['default'] = $type_info['category']; } if ($type !== Upload::TYPE_IMAGE) { unset($form_config['groups']['files']['elements']['rebuild_thumbnail']); } $form_config['groups']['files']['elements']['submission'][1]['allowedTypes'] = $type_info['types']; // Create the form class. $form = new \FA\Form($form_config); // Populate the form (if available). if ($record instanceof Upload) { $form->setDefaults($record->toArray(TRUE, TRUE)); } // Handle form submission. if ($_POST && $this->request->hasFiles() && $form->isValid(array_merge($_POST, $_FILES))) { $data = $form->getValues(); if (!$record instanceof Upload) { $record = new Upload(); $record->upload_type = $type; $record->user = $this->user; $record->is_hidden = true; // Hide until properly populated. $record->save(); // Immediately save to generate IDs used in next steps. } $record->fromArray($data); // Begin file handling. \IMagick::setResourceLimit(\Imagick::RESOURCETYPE_MEMORY, 32); \IMagick::setResourceLimit(\Imagick::RESOURCETYPE_MAP, 32); $files = $form->getFiles($this->request); $imagine = new Imagine(); $submission_file = $files['submission'][0]; $thumbnail_file = null; $thumbnail_paths = array(); $preview_file = null; $preview_paths = array(); if ($submission_file) { $submission_paths = $record->generatePaths($submission_file->getName()); // Create the proper artwork directory if it doesn't exist. $submission_dir = dirname($submission_paths['full']['path']); @mkdir($submission_dir); if ($type == Upload::TYPE_IMAGE) { // Handle image uploads. $submission_image = $imagine->open($submission_file->getTempName()); $is_animated = count($submission_image->layers()) > 1; // So, it seems Imagine really loves to screw up GIFs, so lets avoid that if ($is_animated) { $dest_path = $submission_paths['full']['path']; // Copying this instead of moving due to the file being reused by preview/thumbnail copy($submission_file->getTempName(), $dest_path); } else { $submission_image->save($submission_paths['full']['path'], array('animated' => $is_animated)); } // Make this file the thumbnail if no other is specified. if (empty($files['thumbnail']) && (!$edit_mode || $data['rebuild_thumbnail'])) { $thumbnail_file = $submission_file; $thumbnail_paths = $submission_paths; } // Set up the preview parameters $preview_file = $submission_file; $preview_paths = $submission_paths; } else { // Handle non-images. Way simpler, right? $dest_path = $submission_paths['full']['path']; $submission_file->moveTo($dest_path); // Prevent the file from being deleted below. $submission_file = null; } $record->setFull($submission_paths['full']['base']); } // Use the thumbnail field if supplied. if (!empty($files['thumbnail'])) { $thumbnail_file = $files['thumbnail'][0]; $thumbnail_paths = $record->generatePaths($thumbnail_file->getName()); } // If we haven't set a preview image/path, then use the thumbnail if possible if (is_null($preview_file)) { $preview_file = $thumbnail_file; $preview_paths = $thumbnail_paths; } // Process either the uploaded thumbnail, or resize the original file to be our preview. if ($preview_file) { // Generate "small" size thumbnail. $preview_size = new Box(self::MAX_PREVIEW_SIZE, self::MAX_PREVIEW_SIZE); self::_saveAsJPG($imagine, $preview_file, $preview_paths['small']['path'], 90, $preview_size); $record->setSmall(self::_changeExtension($preview_paths['small']['base'], 'jpg')); } // Process either the uploaded thumbnail, or thumbnailize the original file. if ($thumbnail_file) { // Generate "thumb" size thumbnail. $thumbnail_size = new Box(self::MAX_THUMB_SIZE, self::MAX_THUMB_SIZE); self::_saveAsJPG($imagine, $thumbnail_file, $thumbnail_paths['thumbnail']['path'], 90, $thumbnail_size); $record->setThumbnail(self::_changeExtension($thumbnail_paths['thumbnail']['base'], 'jpg')); } // Delete the temp files (if not already moved). if ($submission_file) { @unlink($submission_file->getTempName()); } if ($thumbnail_file) { @unlink($thumbnail_file->getTempName()); } // Unhide the record that was hidden earlier. if (!$edit_mode) { $record->is_hidden = false; } $record->save(); $view_url = $this->url->get('view/' . $record->id); $view_link = 'You can <a href="' . $view_url . '" target="_blank_">view your submission\'s public page here</a>.'; if ($edit_mode) { $this->alert('<b>Submission Updated!</b><br>' . $view_link, 'green'); } else { $this->alert('<b>New Submission Uploaded!</b><br>' . $view_link, 'green'); } return $this->redirectFromHere(array('action' => 'index', 'id' => NULL, 'type' => NULL)); } // Render the main form. $this->view->type_info = $type_info; $this->view->form = $form; }
public function shoutAction() { $this->fa->readOnly(); $this->acl->checkPermission('is logged in'); if ($this->user->getVariable('account_disabled')) { $this->alert('<b>Your account is currently disabled.</b><br>You cannot make posts while your account is disabled.'); return $this->redirectToReferrer(); } // TODO: Comment rate limit // enforce_comment_rate_limit($PAGE_OWNER_INFO['userid']); // Check blocklist if ($this->owner->isBlocked($this->user)) { $this->alert('<b>Could not post shout.</b><br>Error: User has blocked you.', 'red'); return $this->redirectToReferrer(); } // Check for disabled shouts. if ($this->owner->getVariable('disable_shouts') == 1) { $this->alert('<b>Shouts have been disabled on this user\'s account.</b><br>Your shout could not be posted.', 'red'); return $this->redirectToReferrer(); } $form_config = $this->current_module_config->forms->shout->toArray(); $form = new \FA\Form($form_config); if ($this->request->isPost() && $form->isValid($_POST)) { $data = $form->getValues(); $record = new Shout(); $record->sender = $this->user; $record->recipient = $this->owner; $record->message = $data['shout']; $record->save(); $this->alert('<b>Shout posted!</b>', 'green'); return $this->redirectFromHere(array('name' => 'user_view')); } return $this->renderForm($form, 'edit', 'Submit a Shout'); }
public function indexAction() { $form_config = $this->current_module_config->forms->search->toArray(); $form_config['elements']['perpage']['default'] = $this->user->getVariable('perpage'); if (!$this->fa->canSeeArt('mature')) { unset($form_config['elements']['rating'][1]['options'][Upload::RATING_MATURE]); unset($form_config['elements']['rating'][1]['options'][Upload::RATING_ADULT]); } elseif (!$this->fa->canSeeArt('adult')) { unset($form_config['elements']['rating'][1]['options'][Upload::RATING_ADULT]); } $form = new \FA\Form($form_config); $data = $form->getDefaults(); if ($this->request->isPost() && $form->isValid($_POST)) { // Leave all values default if not specified by the user. $data = array_merge($data, array_filter($form->getValues())); } // Force form to default to page 1, so that if filters change, the page will reset. $form->populate(array('page' => 1)); $this->view->form = $form; $pager = NULL; // Run the search query if the terms were provided if (!empty($data['q'])) { // TODO: Add user search back into this. // Create the sphinx request hash $sphinx_request['q'] = preg_replace('/[\\x00-\\x1F]/', ' ', $data['q']); $sphinx_request['page'] = $data['page']; $sphinx_request['perpage'] = $data['perpage']; $sphinx_request['use_index'] = 'submissions_delta submissions'; $sphinx_request['match_mode'] = $this->_sphinx_match_mode($data['mode']); $sphinx_request['field_weights'] = array('title' => 3, 'keywords' => 4, 'message' => 2, 'filename' => 1, 'lower' => 1); $sphinx_request['order_by'] = $data['order_by']; $sphinx_request['order_direction'] = $data['order_direction']; // Filters $sphinx_request['filters'] = array(); if (isset($data['rating'])) { $sphinx_request['filters']['adultsubmission'] = (array) $data['rating']; if (in_array(Upload::RATING_MATURE, $data['rating']) || in_array(Upload::RATING_ADULT, $data['rating'])) { $this->fa->setPageHasMatureContent(true); } } if (!empty($data['type'])) { $sphinx_request['filters']['type'] = $data['type']; } if ($data['range'] != 0) { $sphinx_request['filters']['date'] = array(time() - $data['range'], time()); } // Make the request $sphinx_error = NULL; $sphinx_warning = NULL; $sphinx_result = $this->_sphinx_make_request($sphinx_request, $sphinx_error, $sphinx_warning); if (!$sphinx_result) { throw new \FA\Exception($sphinx_error); } if ($sphinx_result['total_found'] && isset($sphinx_result['matches']) && is_array($sphinx_result['matches'])) { $found_docs = array(); $doc_info = array(); foreach ($sphinx_result['matches'] as $match) { $found_docs[] = $match['id']; $doc_info[$match['id']] = $match; } $result = $this->em->createQuery('SELECT up, us, field(up.id, :ids) AS HIDDEN field FROM Entity\\Upload up JOIN up.user us WHERE up.id IN (:ids) ORDER BY field')->setParameter('ids', $found_docs)->execute(); $pager = new \FA\Paginator\Sphinx($result, $sphinx_result['total_found'], $data['page'], $data['perpage']); } } if (!$pager) { $pager = new \FA\Paginator\Sphinx(array(), 0, $data['page'], $data['perpage']); } $this->view->page_current = $data['page']; $this->view->page_count = $pager->getPageCount(); $this->view->pager = $pager; $this->view->thumbnail_size = $this->user->getVariable('thumbnail_size'); }
public function editgroupAction() { $this->fa->readOnly(); $form_config = $this->current_module_config->forms->foldergroup->toArray(); $form = new \FA\Form($form_config); $id = (int) $this->getParam('id'); if ($id) { $record = FolderGroup::getRepository()->findOneBy(array('id' => $id, 'user_id' => $this->user->id)); if (!$record instanceof FolderGroup) { throw new \FA\Exception('Folder ID not found!'); } $form->populate($record->toArray()); } if ($this->request->isPost() && $form->isValid($_POST)) { $data = $form->getValues(); if (!$record instanceof FolderGroup) { // TODO: Enforce folder count limit. $record = new FolderGroup(); $record->user = $this->user; $record->sort_order = 100; } $record->fromArray($data); $record->save(); $this->_reSort(); $this->alert('<b>Group updated!</b>', 'green'); return $this->redirectFromHere(array('action' => 'index', 'id' => NULL)); } $this->view->form = $form; }