diff --git a/codepot/Makefile.am b/codepot/Makefile.am index 71e48fa6..8b1c01e1 100644 --- a/codepot/Makefile.am +++ b/codepot/Makefile.am @@ -9,12 +9,14 @@ install-data-hook: $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@" $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/svnrepo" $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/files" + $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/attachments" $(INSTALL) -d "$(DESTDIR)@LOGDIR@" $(INSTALL) -d "$(DESTDIR)@CACHEDIR@" uninstall-hook: - $(RMDIR) "$(DESTDIR)@DEPOTDIR@/svnrepo" + $(RMDIR) "$(DESTDIR)@DEPOTDIR@/attachments" $(RMDIR) "$(DESTDIR)@DEPOTDIR@/files" + $(RMDIR) "$(DESTDIR)@DEPOTDIR@/svnrepo" $(RMDIR) "$(DESTDIR)@DEPOTDIR@" $(RMDIR) "$(DESTDIR)@LOGDIR@" $(RMDIR) "$(DESTDIR)@CACHEDIR@" diff --git a/codepot/Makefile.in b/codepot/Makefile.in index afb43a64..20ec314b 100644 --- a/codepot/Makefile.in +++ b/codepot/Makefile.in @@ -694,12 +694,14 @@ install-data-hook: $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@" $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/svnrepo" $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/files" + $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/attachments" $(INSTALL) -d "$(DESTDIR)@LOGDIR@" $(INSTALL) -d "$(DESTDIR)@CACHEDIR@" uninstall-hook: $(RMDIR) "$(DESTDIR)@DEPOTDIR@/svnrepo" $(RMDIR) "$(DESTDIR)@DEPOTDIR@/files" + $(RMDIR) "$(DESTDIR)@DEPOTDIR@/attachments" $(RMDIR) "$(DESTDIR)@DEPOTDIR@" $(RMDIR) "$(DESTDIR)@LOGDIR@" $(RMDIR) "$(DESTDIR)@CACHEDIR@" diff --git a/codepot/etc/codepot.ini.in b/codepot/etc/codepot.ini.in index ce8a5d8c..5d7b3f95 100644 --- a/codepot/etc/codepot.ini.in +++ b/codepot/etc/codepot.ini.in @@ -25,8 +25,7 @@ database_prefix = "" ; ${userid} and ${password} to represent the actual user ID ; and the password respectively. ;------------------------------------------------------------------------------ -ldap_server_host = "127.0.0.1" -ldap_server_port = "389" +ldap_server_uri = "ldap://127.0.0.1:389" ldap_server_protocol_version = "3" ldap_userid_format = "${userid}" ldap_password_format = "${password}" @@ -125,6 +124,11 @@ svnrepo_dir = "@DEPOTDIR@/svnrepo" ;------------------------------------------------------------------------------ file_dir = "@DEPOTDIR@/files" +;------------------------------------------------------------------------------ +; directory to store wiki attachments +;------------------------------------------------------------------------------ +attachment_dir = "@DEPOTDIR@/attachments" + ;------------------------------------------------------------------------------ ; log threshold ;------------------------------------------------------------------------------ diff --git a/codepot/etc/codepot.sql b/codepot/etc/codepot.sql index c8c1e431..29c6cf17 100644 --- a/codepot/etc/codepot.sql +++ b/codepot/etc/codepot.sql @@ -50,6 +50,24 @@ CREATE TABLE wiki ( ON DELETE RESTRICT ON UPDATE CASCADE ) charset=utf8 engine=InnoDB; +CREATE TABLE wiki_attachment ( + projectid VARCHAR(32) NOT NULL, + wikiname VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + encname VARCHAR(255) NOT NULL, + + createdon DATETIME, + createdby VARCHAR(32), + + UNIQUE KEY wiki_attachment_id (projectid, wikiname, name), + + CONSTRAINT wiki_attachment_projectid FOREIGN KEY (projectid) REFERENCES project(id) + ON DELETE RESTRICT ON UPDATE CASCADE, + + CONSTRAINT wiki_attachment_wikiid FOREIGN KEY (projectid,wikiname) REFERENCES wiki(projectid,name) + ON DELETE RESTRICT ON UPDATE CASCADE +) charset=utf8 engine=InnoDB; + CREATE TABLE issue ( projectid VARCHAR(32) NOT NULL, id BIGINT NOT NULL, diff --git a/codepot/src/codepot/config/mimes.php b/codepot/src/codepot/config/mimes.php index 3dd816de..5972b211 100644 --- a/codepot/src/codepot/config/mimes.php +++ b/codepot/src/codepot/config/mimes.php @@ -9,98 +9,97 @@ */ $mimes = array( 'hqx' => 'application/mac-binhex40', - 'cpt' => 'application/mac-compactpro', - 'csv' => array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel'), - 'bin' => 'application/macbinary', - 'dms' => 'application/octet-stream', - 'lha' => 'application/octet-stream', - 'lzh' => 'application/octet-stream', - 'exe' => 'application/octet-stream', - 'class' => 'application/octet-stream', - 'psd' => 'application/x-photoshop', - 'so' => 'application/octet-stream', - 'sea' => 'application/octet-stream', - 'dll' => 'application/octet-stream', - 'oda' => 'application/oda', - 'pdf' => array('application/pdf', 'application/x-download'), - 'ai' => 'application/postscript', - 'eps' => 'application/postscript', - 'ps' => 'application/postscript', - 'smi' => 'application/smil', - 'smil' => 'application/smil', - 'mif' => 'application/vnd.mif', - 'xls' => array('application/excel', 'application/vnd.ms-excel', 'application/msexcel'), - 'ppt' => array('application/powerpoint', 'application/vnd.ms-powerpoint'), - 'wbxml' => 'application/wbxml', - 'wmlc' => 'application/wmlc', - 'dcr' => 'application/x-director', - 'dir' => 'application/x-director', - 'dxr' => 'application/x-director', - 'dvi' => 'application/x-dvi', - 'gtar' => 'application/x-gtar', - 'gz' => 'application/x-gzip', - 'php' => 'application/x-httpd-php', - 'php4' => 'application/x-httpd-php', - 'php3' => 'application/x-httpd-php', - 'phtml' => 'application/x-httpd-php', - 'phps' => 'application/x-httpd-php-source', - 'js' => 'application/x-javascript', - 'swf' => 'application/x-shockwave-flash', - 'sit' => 'application/x-stuffit', - 'tar' => 'application/x-tar', - 'tgz' => 'application/x-tar', - 'xhtml' => 'application/xhtml+xml', - 'xht' => 'application/xhtml+xml', - 'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed'), - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mpga' => 'audio/mpeg', - 'mp2' => 'audio/mpeg', - 'mp3' => array('audio/mpeg', 'audio/mpg'), - 'aif' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'ram' => 'audio/x-pn-realaudio', - 'rm' => 'audio/x-pn-realaudio', - 'rpm' => array('audio/x-pn-realaudio-plugin', 'application/x-rpm'), - 'ra' => 'audio/x-realaudio', - 'rv' => 'video/vnd.rn-realvideo', - 'wav' => 'audio/x-wav', - 'bmp' => 'image/bmp', - 'gif' => 'image/gif', - 'jpeg' => array('image/jpeg', 'image/pjpeg'), - 'jpg' => array('image/jpeg', 'image/pjpeg'), - 'jpe' => array('image/jpeg', 'image/pjpeg'), - 'png' => array('image/png', 'image/x-png'), - 'tiff' => 'image/tiff', - 'tif' => 'image/tiff', - 'css' => 'text/css', - 'html' => 'text/html', - 'htm' => 'text/html', - 'shtml' => 'text/html', - 'txt' => 'text/plain', - 'text' => 'text/plain', - 'log' => array('text/plain', 'text/x-log'), - 'rtx' => 'text/richtext', - 'rtf' => 'text/rtf', - 'xml' => 'text/xml', - 'xsl' => 'text/xml', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpe' => 'video/mpeg', - 'qt' => 'video/quicktime', - 'mov' => 'video/quicktime', - 'avi' => 'video/x-msvideo', - 'movie' => 'video/x-sgi-movie', - 'doc' => 'application/msword', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'word' => array('application/msword', 'application/octet-stream'), - 'xl' => 'application/excel', - 'eml' => 'message/rfc822', - 'odt' => 'application/vnd.oasis.opendocument.text' - ); - + 'cpt' => 'application/mac-compactpro', + 'csv' => array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel'), + 'bin' => 'application/macbinary', + 'dms' => 'application/octet-stream', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'exe' => 'application/octet-stream', + 'class' => 'application/octet-stream', + 'psd' => 'application/x-photoshop', + 'so' => 'application/octet-stream', + 'sea' => 'application/octet-stream', + 'dll' => 'application/octet-stream', + 'oda' => 'application/oda', + 'pdf' => array('application/pdf', 'application/x-download'), + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'mif' => 'application/vnd.mif', + 'xls' => array('application/excel', 'application/vnd.ms-excel', 'application/msexcel'), + 'ppt' => array('application/powerpoint', 'application/vnd.ms-powerpoint'), + 'wbxml' => 'application/wbxml', + 'wmlc' => 'application/wmlc', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'gtar' => 'application/x-gtar', + 'gz' => 'application/x-gzip', + 'php' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php3' => 'application/x-httpd-php', + 'phtml' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'js' => 'application/x-javascript', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'tar' => 'application/x-tar', + 'tgz' => 'application/x-tar', + 'xhtml' => 'application/xhtml+xml', + 'xht' => 'application/xhtml+xml', + 'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed'), + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mpga' => 'audio/mpeg', + 'mp2' => 'audio/mpeg', + 'mp3' => array('audio/mpeg', 'audio/mpg'), + 'aif' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => array('audio/x-pn-realaudio-plugin', 'application/x-rpm'), + 'ra' => 'audio/x-realaudio', + 'rv' => 'video/vnd.rn-realvideo', + 'wav' => 'audio/x-wav', + 'bmp' => 'image/bmp', + 'gif' => 'image/gif', + 'jpeg' => array('image/jpeg', 'image/pjpeg'), + 'jpg' => array('image/jpeg', 'image/pjpeg'), + 'jpe' => array('image/jpeg', 'image/pjpeg'), + 'png' => array('image/png', 'image/x-png'), + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'css' => 'text/css', + 'html' => 'text/html', + 'htm' => 'text/html', + 'shtml' => 'text/html', + 'txt' => 'text/plain', + 'text' => 'text/plain', + 'log' => array('text/plain', 'text/x-log'), + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'xml' => 'text/xml', + 'xsl' => 'text/xml', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'qt' => 'video/quicktime', + 'mov' => 'video/quicktime', + 'avi' => 'video/x-msvideo', + 'movie' => 'video/x-sgi-movie', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'word' => array('application/msword', 'application/octet-stream'), + 'xl' => 'application/excel', + 'eml' => 'message/rfc822', + 'odt' => 'application/vnd.oasis.opendocument.text' +); /* End of file mimes.php */ /* Location: ./system/application/config/mimes.php */ diff --git a/codepot/src/codepot/controllers/file.php b/codepot/src/codepot/controllers/file.php index c2c0cf51..a1969f50 100644 --- a/codepot/src/codepot/controllers/file.php +++ b/codepot/src/codepot/controllers/file.php @@ -302,9 +302,8 @@ class File extends Controller $md5sum = md5_file ($upload['full_path']); if ($md5sum === FALSE) { - unlink (CODEPOT_FILE_DIR . "/{$file->encname}"); - - $data['message'] = "CANNOT GET MD5SUM OF FILE - {$file->name}"; + @unlink ($upload['full_path']); + $data['message'] = "CANNOT GET MD5SUM - {$file->name}"; $data['file'] = $file; $this->load->view ($this->VIEW_EDIT, $data); } diff --git a/codepot/src/codepot/controllers/site.php b/codepot/src/codepot/controllers/site.php index 1eb5e240..094ef724 100644 --- a/codepot/src/codepot/controllers/site.php +++ b/codepot/src/codepot/controllers/site.php @@ -454,6 +454,25 @@ class Site extends Controller } } + function image ($xlink = '') + { + $login = $this->login->getUser (); + if (CODEPOT_SIGNIN_COMPULSORY && $login['id'] == '') + redirect ('main/signin'); + + $data['login'] = $login; + + $linkname = $this->converter->HexToAscii ($xlink); + + $part = explode (':', $linkname); + if (count($part) == 3) + { + $hexwikiname = $this->converter->AsciiTohex($part[1]); + $hexattname = $this->converter->AsciiTohex($part[2]); + redirect ("wiki/attachment/{$part[0]}/{$hexwikiname}/{$hexattname}"); + } + } + } ?> diff --git a/codepot/src/codepot/controllers/wiki.php b/codepot/src/codepot/controllers/wiki.php index 0c160967..83f2fde6 100644 --- a/codepot/src/codepot/controllers/wiki.php +++ b/codepot/src/codepot/controllers/wiki.php @@ -20,7 +20,7 @@ class Wiki extends Controller $this->load->library ('Language', 'lang'); $this->lang->load ('common', CODEPOT_LANG); - + $this->lang->load ('wiki', CODEPOT_LANG); } function home ($projectid = '') @@ -98,7 +98,8 @@ class Wiki extends Controller } else { - $link = $this->wikihelper->parseLink ($name, $projectid, $this->converter); + $link = $this->wikihelper->parseLink ( + $name, $projectid, $this->converter); if ($link === FALSE) { $data['project'] = $project; @@ -132,9 +133,8 @@ class Wiki extends Controller else { $data['project'] = $project; - $data['message'] = - $this->lang->line('MSG_NO_SUCH_WIKI_PAGE') . - " - {$name}"; + $data['message'] = sprintf ( + $this->lang->line('WIKI_MSG_NO_SUCH_PAGE'), $name); $this->load->view ($this->VIEW_ERROR, $data); } } @@ -157,10 +157,126 @@ class Wiki extends Controller $this->_show_wiki ($projectid, $name, FALSE); } + function attachment0 ($projectid = '', $target = '') + { + //$target => projectid:wikiname:attachment + + $login = $this->login->getUser (); + if (CODEPOT_SIGNIN_COMPULSORY && $login['id'] == '') + redirect ('main/signin'); + + if ($target == '') + { + $data['login'] = $login; + $data['message'] = 'INVALID PARAMETERS'; + $this->load->view ($this->VIEW_ERROR, $data); + return; + } + + $target = $this->converter->HexToAscii ($target); + $part = explode (':', $target); + if (count($part) == 3) + { + if ($part[0] == '') $part[0] = $projectid; + $this->_handle_attachment ($login, $part[0], $part[1], $part[2]); + } + } + + function attachment ($projectid = '', $wikiname = '', $name = '') + { + $login = $this->login->getUser (); + if (CODEPOT_SIGNIN_COMPULSORY && $login['id'] == '') + redirect ('main/signin'); + + if ($wikiname == '' || $name == '') + { + $data['login'] = $login; + $data['message'] = 'INVALID PARAMETERS'; + $this->load->view ($this->VIEW_ERROR, $data); + return; + } + + $wikiname = $this->converter->HexToAscii ($wikiname); + $name = $this->converter->HexToAscii ($name); + + $part = explode (':', $name); + if (count($part) == 3) + { + if ($part[0] != '') $projectid = $part[0]; + if ($part[1] != '') $wikiname = $part[1]; + if ($part[2] != '') $name = $part[2]; + } + + $this->_handle_attachment ($login, $projectid, $wikiname, $name); + } + + function _handle_attachment ($login, $projectid, $wikiname, $name) + { + $this->load->model ('ProjectModel', 'projects'); + $this->load->model ('WikiModel', 'wikis'); + + $data['login'] = $login; + + $project = $this->projects->get ($projectid); + if ($project === FALSE) + { + $data['message'] = 'DATABASE ERROR'; + $this->load->view ($this->VIEW_ERROR, $data); + } + else if ($project === NULL) + { + $data['message'] = + $this->lang->line('MSG_NO_SUCH_PROJECT') . + " - {$projectid}"; + $this->load->view ($this->VIEW_ERROR, $data); + } + else + { + $att = $this->wikis->getAttachment ($login['id'], $project, $wikiname, $name); + if ($att == FALSE) + { + $data['project'] = $project; + $data['message'] = 'DATABASE ERROR'; + $this->load->view ($this->VIEW_ERROR, $data); + return; + } + else if ($att === NULL) + { + $data['project'] = $project; + $data['message'] = sprintf ( + $this->lang->line('MSG_WIKI_NO_SUCH_ATTACHMENT'), $name); + $this->load->view ($this->VIEW_ERROR, $data); + } + + $path = CODEPOT_ATTACHMENT_DIR . "/{$att->encname}"; + + $mtime = @filemtime ($path); + if ($mtime === FALSE) $mtime = time(); + header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $mtime) . ' GMT'); + header ('Content-Type: ' . mime_content_type($path)); + header("Content-Disposition: filename={$name}"); + $len = @filesize($path); + if ($len !== FALSE) header("Content-Length: {$len}"); + //header("Content-Transfer-Encoding: binary"); + flush (); + + $x = @readfile($path); + if ($x === FALSE) + { + $data['project'] = $project; + $data['message'] = sprintf ( + $this->lang->line('MSG_WIKI_FAILED_TO_READ_ATTACHMENT'), $name); + $this->load->view ($this->VIEW_ERROR, $data); + } + } + } + function _edit_wiki ($projectid, $name, $mode) { $this->load->helper ('form'); $this->load->library ('form_validation'); + $this->load->library ('upload'); + $this->load->model ('ProjectModel', 'projects'); $this->load->model ('WikiModel', 'wikis'); @@ -208,9 +324,39 @@ class Wiki extends Controller if ($this->input->post('wiki')) { $wiki->projectid = $this->input->post('wiki_projectid'); + $wiki->name = $this->input->post('wiki_name'); $wiki->text = $this->input->post('wiki_text'); + $wiki->delete_attachments = array(); + $delatts = $this->input->post('wiki_delete_attachment'); + + if (!empty($delatts)) + { + foreach ($delatts as $att) + { + $atpos = strpos ($att, '@'); + if ($atpos === FALSE) continue; + + $attinfo['name'] = $this->converter->HexToAscii(substr ($att, 0, $atpos)); + $attinfo['encname'] = $this->converter->HexToAscii(substr ($att, $atpos + 1)); + + array_push ( + $wiki->delete_attachments, + (object)$attinfo + ); + } + } + + $wiki->attachments = $this->wikis->getAttachments ( + $login['id'], $project, $wiki->name); + if ($wiki->attachments === FALSE) + { + $data['message'] = 'DATABASE ERROR'; + $this->load->view ($this->VIEW_ERROR, $data); + return; + } + if ($this->form_validation->run()) { if ($this->wikihelper->_is_reserved ($wiki->name, FALSE)) @@ -221,17 +367,38 @@ class Wiki extends Controller } else { + list($ret,$extra) = + $this->_upload_attachments ('wiki_new_attachment'); + if ($ret === FALSE) + { + $data['wiki'] = $wiki; + $data['message'] = $extra; + $this->load->view ($this->VIEW_EDIT, $data); + return; + } + + $wiki->new_attachments = $extra; + $result = ($mode == 'update')? $this->wikis->update ($login['id'], $wiki): $this->wikis->create ($login['id'], $wiki); + if ($result === FALSE) { + foreach ($extra as $att) + @unlink ($att['fullencpath']); + $data['message'] = 'DATABASE ERROR'; $data['wiki'] = $wiki; $this->load->view ($this->VIEW_EDIT, $data); } else { + // delete attachments after database operation + // as 'delete' is not easy to restore. + foreach ($wiki->delete_attachments as $att) + @unlink (CODEPOT_ATTACHMENT_DIR . "/{$att->encname}"); + redirect ("wiki/show/{$project->id}/" . $this->converter->AsciiToHex($wiki->name)); } @@ -257,7 +424,7 @@ class Wiki extends Controller else if ($wiki == NULL) { $data['message'] = - $this->lang->line('MSG_NO_SUCH_WIKI_PAGE') . + $this->lang->line('WIKI_MSG_NO_SUCH_PAGE') . " - {$name}"; $this->load->view ($this->VIEW_ERROR, $data); } @@ -383,9 +550,8 @@ class Wiki extends Controller } else if ($wiki === NULL) { - $data['message'] = - $this->lang->line('MSG_NO_SUCH_WIKI_PAGE') . - " - {$name}"; + $data['message'] = sprintf ( + $this->lang->line('WIKI_MSG_NO_SUCH_PAGE'), $name); $this->load->view ($this->VIEW_ERROR, $data); } else @@ -398,4 +564,61 @@ class Wiki extends Controller } } + + function _upload_attachments ($id) + { + $attno = 0; + $count = count($_FILES); + + $attachments = array (); + + for ($i = 0; $i < $count; $i++) + { + $field_name = "{$id}_{$i}"; + + if (array_key_exists($field_name, $_FILES) && + $_FILES[$field_name]['name'] != '') + { + $fname = $_FILES[$field_name]['name']; + if (strpos ($fname, ':') !== FALSE) + { + while ($attno > 0) + @unlink ($attachments[$attno--]['fullencpath']); + return array(FALSE,$this->lang->line('WIKI_MSG_ATTACHMENT_NAME_NO_COLON')); + } + + $ext = substr ($fname, strrpos ($fname, '.') + 1); + + // delete all \" instances ... + $_FILES[$field_name]['type'] = + str_replace('\"', '', $_FILES[$field_name]['type']); + // delete all \\ instances ... + $_FILES[$field_name]['type'] = + str_replace('\\', '', $_FILES[$field_name]['type']); + + $config['allowed_types'] = $ext; + $config['upload_path'] = CODEPOT_ATTACHMENT_DIR; + $config['max_size'] = CODEPOT_MAX_UPLOAD_SIZE; + $config['encrypt_name'] = TRUE; + + $this->upload->initialize ($config); + + if (!$this->upload->do_upload ($field_name)) + { + while ($attno > 0) + @unlink ($attachments[$attno--]['fullencpath']); + return array(FALSE,$this->upload->display_errors('','')); + } + + $upload = $this->upload->data (); + + $attachments[$attno++] = array ( + 'name' => $fname, + 'encname' => $upload['file_name'], + 'fullencpath' => $upload['full_path']); + } + } + + return array(TRUE,$attachments); + } } diff --git a/codepot/src/codepot/language/english/Makefile.am b/codepot/src/codepot/language/english/Makefile.am index 8a9cd58c..b5345e46 100644 --- a/codepot/src/codepot/language/english/Makefile.am +++ b/codepot/src/codepot/language/english/Makefile.am @@ -5,7 +5,8 @@ www_DATA = \ issue_lang.php \ index.html \ project_lang.php \ - site_lang.php + site_lang.php \ + wiki_lang.php EXTRA_DIST = $(www_DATA) diff --git a/codepot/src/codepot/language/english/Makefile.in b/codepot/src/codepot/language/english/Makefile.in index f956bb40..5f1be71e 100644 --- a/codepot/src/codepot/language/english/Makefile.in +++ b/codepot/src/codepot/language/english/Makefile.in @@ -171,7 +171,8 @@ www_DATA = \ issue_lang.php \ index.html \ project_lang.php \ - site_lang.php + site_lang.php \ + wiki_lang.php EXTRA_DIST = $(www_DATA) all: all-am diff --git a/codepot/src/codepot/language/english/common_lang.php b/codepot/src/codepot/language/english/common_lang.php index 02d169fb..7fa935a4 100644 --- a/codepot/src/codepot/language/english/common_lang.php +++ b/codepot/src/codepot/language/english/common_lang.php @@ -1,6 +1,8 @@ diff --git a/codepot/src/codepot/language/english/issue_lang.php b/codepot/src/codepot/language/english/issue_lang.php index aaa99418..0448b85c 100644 --- a/codepot/src/codepot/language/english/issue_lang.php +++ b/codepot/src/codepot/language/english/issue_lang.php @@ -20,5 +20,6 @@ $lang['ISSUE_PRIORITY_OTHER'] = 'Other'; $lang['ISSUE_MSG_CHANGED_X_TO_Z'] = "Changed %s to %s"; $lang['ISSUE_MSG_CHANGED_X_FROM_Y_TO_Z'] = "Changed %s from %s to %s"; $lang['ISSUE_MSG_CONFIRM_UNDO'] = 'Are you sure to undo the last change?'; +$lang['ISSUE_MSG_CREATED'] = 'Created'; $lang['ISSUE_MSG_TOTAL_NUM_ISSUES'] = 'Total %d issues'; ?> diff --git a/codepot/src/codepot/language/english/wiki_lang.php b/codepot/src/codepot/language/english/wiki_lang.php new file mode 100644 index 00000000..041d5cf2 --- /dev/null +++ b/codepot/src/codepot/language/english/wiki_lang.php @@ -0,0 +1,11 @@ + diff --git a/codepot/src/codepot/language/indonesian/common_lang.php b/codepot/src/codepot/language/indonesian/common_lang.php index fca53f29..342272fb 100644 --- a/codepot/src/codepot/language/indonesian/common_lang.php +++ b/codepot/src/codepot/language/indonesian/common_lang.php @@ -91,7 +91,5 @@ $lang['MSG_NO_ISSUES_AVAIL'] = 'Tidak ada issue'; $lang['MSG_NO_SUCH_FILE'] = 'No such file'; $lang['MSG_NO_SUCH_ISSUE'] = 'No such issue'; $lang['MSG_NO_SUCH_PROJECT'] = 'No such project'; -$lang['MSG_NO_SUCH_WIKI_PAGE'] = 'No such wiki page'; -$lang['MSG_NO_WIKIS_AVAIL'] = 'Tidak ada halaman wiki tersedia'; $lang['MSG_SURE_TO_DELETE_THIS'] = "Saya yakin untuk menghapus"; ?> diff --git a/codepot/src/codepot/language/korean/Makefile.am b/codepot/src/codepot/language/korean/Makefile.am index 98a58506..d54c4b1e 100644 --- a/codepot/src/codepot/language/korean/Makefile.am +++ b/codepot/src/codepot/language/korean/Makefile.am @@ -5,7 +5,8 @@ www_DATA = \ issue_lang.php \ index.html \ project_lang.php \ - site_lang.php + site_lang.php \ + wiki_lang.php EXTRA_DIST = $(www_DATA) diff --git a/codepot/src/codepot/language/korean/Makefile.in b/codepot/src/codepot/language/korean/Makefile.in index 241d1655..cc373e79 100644 --- a/codepot/src/codepot/language/korean/Makefile.in +++ b/codepot/src/codepot/language/korean/Makefile.in @@ -171,7 +171,8 @@ www_DATA = \ issue_lang.php \ index.html \ project_lang.php \ - site_lang.php + site_lang.php \ + wiki_lang.php EXTRA_DIST = $(www_DATA) all: all-am diff --git a/codepot/src/codepot/language/korean/common_lang.php b/codepot/src/codepot/language/korean/common_lang.php index 1b74d30f..484551ea 100644 --- a/codepot/src/codepot/language/korean/common_lang.php +++ b/codepot/src/codepot/language/korean/common_lang.php @@ -1,6 +1,8 @@ diff --git a/codepot/src/codepot/language/korean/issue_lang.php b/codepot/src/codepot/language/korean/issue_lang.php index af0b6d98..b6edf72f 100644 --- a/codepot/src/codepot/language/korean/issue_lang.php +++ b/codepot/src/codepot/language/korean/issue_lang.php @@ -20,5 +20,6 @@ $lang['ISSUE_PRIORITY_OTHER'] = '기타'; $lang['ISSUE_MSG_CHANGED_X_TO_Z'] = "%s을/를 %s(으)로 변경"; $lang['ISSUE_MSG_CHANGED_X_FROM_Y_TO_Z'] = "%s을/를 %s에서 %s(으)로 변경"; $lang['ISSUE_MSG_CONFIRM_UNDO'] = '마지막 변경내용을 취소할까요?'; +$lang['ISSUE_MSG_CREATED'] = '생성됨'; $lang['ISSUE_MSG_TOTAL_NUM_ISSUES'] = '전체 이슈 %d개'; ?> diff --git a/codepot/src/codepot/language/korean/wiki_lang.php b/codepot/src/codepot/language/korean/wiki_lang.php new file mode 100644 index 00000000..f9f290fe --- /dev/null +++ b/codepot/src/codepot/language/korean/wiki_lang.php @@ -0,0 +1,11 @@ + diff --git a/codepot/src/codepot/models/ldaploginmodel.php b/codepot/src/codepot/models/ldaploginmodel.php index 994f0d69..2bf28c3f 100644 --- a/codepot/src/codepot/models/ldaploginmodel.php +++ b/codepot/src/codepot/models/ldaploginmodel.php @@ -10,8 +10,9 @@ class LdapLoginModel extends LoginModel function authenticate ($userid, $password) { - $ldap = @ldap_connect ( - CODEPOT_LDAP_SERVER_HOST, CODEPOT_LDAP_SERVER_PORT); + //$ldap = @ldap_connect ( + // CODEPOT_LDAP_SERVER_HOST, CODEPOT_LDAP_SERVER_PORT); + $ldap = @ldap_connect (CODEPOT_LDAP_SERVER_URI); if ($ldap === FALSE) { $this->setErrorMessage ("Can't connect to LDAP server"); diff --git a/codepot/src/codepot/models/wikimodel.php b/codepot/src/codepot/models/wikimodel.php index 50787959..3a726d01 100644 --- a/codepot/src/codepot/models/wikimodel.php +++ b/codepot/src/codepot/models/wikimodel.php @@ -11,15 +11,41 @@ class WikiModel extends Model function get ($userid, $project, $name) { $this->db->trans_start (); + $this->db->where ('projectid', $project->id); $this->db->where ('name', $name); $query = $this->db->get ('wiki'); - $this->db->trans_complete (); - - if ($this->db->trans_status() === FALSE) return FALSE; + if ($this->db->trans_status() === FALSE) + { + $this->db->trans_complete (); + return FALSE; + } $result = $query->result (); - return empty($result)? NULL: $result[0]; + if (empty($result)) + { + $this->db->trans_complete (); + return NULL; + } + + $this->db->select ('name,encname,createdon,createdby'); + $this->db->where ('projectid', $project->id); + $this->db->where ('wikiname', $name); + $this->db->order_by ('name', 'ASC'); + $query2 = $this->db->get ('wiki_attachment'); + + if ($this->db->trans_status() === FALSE) + { + $this->db->trans_complete (); + return FALSE; + } + + $this->db->trans_complete (); + + $wikis = $result[0]; + $wikis->attachments = $query2->result(); + + return $wikis; } function getAll ($userid, $project) @@ -33,20 +59,91 @@ class WikiModel extends Model return $query->result (); } + function getAttachment ($userid, $project, $wikiname, $name) + { + $this->db->trans_start (); + + $this->db->select ('name,encname,createdon,createdby'); + $this->db->where ('projectid', $project->id); + $this->db->where ('wikiname', $wikiname); + $this->db->where ('name', $name); + + $query = $this->db->get ('wiki_attachment'); + $this->db->trans_complete (); + + if ($this->db->trans_status() === FALSE) return FALSE; + $result = $query->result (); + if (empty($result)) return NULL; + + return $result[0]; + } + + function getAttachments ($userid, $project, $wikiname) + { + $this->db->trans_start (); + + $this->db->select ('name,encname,createdon,createdby'); + $this->db->where ('projectid', $project->id); + $this->db->where ('wikiname', $wikiname); + + $query = $this->db->get ('wiki_attachment'); + $this->db->trans_complete (); + + if ($this->db->trans_status() === FALSE) return FALSE; + $result = $query->result (); + + return $result; + } + function create ($userid, $wiki) { // TODO: check if userid can do this.. - $this->db->trans_start (); + $this->db->trans_begin (); + + $now = date('Y-m-d H:i:s'); + $this->db->set ('projectid', $wiki->projectid); $this->db->set ('name', $wiki->name); $this->db->set ('text', $wiki->text); - $this->db->set ('createdon', date('Y-m-d H:i:s')); - $this->db->set ('updatedon', date('Y-m-d H:i:s')); + $this->db->set ('createdon', $now); + $this->db->set ('updatedon', $now); $this->db->set ('createdby', $userid); $this->db->set ('updatedby', $userid); $this->db->insert ('wiki'); - $this->db->set ('createdon', date('Y-m-d H:i:s')); + foreach ($wiki->delete_attachments as $att) + { + $this->db->where ('projectid', $wiki->projectid); + $this->db->where ('wikiname', $wiki->name); + $this->db->where ('name', $att->name); + $this->db->where ('encname', $att->encname); + $this->db->delete ('wiki_attachment'); + + if ($this->db->trans_status() === FALSE) + { + $this->db->trans_rollback (); + return FALSE; + } + + if ($this->db->affected_rows() <= 0) + { + $this->db->trans_rollback (); + return FALSE; + } + } + + foreach ($wiki->new_attachments as $att) + { + $this->db->set ('projectid', $wiki->projectid); + $this->db->set ('wikiname', $wiki->name); + $this->db->set ('name', $att['name']); + $this->db->set ('encname', $att['encname']); + $this->db->set ('createdon', $now); + $this->db->set ('createdby', $userid); + $this->db->insert ('wiki_attachment'); + } + + $this->db->set ('createdon', $now); $this->db->set ('type', 'wiki'); $this->db->set ('action', 'create'); $this->db->set ('projectid', $wiki->projectid); @@ -54,22 +151,63 @@ class WikiModel extends Model $this->db->set ('message', $wiki->name); $this->db->insert ('log'); - $this->db->trans_complete (); - return $this->db->trans_status(); + if ($this->db->trans_status() === FALSE) + { + $this->db->trans_rollback (); + return FALSE; + } + + $this->db->trans_commit (); + return TRUE; } function update ($userid, $wiki) { // TODO: check if userid can do this.. - $this->db->trans_start (); + $this->db->trans_begin (); + + $now = date('Y-m-d H:i:s'); + $this->db->where ('projectid', $wiki->projectid); $this->db->where ('name', $wiki->name); $this->db->set ('text', $wiki->text); - $this->db->set ('updatedon', date('Y-m-d H:i:s')); + $this->db->set ('updatedon', $now); $this->db->set ('updatedby', $userid); $this->db->update ('wiki'); - $this->db->set ('createdon', date('Y-m-d H:i:s')); + foreach ($wiki->delete_attachments as $att) + { + $this->db->where ('projectid', $wiki->projectid); + $this->db->where ('wikiname', $wiki->name); + $this->db->where ('name', $att->name); + $this->db->where ('encname', $att->encname); + $this->db->delete ('wiki_attachment'); + + if ($this->db->trans_status() === FALSE) + { + $this->db->trans_rollback (); + return FALSE; + } + + if ($this->db->affected_rows() <= 0) + { + $this->db->trans_rollback (); + return FALSE; + } + } + + foreach ($wiki->new_attachments as $att) + { + $this->db->set ('projectid', $wiki->projectid); + $this->db->set ('wikiname', $wiki->name); + $this->db->set ('name', $att['name']); + $this->db->set ('encname', $att['encname']); + $this->db->set ('createdon', $now); + $this->db->set ('createdby', $userid); + $this->db->insert ('wiki_attachment'); + } + + $this->db->set ('createdon', $now); $this->db->set ('type', 'wiki'); $this->db->set ('action', 'update'); $this->db->set ('projectid', $wiki->projectid); @@ -77,14 +215,25 @@ class WikiModel extends Model $this->db->set ('message', $wiki->name); $this->db->insert ('log'); - $this->db->trans_complete (); - return $this->db->trans_status(); + if ($this->db->trans_status() === FALSE) + { + $this->db->trans_rollback (); + return FALSE; + } + + $this->db->trans_commit (); + return TRUE; } function delete ($userid, $wiki) { // TODO: check if userid can do this.. $this->db->trans_start (); + + $this->db->where ('projectid', $wiki->projectid); + $this->db->where ('wikiname', $wiki->name); + $this->db->delete ('wiki_attachment'); + $this->db->where ('projectid', $wiki->projectid); $this->db->where ('name', $wiki->name); $this->db->delete ('wiki'); diff --git a/codepot/src/codepot/views/file_show.php b/codepot/src/codepot/views/file_show.php index a7ece412..161053ee 100644 --- a/codepot/src/codepot/views/file_show.php +++ b/codepot/src/codepot/views/file_show.php @@ -10,9 +10,10 @@ function render_wiki() { creole_render_wiki ( - "file_show_textpre", - "file_show_textarea", - "/wiki/show/id?>/" + "file_show_mainarea_wiki_text", + "file_show_mainarea_wiki", + "/wiki/show/id?>/", + "/wiki/attachment0/id?>/" ); } @@ -76,11 +77,11 @@ $this->load->view (
name)?>
-
-
diff --git a/codepot/src/codepot/views/issue_show.php b/codepot/src/codepot/views/issue_show.php index 588dbf00..4e3f64e1 100644 --- a/codepot/src/codepot/views/issue_show.php +++ b/codepot/src/codepot/views/issue_show.php @@ -109,6 +109,7 @@ $(function () { $("#issue_show_mainarea_change_form_open").button().click ( function () { $('#issue_show_mainarea_change_form').dialog('open'); + return false; } ); @@ -135,6 +136,7 @@ $(function () { $("#issue_show_mainarea_undo_change").button().click ( function () { $('#issue_show_mainarea_undo_change_confirm').dialog('open'); + return false; } ); @@ -234,17 +236,15 @@ $this->load->view ( $msgfmt_changed_from_to = $this->lang->line ('ISSUE_MSG_CHANGED_X_FROM_Y_TO_Z'); $msgfmt_changed_to = $this->lang->line ('ISSUE_MSG_CHANGED_X_TO_Z'); $count = count($issue->changes); - if ($count > 1) - { - print '
'; - print ''; - print $this->lang->line('Change log'); - print ''; - print ''; - print $this->lang->line('Undo'); - print ''; - print '
'; - } + + print '
'; + print ''; + print $this->lang->line('Change log'); + print ''; + print ''; + print $this->lang->line('Undo'); + print ''; + print '
'; print ''; while ($count > 1) @@ -252,7 +252,7 @@ $this->load->view ( $new = $issue->changes[--$count]; $old = $issue->changes[$count-1]; - print ""; + print ''; print ''; + + print ''; + + print ''; + + print ''; + print '
'; print ''; + print ''; + print date ('Y-m-d', strtotime($issue->updatedon)); + print ''; + print ''; + print htmlspecialchars($issue->createdby); + print ''; + print $this->lang->line('ISSUE_MSG_CREATED'); + print '
'; ?> @@ -437,12 +457,16 @@ $this->load->view ( @@ -209,11 +210,11 @@ $this->load->view ( name)?> -
-
diff --git a/codepot/src/codepot/views/site_home.php b/codepot/src/codepot/views/site_home.php index 9d6d142f..e84b3996 100644 --- a/codepot/src/codepot/views/site_home.php +++ b/codepot/src/codepot/views/site_home.php @@ -9,9 +9,10 @@ function render_wiki() { creole_render_wiki ( - "site_home_mainarea_textpre", - "site_home_mainarea_text", - "/site/wiki/" + "site_home_mainarea_wiki_text", + "site_home_mainarea_wiki", + "/site/wiki/", + "/site/image/" ); } @@ -204,8 +205,8 @@ foreach ($latest_projects as $project) -
-
-
-
'; ?> -id}/".$this->converter->AsciiToHex($wiki->name))?> +id}/".$this->converter->AsciiToHex($wiki->name))?>
@@ -74,6 +96,52 @@ $this->load->view ( ?>
+ + attachments)): ?> +
+
+ lang->line('WIKI_ATTACHMENTS').': ', 'wiki_edit_attachment_list')?> + +
+ + + +
+ + +
+
+ lang->line('WIKI_NEW_ATTACHMENTS').': ', 'wiki_edit_new_attachment_list')?> + + lang->line('WIKI_MORE_NEW_ATTACHMENTS')?> + + +
+ + + +
projectid))?> diff --git a/codepot/src/codepot/views/wiki_home.php b/codepot/src/codepot/views/wiki_home.php index 50b36737..8b85410c 100644 --- a/codepot/src/codepot/views/wiki_home.php +++ b/codepot/src/codepot/views/wiki_home.php @@ -45,7 +45,7 @@ $this->load->view ( lang->line('MSG_NO_WIKIS_AVAIL'); + print $this->lang->line('WIKI_MSG_NO_PAGES_AVAILABLE'); } else { diff --git a/codepot/src/codepot/views/wiki_show.php b/codepot/src/codepot/views/wiki_show.php index 631fb775..56bdfe61 100644 --- a/codepot/src/codepot/views/wiki_show.php +++ b/codepot/src/codepot/views/wiki_show.php @@ -8,14 +8,19 @@ <?=htmlspecialchars($wiki->name)?> +converter->AsciiToHex ($wiki->name); +?> + @@ -31,7 +36,6 @@ function render_wiki() converter->AsciiToHex ($wiki->name); $this->load->view ( 'projectbar', array ( @@ -62,16 +66,37 @@ $this->load->view (
  • lang->line('Last updated by')?> updatedby ?>
  • + +attachments)): ?> +
    +
    lang->line('WIKI_ATTACHMENTS') ?>
    + +
    + +
    name)?>
    -
    -
    diff --git a/codepot/src/config.php.in b/codepot/src/config.php.in index 1eb45da3..acc4bc32 100644 --- a/codepot/src/config.php.in +++ b/codepot/src/config.php.in @@ -47,8 +47,7 @@ function load_ini ($file) array ('auth_mysql_name', 'string', ''), array ('auth_mysql_prefix', 'string', ''), - array ('ldap_server_host', 'string', '127.0.0.1'), - array ('ldap_server_port', 'integer', 389), + array ('ldap_server_uri', 'string', 'ldap://127.0.0.1:389'), array ('ldap_server_protocol_version', 'integer', 3), array ('ldap_userid_format', 'string', '${userid}'), array ('ldap_password_format', 'string', '${password}'), @@ -58,6 +57,7 @@ function load_ini ($file) array ('svnrepo_dir', 'string', CODEPOT_DEPOT_DIR.'/svnrepo'), array ('file_dir', 'string', CODEPOT_DEPOT_DIR.'/files'), + array ('attachment_dir', 'string', CODEPOT_DEPOT_DIR.'/attachments'), array ('log_threshold', 'integer', 0), diff --git a/codepot/src/css/common.css b/codepot/src/css/common.css index 2127b723..73638b53 100644 --- a/codepot/src/css/common.css +++ b/codepot/src/css/common.css @@ -284,6 +284,11 @@ body { .content .mainarea p.wiki { /* use the default for normal cases */ + overflow: auto; +} + +.content .mainarea p.wiki img { + max-width: 100%; } .content .mainarea table p.wiki { diff --git a/codepot/src/css/file.css b/codepot/src/css/file.css index 911cca5c..dc611b5e 100644 --- a/codepot/src/css/file.css +++ b/codepot/src/css/file.css @@ -10,3 +10,4 @@ white-space: nowrap; } + diff --git a/codepot/src/css/issue.css b/codepot/src/css/issue.css index 2ab7e367..909c8072 100644 --- a/codepot/src/css/issue.css +++ b/codepot/src/css/issue.css @@ -156,6 +156,7 @@ padding-top: 0.2em; padding-bottom: 0.2em; border-bottom: 1px solid lightgray; + overflow: auto; } #issue_show_mainarea_changes_table td.details .list { diff --git a/codepot/src/css/site.css b/codepot/src/css/site.css index 443d34c1..6ba09291 100644 --- a/codepot/src/css/site.css +++ b/codepot/src/css/site.css @@ -44,9 +44,21 @@ white-space: pre-wrap; } +/*----------------------------------------------- + * site show view + *-----------------------------------------------*/ +#site_show_mainarea_text p.wiki { + overflow: auto; +} + +#site_show_mainarea_text img { + max-width: 100%; +} + /*----------------------------------------------- * site edit view *-----------------------------------------------*/ #site_edit_form .text { width: 100%; } + diff --git a/codepot/src/css/wiki.css b/codepot/src/css/wiki.css index a3dd3030..6fa45e51 100644 --- a/codepot/src/css/wiki.css +++ b/codepot/src/css/wiki.css @@ -5,3 +5,4 @@ #wiki_edit_mainarea_text { width: 100%; } + diff --git a/codepot/src/js/creole.js b/codepot/src/js/creole.js index 014f23ef..75c3bbff 100644 --- a/codepot/src/js/creole.js +++ b/codepot/src/js/creole.js @@ -342,7 +342,19 @@ var Url = { img: { regex: rx.img, build: function(node, r, options) { var img = document.createElement('img'); - img.src = r[1]; + + if (r[1].match(rx.uriPrefix)) + { + img.src = r[1]; + } + else + { + var tmp = r[1].replace(/~(.)/g, '$1'); + tmp = Url.encode (tmp); + img.src = options && options.imgFormat? + formatLink (tmp, options.imgFormat): tmp; + } + img.alt = r[2] === undefined ? (options && options.defaultImageText ? options.defaultImageText : '') : r[2].replace(/~(.)/g, '$1'); @@ -474,7 +486,7 @@ Parse.Simple.Creole.prototype = new Parse.Simple.Base(); Parse.Simple.Creole.prototype.constructor = Parse.Simple.Creole; -function creole_render_wiki (inputid, outputid, linkbase) +function creole_render_wiki (inputid, outputid, linkbase, imgbase) { function $(id) { return document.getElementById(id); } @@ -495,7 +507,8 @@ function creole_render_wiki (inputid, outputid, linkbase) WikiCreole: 'http://www.wikicreole.org/wiki/', Wikipedia: 'http://en.wikipedia.org/wiki/' },*/ - linkFormat: linkbase + linkFormat: linkbase, + imgFormat: imgbase } ); var xinput = decodeEntities(input.innerHTML);