diff --git a/codepot/Makefile.am b/codepot/Makefile.am
index db9ccd65..3d94c4e9 100644
--- a/codepot/Makefile.am
+++ b/codepot/Makefile.am
@@ -11,6 +11,7 @@ install-data-hook:
$(INSTALL) -d "$(DESTDIR)@DEPOTDIR@"
$(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/svnrepo"
$(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/files"
+ $(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/issuefiles"
$(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/attachments"
$(INSTALL) -d "$(DESTDIR)@DEPOTDIR@/usericons"
$(INSTALL) -d "$(DESTDIR)@LOGDIR@"
@@ -19,6 +20,7 @@ install-data-hook:
uninstall-hook:
$(RMDIR) "$(DESTDIR)@DEPOTDIR@/usericons"
$(RMDIR) "$(DESTDIR)@DEPOTDIR@/attachments"
+ $(RMDIR) "$(DESTDIR)@DEPOTDIR@/issuefiles"
$(RMDIR) "$(DESTDIR)@DEPOTDIR@/files"
$(RMDIR) "$(DESTDIR)@DEPOTDIR@/svnrepo"
$(RMDIR) "$(DESTDIR)@DEPOTDIR@"
diff --git a/codepot/README b/codepot/README
index cafd1bda..1f1cf428 100644
--- a/codepot/README
+++ b/codepot/README
@@ -22,6 +22,8 @@ UPGRADING FROM 0.2.0
mysql> ALTER TABLE file DROP COLUMN md5sum;
mysql> ALTER TABLE file DROP COLUMN encname;
mysql> ALTER TABLE project ADD COLUMN (codecharset VARCHAR(32));
+ mysql> DROP TABLE issue_attachment;
+ mysql> create the issue_file_list table according to the definition found in codepot.mysql
INSTALLATION ON CENTOS
diff --git a/codepot/codepot.spec.in b/codepot/codepot.spec.in
index 2234eec8..0a8c519d 100644
--- a/codepot/codepot.spec.in
+++ b/codepot/codepot.spec.in
@@ -85,6 +85,7 @@ rm -rf $RPM_BUILD_ROOT
%dir %attr(-,apache,apache) /var/lib/codepot/svnrepo
%dir %attr(-,apache,apache) /var/lib/codepot/files
+%dir %attr(-,apache,apache) /var/lib/codepot/issuefiles
%dir %attr(-,apache,apache) /var/lib/codepot/attachments
%dir %attr(-,apache,apache) /var/lib/codepot/usericons
%dir %attr(-,apache,apache) /var/log/codepot
diff --git a/codepot/etc/codepot.ini.in b/codepot/etc/codepot.ini.in
index 7c7e4aea..e8c7cb44 100644
--- a/codepot/etc/codepot.ini.in
+++ b/codepot/etc/codepot.ini.in
@@ -186,6 +186,11 @@ svnrepo_dir = "@DEPOTDIR@/svnrepo"
;------------------------------------------------------------------------------
file_dir = "@DEPOTDIR@/files"
+;------------------------------------------------------------------------------
+; directory to store issue attachments
+;------------------------------------------------------------------------------
+issue_file_dir = "@DEPOTDIR@/issuefiles"
+
;------------------------------------------------------------------------------
; directory to store wiki attachments
;------------------------------------------------------------------------------
diff --git a/codepot/etc/codepot.mysql b/codepot/etc/codepot.mysql
index 97333082..befeda3e 100644
--- a/codepot/etc/codepot.mysql
+++ b/codepot/etc/codepot.mysql
@@ -99,21 +99,24 @@ CREATE TABLE issue (
ON DELETE RESTRICT ON UPDATE CASCADE
) charset=utf8 engine=InnoDB;
-CREATE TABLE issue_attachment (
- projectid VARCHAR(32) NOT NULL,
- issueid BIGINT NOT NULL,
- name VARCHAR(255) NOT NULL,
- encname VARCHAR(255) NOT NULL,
+CREATE TABLE issue_file_list (
+ projectid VARCHAR(32) NOT NULL,
+ issueid BIGINT NOT NULL,
+ filename VARCHAR(255) NOT NULL,
+ encname VARCHAR(255) NOT NULL,
+ md5sum CHAR(32) NOT NULL,
+ description VARCHAR(255) NOT NULL,
- createdon DATETIME NOT NULL,
- createdby VARCHAR(32) NOT NULL,
+ createdon DATETIME NOT NULL,
+ createdby VARCHAR(32) NOT NULL,
- UNIQUE KEY issue_attachment_id (projectid, issueid, name),
+ UNIQUE KEY issue_file_list_id (projectid, issueid, filename),
+ UNIQUE KEY (encname),
- CONSTRAINT issue_attachment_projectid FOREIGN KEY (projectid) REFERENCES project(id)
+ CONSTRAINT issue_file_list_projectid FOREIGN KEY (projectid) REFERENCES project(id)
ON DELETE RESTRICT ON UPDATE CASCADE,
- CONSTRAINT issue_attachment_issueid FOREIGN KEY (projectid,issueid) REFERENCES issue(projectid,id)
+ CONSTRAINT issue_file_list_issueid FOREIGN KEY (projectid,issueid) REFERENCES issue(projectid,id)
ON DELETE RESTRICT ON UPDATE CASCADE
) charset=utf8 engine=InnoDB;
diff --git a/codepot/src/codepot/controllers/issue.php b/codepot/src/codepot/controllers/issue.php
index 79182cb6..a382bb56 100644
--- a/codepot/src/codepot/controllers/issue.php
+++ b/codepot/src/codepot/controllers/issue.php
@@ -517,4 +517,111 @@ class Issue extends Controller
}
}
+ function xhr_create ($projectid = '')
+ {
+ $this->load->model ('ProjectModel', 'projects');
+ $this->load->model ('IssueModel', 'issues');
+ $this->load->library ('upload');
+
+ $login = $this->login->getUser ();
+ $revision_saved = -1;
+
+ if ($login['id'] == '')
+ {
+ $status = 'error - anonymous user';
+ }
+ else
+ {
+ $project = $this->projects->get ($projectid);
+ if ($project === FALSE)
+ {
+ $status = "error - failed to get the project {$projectid}";
+ }
+ else if ($project === NULL)
+ {
+ $status = "error - no such project {$projectid}";
+ }
+ else if (!$login['sysadmin?'] &&
+ $this->projects->projectHasMember($projectid, $login['id']) === FALSE)
+ {
+ $status = "error - not a member {$login['id']}";
+ }
+ else
+ {
+ $issue = new stdClass();
+ $issue->projectid = $projectid;
+ $issue->summary = $this->input->post('issue_new_summary');
+ $issue->description = $this->input->post('issue_new_description');
+ $issue->type = $this->input->post('issue_new_type');
+ $issue->status = $this->issuehelper->STATUS_NEW;
+ $issue->priority = $this->issuehelper->PRIORITY_OTHER;
+ if ($this->projects->projectHasMember($project->id, $login['id']))
+ {
+ // let the current user be the issue owner if he/she is a
+ // project memeber.
+ $issue->owner = $login['id'];
+ }
+ else
+ {
+ // if not, assign the issue to the first member.
+ $issue->owner = (count($project->members) > 0)? $project->members[0]: '';
+ }
+
+ $post_new_file_count = $this->input->post('issue_new_file_count');
+
+ if ($issue->type === FALSE || ($issue->type = trim($issue->type)) == '')
+ {
+ $status = 'error - no type';
+ }
+ else if ($issue->summary === FALSE || ($issue->summary = trim($issue->summary)) == '')
+ {
+ $status = 'error - no name';
+ }
+ else if ($issue->description === FALSE || ($issue->description = $issue->description) == '')
+ {
+ $status = 'error - no description';
+ }
+ else
+ {
+ if ($post_new_file_count === FALSE || $post_new_file_count <= 0) $post_new_file_count = 0;
+
+ $status = '';
+ $attached_files = array ();
+ for ($i = 0; $i < $post_new_file_count; $i++)
+ {
+ $fid = "issue_new_file_{$i}";
+ if (array_key_exists($fid, $_FILES) && $_FILES[$fid]['name'] != '')
+ {
+ $d = $this->input->post("issue_new_file_desc_{$i}");
+ if ($d === FALSE || ($d = trim($d)) == '') $d = ''; // description optional
+
+ if (strpos($_FILES[$fid]['name'], ':') !== FALSE ||
+ strpos($_FILES[$fid]['name'], '/') !== FALSE)
+ {
+ // prevents these letters for wiki creole
+ $status = "error - colon or slash not allowed - {$_FILES[$fid]['name']}";
+ break;
+ }
+
+ array_push ($attached_files, array ('fid' => $fid, 'name' => $_FILES[$fid]['name'], 'desc' => $d));
+ }
+ }
+
+ if ($status == '')
+ {
+ if ($this->issues->create_with_files ($login['id'], $issue, $attached_files, $this->upload) === FALSE)
+ {
+ $status = 'error - ' . $this->issues->getErrorMessage();
+ }
+ else
+ {
+ $status = 'ok';
+ }
+ }
+ }
+ }
+ }
+
+ print $status;
+ }
}
diff --git a/codepot/src/codepot/models/issuemodel.php b/codepot/src/codepot/models/issuemodel.php
index a6955226..c6a44951 100644
--- a/codepot/src/codepot/models/issuemodel.php
+++ b/codepot/src/codepot/models/issuemodel.php
@@ -2,6 +2,18 @@
class IssueModel extends Model
{
+ protected $errmsg = '';
+
+ function capture_error ($errno, $errmsg)
+ {
+ $this->errmsg = $errmsg;
+ }
+
+ function getErrorMessage ()
+ {
+ return $this->errmsg;
+ }
+
function IssueModel ()
{
parent::Model ();
@@ -184,7 +196,7 @@ class IssueModel extends Model
$this->db->set ('projectid', $issue->projectid);
$this->db->set ('userid', $userid);
$this->db->set ('message', $newid);
- $this->db->insert ('log');
+ $this->db->insert ('log');
$this->db->trans_complete ();
if ($this->db->trans_status() === FALSE) return FALSE;
@@ -405,6 +417,143 @@ class IssueModel extends Model
return $this->db->trans_status();
}
+ private function delete_all_files ($files)
+ {
+ foreach ($files as $f) @unlink ($f);
+ }
+
+ private function _create_issue ($userid, $issue, $attached_files, $uploader)
+ {
+ $this->db->trans_begin (); // manual transaction. not using trans_start().
+
+ $this->db->where ('projectid', $issue->projectid);
+ $this->db->select ('MAX(id) as maxid');
+ $query = $this->db->get ('issue');
+ if ($this->db->trans_status() === FALSE)
+ {
+ $this->errmsg = $this->db->_error_message();
+ $this->db->trans_rollback ();
+ return FALSE;
+ }
+
+ $result = $query->result();
+ $maxid = (empty($result) || $result[0] == NULL)? 0: $result[0]->maxid;
+
+ $newid = $maxid + 1;
+
+ $this->db->set ('projectid', $issue->projectid);
+ $this->db->set ('id', $newid);
+ $this->db->set ('summary', $issue->summary);
+ $this->db->set ('description', $issue->description);
+ $this->db->set ('type', $issue->type);
+ $this->db->set ('status', $issue->status);
+ $this->db->set ('owner', $issue->owner);
+ $this->db->set ('priority', $issue->priority);
+ $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 ('createdby', $userid);
+ $this->db->set ('updatedby', $userid);
+ $this->db->insert ('issue');
+ if ($this->db->trans_status() === FALSE)
+ {
+ $this->errmsg = $this->db->_error_message();
+ $this->db->trans_rollback ();
+ return FALSE;
+ }
+
+ $this->db->set ('projectid', $issue->projectid);
+ $this->db->set ('id', $newid);
+ $this->db->set ('sno', 1);
+ $this->db->set ('type', $issue->type);
+ $this->db->set ('status', $issue->status);
+ $this->db->set ('owner', $issue->owner);
+ $this->db->set ('comment', '');
+ $this->db->set ('priority', $issue->priority);
+ $this->db->set ('updatedon', date('Y-m-d H:i:s'));
+ $this->db->set ('updatedby', $userid);
+ $this->db->insert ('issue_change');
+ if ($this->db->trans_status() === FALSE)
+ {
+ $this->errmsg = $this->db->_error_message();
+ $this->db->trans_rollback ();
+ return FALSE;
+ }
+
+ $config['allowed_types'] = '*';
+ $config['upload_path'] = CODEPOT_ISSUE_FILE_DIR;
+ $config['max_size'] = CODEPOT_MAX_UPLOAD_SIZE;
+ $config['encrypt_name'] = TRUE;
+ $config['overwrite'] = FALSE;
+ $config['remove_spaces'] = FALSE;
+ $uploader->initialize ($config);
+
+ $ok_files = array();
+ $file_count = count($attached_files);
+ for ($i = 0; $i < $file_count; $i++)
+ {
+ $f = $attached_files[$i];
+ if (!$uploader->do_upload($f['fid']))
+ {
+ $this->errmsg = "Failed to upload {$f['name']}";
+ $this->db->trans_rollback ();
+ $this->delete_all_files ($ok_files);
+ return FALSE;
+ }
+
+ $ud = $uploader->data();
+ array_push ($ok_files, $ud['full_path']);
+
+ $md5sum = @md5_file ($ud['full_path']);
+ if ($md5sum === FALSE)
+ {
+ $this->db->trans_rollback ();
+ $this->delete_all_files ($ok_files);
+ return FALSE;
+ }
+
+ $this->db->set ('projectid', $issue->projectid);
+ $this->db->set ('issueid', $newid);
+ $this->db->set ('filename', $f['name']);
+ $this->db->set ('encname', $ud['file_name']);
+ $this->db->set ('description', $f['desc']);
+ $this->db->set ('md5sum', $md5sum);
+ $this->db->insert ('issue_file_list');
+ if ($this->db->trans_status() === FALSE)
+ {
+ $this->errmsg = $this->db->_error_message();
+ $this->db->trans_rollback ();
+ $this->delete_all_files ($ok_files);
+ return FALSE;
+ }
+ }
+
+ $this->db->set ('createdon', date('Y-m-d H:i:s'));
+ $this->db->set ('type', 'issue');
+ $this->db->set ('action', 'create');
+ $this->db->set ('projectid', $issue->projectid);
+ $this->db->set ('userid', $userid);
+ $this->db->set ('message', $newid);
+ $this->db->insert ('log');
+ if ($this->db->trans_status() === FALSE)
+ {
+ $this->errmsg = $this->db->_error_message();
+ $this->db->trans_rollback ();
+ $this->delete_all_files ($ok_files);
+ return FALSE;
+ }
+
+ $this->db->trans_commit ();
+ return $newid;
+ }
+
+ function create_with_files ($userid, $issue, $attached_files, $uploader)
+ {
+ set_error_handler (array ($this, 'capture_error'));
+ $errmsg = '';
+ $x = $this->_create_issue ($userid, $issue, $attached_files, $uploader);
+ restore_error_handler ();
+ return $x;
+ }
}
?>
diff --git a/codepot/src/codepot/views/issue_home.php b/codepot/src/codepot/views/issue_home.php
index a11732ed..a02ba245 100644
--- a/codepot/src/codepot/views/issue_home.php
+++ b/codepot/src/codepot/views/issue_home.php
@@ -10,12 +10,37 @@
+
+
+
+
+
+
+
+
+