Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
bugzilla
Commits
7c03ca4c
Commit
7c03ca4c
authored
Apr 08, 2005
by
lpsolit%gmail.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bug 238870: remove %FORM from attachment.cgi - Patch by Teemu Mannermaa…
Bug 238870: remove %FORM from attachment.cgi - Patch by Teemu Mannermaa <wicked@etlicon.fi> r=myk,LpSolit a=justdave
parent
27cf9640
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
287 additions
and
259 deletions
+287
-259
attachment.cgi
attachment.cgi
+287
-259
No files found.
attachment.cgi
View file @
7c03ca4c
...
@@ -50,20 +50,8 @@ use Bugzilla::User;
...
@@ -50,20 +50,8 @@ use Bugzilla::User;
use
Bugzilla::
Util
;
use
Bugzilla::
Util
;
use
Bugzilla::
Bug
;
use
Bugzilla::
Bug
;
# Check whether or not the user is logged in and, if so, set the $::userid
Bugzilla
->
login
();
Bugzilla
->
login
();
# The ID of the bug to which the attachment is attached. Gets set
# by validateID() (which validates the attachment ID, not the bug ID, but has
# to check if the user is authorized to access this attachment) and is used
# by Flag:: and FlagType::validate() to ensure the requestee (if any) for a
# requested flag is authorized to see the bug in question. Note: This should
# really be defined just above validateID() itself, but it's used in the main
# body of the script before that function is defined, so we define it up here
# instead. We should move the validation into each function and then move this
# to just above validateID().
my
$bugid
;
my
$cgi
=
Bugzilla
->
cgi
;
my
$cgi
=
Bugzilla
->
cgi
;
################################################################################
################################################################################
...
@@ -76,93 +64,42 @@ my $cgi = Bugzilla->cgi;
...
@@ -76,93 +64,42 @@ my $cgi = Bugzilla->cgi;
# supplied, we default to 'view'.
# supplied, we default to 'view'.
# Determine whether to use the action specified by the user or the default.
# Determine whether to use the action specified by the user or the default.
my
$action
=
$
::FORM
{
'action'
}
||
'view'
;
my
$action
=
$
cgi
->
param
(
'action'
)
||
'view'
;
if
(
$action
eq
"view"
)
if
(
$action
eq
"view"
)
{
{
validateID
();
view
();
view
();
}
}
elsif
(
$action
eq
"interdiff"
)
elsif
(
$action
eq
"interdiff"
)
{
{
validateID
(
'oldid'
);
interdiff
();
validateID
(
'newid'
);
validateFormat
(
"html"
,
"raw"
);
validateContext
();
interdiff
();
}
}
elsif
(
$action
eq
"diff"
)
elsif
(
$action
eq
"diff"
)
{
{
validateID
();
diff
();
validateFormat
(
"html"
,
"raw"
);
validateContext
();
diff
();
}
}
elsif
(
$action
eq
"viewall"
)
elsif
(
$action
eq
"viewall"
)
{
{
ValidateBugID
(
$::FORM
{
'bugid'
});
viewall
();
viewall
();
}
}
elsif
(
$action
eq
"enter"
)
elsif
(
$action
eq
"enter"
)
{
{
Bugzilla
->
login
(
LOGIN_REQUIRED
);
Bugzilla
->
login
(
LOGIN_REQUIRED
);
ValidateBugID
(
$::FORM
{
'bugid'
});
enter
();
validateCanChangeBug
(
$::FORM
{
'bugid'
});
enter
();
}
}
elsif
(
$action
eq
"insert"
)
elsif
(
$action
eq
"insert"
)
{
{
Bugzilla
->
login
(
LOGIN_REQUIRED
);
Bugzilla
->
login
(
LOGIN_REQUIRED
);
ValidateBugID
(
$::FORM
{
'bugid'
});
insert
();
validateCanChangeBug
(
$::FORM
{
'bugid'
});
ValidateComment
(
$::FORM
{
'comment'
});
validateFilename
();
validateIsPatch
();
my
$data
=
validateData
();
validateDescription
();
validateContentType
()
unless
$::FORM
{
'ispatch'
};
validateObsolete
()
if
$::FORM
{
'obsolete'
};
# The order of these function calls is important, as both Flag::validate
# and FlagType::validate assume User::match_field has ensured that the values
# in the requestee fields are legitimate user email addresses.
Bugzilla::User::
match_field
(
$cgi
,
{
'^requestee(_type)?-(\d+)$'
=>
{
'type'
=>
'single'
}
});
Bugzilla::Flag::
validate
(
$cgi
,
$bugid
);
Bugzilla::FlagType::
validate
(
$cgi
,
$bugid
,
$::FORM
{
'id'
});
insert
(
$data
);
}
}
elsif
(
$action
eq
"edit"
)
elsif
(
$action
eq
"edit"
)
{
{
validateID
();
edit
();
validateCanEdit
(
$::FORM
{
'id'
});
edit
();
}
}
elsif
(
$action
eq
"update"
)
elsif
(
$action
eq
"update"
)
{
{
Bugzilla
->
login
(
LOGIN_REQUIRED
);
Bugzilla
->
login
(
LOGIN_REQUIRED
);
ValidateComment
(
$::FORM
{
'comment'
});
update
();
validateID
();
validateCanEdit
(
$::FORM
{
'id'
});
validateCanChangeAttachment
(
$::FORM
{
'id'
});
validateDescription
();
validateIsPatch
();
validateContentType
()
unless
$::FORM
{
'ispatch'
};
validateIsObsolete
();
validatePrivate
();
# The order of these function calls is important, as both Flag::validate
# and FlagType::validate assume User::match_field has ensured that the values
# in the requestee fields are legitimate user email addresses.
Bugzilla::User::
match_field
(
$cgi
,
{
'^requestee(_type)?-(\d+)$'
=>
{
'type'
=>
'single'
}
});
Bugzilla::Flag::
validate
(
$cgi
,
$bugid
);
Bugzilla::FlagType::
validate
(
$cgi
,
$bugid
,
$::FORM
{
'id'
});
update
();
}
}
else
else
{
{
...
@@ -175,6 +112,18 @@ exit;
...
@@ -175,6 +112,18 @@ exit;
# Data Validation / Security Authorization
# Data Validation / Security Authorization
################################################################################
################################################################################
# Validates an attachment ID. Optionally takes a parameter of a form
# variable name that contains the ID to be validated. If not specified,
# uses 'id'.
#
# Will throw an error if 1) attachment ID is not a valid number,
# 2) attachment does not exist, or 3) user isn't allowed to access the
# attachment.
#
# Returns a list, where the first item is the validated, detainted
# attachment id, and the 2nd item is the bug id corresponding to the
# attachment.
#
sub
validateID
sub
validateID
{
{
my
$param
=
@_
?
$_
[
0
]
:
'id'
;
my
$param
=
@_
?
$_
[
0
]
:
'id'
;
...
@@ -204,7 +153,8 @@ sub validateID
...
@@ -204,7 +153,8 @@ sub validateID
||
ThrowUserError
(
"invalid_attach_id"
,
{
attach_id
=>
$attach_id
});
||
ThrowUserError
(
"invalid_attach_id"
,
{
attach_id
=>
$attach_id
});
# Make sure the user is authorized to access this attachment's bug.
# Make sure the user is authorized to access this attachment's bug.
(
$bugid
,
my
$isprivate
)
=
FetchSQLData
();
(
my
$bugid
,
my
$isprivate
)
=
FetchSQLData
();
ValidateBugID
(
$bugid
);
ValidateBugID
(
$bugid
);
if
(
$isprivate
&&
Param
(
"insidergroup"
))
{
if
(
$isprivate
&&
Param
(
"insidergroup"
))
{
UserInGroup
(
Param
(
"insidergroup"
))
UserInGroup
(
Param
(
"insidergroup"
))
...
@@ -212,10 +162,12 @@ sub validateID
...
@@ -212,10 +162,12 @@ sub validateID
object
=>
"attachment"
});
object
=>
"attachment"
});
}
}
# XXX shim code, kill $::FORM
return
(
$attach_id
,
$bugid
);
$::FORM
{
$param
}
=
$attach_id
;
}
}
# Validates format of a diff/interdiff. Takes a list as an parameter, which
# defines the valid format values. Will throw an error if the format is not
# in the list. Returns either the user selected or default format.
sub
validateFormat
sub
validateFormat
{
{
# receives a list of legal formats; first item is a default
# receives a list of legal formats; first item is a default
...
@@ -225,10 +177,11 @@ sub validateFormat
...
@@ -225,10 +177,11 @@ sub validateFormat
ThrowUserError
(
"invalid_format"
,
{
format
=>
$format
,
formats
=>
\
@_
});
ThrowUserError
(
"invalid_format"
,
{
format
=>
$format
,
formats
=>
\
@_
});
}
}
# XXX shim code, kill $::FORM
return
$format
;
$::FORM
{
'format'
}
=
$format
;
}
}
# Validates context of a diff/interdiff. Will throw an error if the context
# is not number, "file" or "patch". Returns the validated, detainted context.
sub
validateContext
sub
validateContext
{
{
my
$context
=
$cgi
->
param
(
'context'
)
||
"patch"
;
my
$context
=
$cgi
->
param
(
'context'
)
||
"patch"
;
...
@@ -236,8 +189,8 @@ sub validateContext
...
@@ -236,8 +189,8 @@ sub validateContext
detaint_natural
(
$context
)
detaint_natural
(
$context
)
||
ThrowUserError
(
"invalid_context"
,
{
context
=>
$cgi
->
param
(
'context'
)
});
||
ThrowUserError
(
"invalid_context"
,
{
context
=>
$cgi
->
param
(
'context'
)
});
}
}
# XXX shim code, kill $::FORM
$::FORM
{
'context'
}
=
$context
;
return
$context
;
}
}
sub
validateCanEdit
sub
validateCanEdit
...
@@ -249,14 +202,14 @@ sub validateCanEdit
...
@@ -249,14 +202,14 @@ sub validateCanEdit
# People not logged in can't actually commit changes, because that code
# People not logged in can't actually commit changes, because that code
# calls Bugzilla->login with LOGIN_REQUIRED, not with LOGIN_NORMAL,
# calls Bugzilla->login with LOGIN_REQUIRED, not with LOGIN_NORMAL,
# before calling this sub
# before calling this sub
return
if
$::userid
==
0
;
return
unless
Bugzilla
->
user
;
# People in editbugs can edit all attachments
# People in editbugs can edit all attachments
return
if
UserInGroup
(
"editbugs"
);
return
if
UserInGroup
(
"editbugs"
);
# Bug 97729 - the submitter can edit their attachments
# Bug 97729 - the submitter can edit their attachments
SendSQL
(
"SELECT attach_id FROM attachments WHERE "
.
SendSQL
(
"SELECT attach_id FROM attachments WHERE "
.
"attach_id = $attach_id AND submitter_id =
$::userid"
);
"attach_id = $attach_id AND submitter_id =
"
.
Bugzilla
->
user
->
id
);
FetchSQLData
()
FetchSQLData
()
||
ThrowUserError
(
"illegal_attachment_edit"
,
||
ThrowUserError
(
"illegal_attachment_edit"
,
...
@@ -291,28 +244,28 @@ sub validateCanChangeBug
...
@@ -291,28 +244,28 @@ sub validateCanChangeBug
sub
validateDescription
sub
validateDescription
{
{
$::FORM
{
'description'
}
$cgi
->
param
(
'description'
)
||
ThrowUserError
(
"missing_attachment_description"
);
||
ThrowUserError
(
"missing_attachment_description"
);
}
}
sub
validateIsPatch
sub
validateIsPatch
{
{
# Set the ispatch flag to zero if it is undefined, since the UI uses
# Set the ispatch flag to zero if it is undefined, since the UI uses
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# do not get sent in HTML requests.
# do not get sent in HTML requests.
$::FORM
{
'ispatch'
}
=
$::FORM
{
'ispatch'
}
?
1
:
0
;
$cgi
->
param
(
'ispatch'
,
$cgi
->
param
(
'ispatch'
)
?
1
:
0
)
;
# Set the content type to text/plain if the attachment is a patch.
# Set the content type to text/plain if the attachment is a patch.
$::FORM
{
'contenttype'
}
=
"text/plain"
if
$::FORM
{
'ispatch'
}
;
$cgi
->
param
(
'contenttype'
,
'text/plain'
)
if
$cgi
->
param
(
'ispatch'
)
;
}
}
sub
validateContentType
sub
validateContentType
{
{
if
(
!
$::FORM
{
'contenttypemethod'
}
)
if
(
!
defined
$cgi
->
param
(
'contenttypemethod'
)
)
{
{
ThrowUserError
(
"missing_content_type_method"
);
ThrowUserError
(
"missing_content_type_method"
);
}
}
elsif
(
$
::FORM
{
'contenttypemethod'
}
eq
'autodetect'
)
elsif
(
$
cgi
->
param
(
'contenttypemethod'
)
eq
'autodetect'
)
{
{
my
$contenttype
=
$cgi
->
uploadInfo
(
$cgi
->
param
(
'data'
))
->
{
'Content-Type'
};
my
$contenttype
=
$cgi
->
uploadInfo
(
$cgi
->
param
(
'data'
))
->
{
'Content-Type'
};
# The user asked us to auto-detect the content type, so use the type
# The user asked us to auto-detect the content type, so use the type
...
@@ -321,37 +274,38 @@ sub validateContentType
...
@@ -321,37 +274,38 @@ sub validateContentType
{
{
ThrowUserError
(
"missing_content_type"
);
ThrowUserError
(
"missing_content_type"
);
}
}
$
::FORM
{
'contenttype'
}
=
$contenttype
;
$
cgi
->
param
(
'contenttype'
,
$contenttype
)
;
}
}
elsif
(
$
::FORM
{
'contenttypemethod'
}
eq
'list'
)
elsif
(
$
cgi
->
param
(
'contenttypemethod'
)
eq
'list'
)
{
{
# The user selected a content type from the list, so use their selection.
# The user selected a content type from the list, so use their selection.
$
::FORM
{
'contenttype'
}
=
$::FORM
{
'contenttypeselection'
}
;
$
cgi
->
param
(
'contenttype'
,
$cgi
->
param
(
'contenttypeselection'
))
;
}
}
elsif
(
$
::FORM
{
'contenttypemethod'
}
eq
'manual'
)
elsif
(
$
cgi
->
param
(
'contenttypemethod'
)
eq
'manual'
)
{
{
# The user entered a content type manually, so use their entry.
# The user entered a content type manually, so use their entry.
$
::FORM
{
'contenttype'
}
=
$::FORM
{
'contenttypeentry'
}
;
$
cgi
->
param
(
'contenttype'
,
$cgi
->
param
(
'contenttypeentry'
))
;
}
}
else
else
{
{
ThrowCodeError
(
"illegal_content_type_method"
,
ThrowCodeError
(
"illegal_content_type_method"
,
{
contenttypemethod
=>
$
::FORM
{
'contenttypemethod'
}
});
{
contenttypemethod
=>
$
cgi
->
param
(
'contenttypemethod'
)
});
}
}
if
(
$::FORM
{
'contenttype'
}
!~
/^(application|audio|image|message|model|multipart|text|video)\/.+$/
)
if
(
$cgi
->
param
(
'contenttype'
)
!~
/^(application|audio|image|message|model|multipart|text|video)\/.+$/
)
{
{
ThrowUserError
(
"invalid_content_type"
,
ThrowUserError
(
"invalid_content_type"
,
{
contenttype
=>
$
::FORM
{
'contenttype'
}
});
{
contenttype
=>
$
cgi
->
param
(
'contenttype'
)
});
}
}
}
}
sub
validateIsObsolete
sub
validateIsObsolete
{
{
# Set the isobsolete flag to zero if it is undefined, since the UI uses
# Set the isobsolete flag to zero if it is undefined, since the UI uses
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# do not get sent in HTML requests.
# do not get sent in HTML requests.
$::FORM
{
'isobsolete'
}
=
$::FORM
{
'isobsolete'
}
?
1
:
0
;
$cgi
->
param
(
'isobsolete'
,
$cgi
->
param
(
'isobsolete'
)
?
1
:
0
)
;
}
}
sub
validatePrivate
sub
validatePrivate
...
@@ -359,17 +313,17 @@ sub validatePrivate
...
@@ -359,17 +313,17 @@ sub validatePrivate
# Set the isprivate flag to zero if it is undefined, since the UI uses
# Set the isprivate flag to zero if it is undefined, since the UI uses
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# do not get sent in HTML requests.
# do not get sent in HTML requests.
$
::FORM
{
'isprivate'
}
=
$::FORM
{
'isprivate'
}
?
1
:
0
;
$
cgi
->
param
(
'isprivate'
,
$cgi
->
param
(
'isprivate'
)
?
1
:
0
)
;
}
}
sub
validateData
sub
validateData
{
{
my
$maxsize
=
$
::FORM
{
'ispatch'
}
?
Param
(
'maxpatchsize'
)
:
Param
(
'maxattachmentsize'
);
my
$maxsize
=
$
cgi
->
param
(
'ispatch'
)
?
Param
(
'maxpatchsize'
)
:
Param
(
'maxattachmentsize'
);
$maxsize
*=
1024
;
# Convert from K
$maxsize
*=
1024
;
# Convert from K
my
$fh
;
my
$fh
;
# Skip uploading into a local variable if the user wants to upload huge
# Skip uploading into a local variable if the user wants to upload huge
# attachments into local files.
# attachments into local files.
if
(
!
$
::FORM
{
'bigfile'
}
)
if
(
!
$
cgi
->
param
(
'bigfile'
)
)
{
{
$fh
=
$cgi
->
upload
(
'data'
);
$fh
=
$cgi
->
upload
(
'data'
);
}
}
...
@@ -377,7 +331,7 @@ sub validateData
...
@@ -377,7 +331,7 @@ sub validateData
# We could get away with reading only as much as required, except that then
# We could get away with reading only as much as required, except that then
# we wouldn't have a size to print to the error handler below.
# we wouldn't have a size to print to the error handler below.
if
(
!
$
::FORM
{
'bigfile'
}
)
if
(
!
$
cgi
->
param
(
'bigfile'
)
)
{
{
# enable 'slurp' mode
# enable 'slurp' mode
local
$/
;
local
$/
;
...
@@ -385,14 +339,14 @@ sub validateData
...
@@ -385,14 +339,14 @@ sub validateData
}
}
$data
$data
||
(
$
::FORM
{
'bigfile'
}
)
||
(
$
cgi
->
param
(
'bigfile'
)
)
||
ThrowUserError
(
"zero_length_file"
);
||
ThrowUserError
(
"zero_length_file"
);
# Make sure the attachment does not exceed the maximum permitted size
# Make sure the attachment does not exceed the maximum permitted size
my
$len
=
$data
?
length
(
$data
)
:
0
;
my
$len
=
$data
?
length
(
$data
)
:
0
;
if
(
$maxsize
&&
$len
>
$maxsize
)
{
if
(
$maxsize
&&
$len
>
$maxsize
)
{
my
$vars
=
{
filesize
=>
sprintf
(
"%.0f"
,
$len
/
1024
)
};
my
$vars
=
{
filesize
=>
sprintf
(
"%.0f"
,
$len
/
1024
)
};
if
(
$::FORM
{
'ispatch'
}
)
{
if
(
$cgi
->
param
(
'ispatch'
)
)
{
ThrowUserError
(
"patch_too_large"
,
$vars
);
ThrowUserError
(
"patch_too_large"
,
$vars
);
}
else
{
}
else
{
ThrowUserError
(
"file_too_large"
,
$vars
);
ThrowUserError
(
"file_too_large"
,
$vars
);
...
@@ -402,13 +356,12 @@ sub validateData
...
@@ -402,13 +356,12 @@ sub validateData
return
$data
||
''
;
return
$data
||
''
;
}
}
my
$filename
;
sub
validateFilename
sub
validateFilename
{
{
defined
$cgi
->
upload
(
'data'
)
defined
$cgi
->
upload
(
'data'
)
||
ThrowUserError
(
"file_not_specified"
);
||
ThrowUserError
(
"file_not_specified"
);
$filename
=
$cgi
->
upload
(
'data'
);
my
$filename
=
$cgi
->
upload
(
'data'
);
# Remove path info (if any) from the file name. The browser should do this
# Remove path info (if any) from the file name. The browser should do this
# for us, but some are buggy. This may not work on Mac file names and could
# for us, but some are buggy. This may not work on Mac file names and could
...
@@ -420,13 +373,17 @@ sub validateFilename
...
@@ -420,13 +373,17 @@ sub validateFilename
# Truncate the filename to 100 characters, counting from the end of the string
# Truncate the filename to 100 characters, counting from the end of the string
# to make sure we keep the filename extension.
# to make sure we keep the filename extension.
$filename
=
substr
(
$filename
,
-
100
,
100
);
$filename
=
substr
(
$filename
,
-
100
,
100
);
return
$filename
;
}
}
sub
validateObsolete
sub
validateObsolete
{
{
my
@obsolete_ids
=
();
# Make sure the attachment id is valid and the user has permissions to view
# Make sure the attachment id is valid and the user has permissions to view
# the bug to which it is attached.
# the bug to which it is attached.
foreach
my
$attachid
(
@
{
$::MFORM
{
'obsolete'
}}
)
{
foreach
my
$attachid
(
$cgi
->
param
(
'obsolete'
)
)
{
my
$vars
=
{};
my
$vars
=
{};
$vars
->
{
'attach_id'
}
=
$attachid
;
$vars
->
{
'attach_id'
}
=
$attachid
;
...
@@ -444,9 +401,9 @@ sub validateObsolete
...
@@ -444,9 +401,9 @@ sub validateObsolete
$vars
->
{
'description'
}
=
$description
;
$vars
->
{
'description'
}
=
$description
;
if
(
$bugid
!=
$
::FORM
{
'bugid'
}
)
if
(
$bugid
!=
$
cgi
->
param
(
'bugid'
)
)
{
{
$vars
->
{
'my_bug_id'
}
=
$
::FORM
{
'bugid'
}
;
$vars
->
{
'my_bug_id'
}
=
$
cgi
->
param
(
'bugid'
)
;
$vars
->
{
'attach_bug_id'
}
=
$bugid
;
$vars
->
{
'attach_bug_id'
}
=
$bugid
;
ThrowCodeError
(
"mismatched_bug_ids_on_obsolete"
,
$vars
);
ThrowCodeError
(
"mismatched_bug_ids_on_obsolete"
,
$vars
);
}
}
...
@@ -458,7 +415,10 @@ sub validateObsolete
...
@@ -458,7 +415,10 @@ sub validateObsolete
# Check that the user can modify this attachment
# Check that the user can modify this attachment
validateCanEdit
(
$attachid
);
validateCanEdit
(
$attachid
);
push
(
@obsolete_ids
,
$attachid
);
}
}
return
@obsolete_ids
;
}
}
# Returns 1 if the parameter is a content-type viewable in this browser
# Returns 1 if the parameter is a content-type viewable in this browser
...
@@ -497,21 +457,25 @@ sub isViewable
...
@@ -497,21 +457,25 @@ sub isViewable
# Functions
# Functions
################################################################################
################################################################################
# Display an attachment.
sub
view
sub
view
{
{
# Display an attachment.
# Retrieve and validate parameters
my
(
$attach_id
)
=
validateID
();
# Retrieve the attachment content and its content type from the database.
# Retrieve the attachment content and its content type from the database.
SendSQL
(
"SELECT mimetype, filename, thedata FROM attachments WHERE attach_id = $::FORM{'id'}"
);
SendSQL
(
"SELECT mimetype, filename, thedata FROM attachments "
.
"WHERE attach_id = $attach_id"
);
my
(
$contenttype
,
$filename
,
$thedata
)
=
FetchSQLData
();
my
(
$contenttype
,
$filename
,
$thedata
)
=
FetchSQLData
();
# Bug 111522: allow overriding content-type manually in the posted $::FORM.
# Bug 111522: allow overriding content-type manually in the posted form
if
(
$::FORM
{
'content_type'
})
# params.
if
(
defined
$cgi
->
param
(
'content_type'
))
{
{
$
::FORM
{
'contenttypemethod'
}
=
'manual'
;
$
cgi
->
param
(
'contenttypemethod'
,
'manual'
)
;
$
::FORM
{
'contenttypeentry'
}
=
$::FORM
{
'content_type'
}
;
$
cgi
->
param
(
'contenttypeentry'
,
$cgi
->
param
(
'content_type'
))
;
validateContentType
();
validateContentType
();
$contenttype
=
$
::FORM
{
'content_type'
}
;
$contenttype
=
$
cgi
->
param
(
'content_type'
)
;
}
}
# Return the appropriate HTTP response headers.
# Return the appropriate HTTP response headers.
...
@@ -521,10 +485,9 @@ sub view
...
@@ -521,10 +485,9 @@ sub view
# stored in a local file
# stored in a local file
if
(
$filesize
==
0
)
if
(
$filesize
==
0
)
{
{
my
$attachid
=
$::FORM
{
'id'
};
my
$hash
=
(
$attach_id
%
100
)
+
100
;
my
$hash
=
(
$attachid
%
100
)
+
100
;
$hash
=~
s/.*(\d\d)$/group.$1/
;
$hash
=~
s/.*(\d\d)$/group.$1/
;
if
(
open
(
AH
,
"$attachdir/$hash/attachment.$attachid"
))
{
if
(
open
(
AH
,
"$attachdir/$hash/attachment.$attach
_
id"
))
{
binmode
AH
;
binmode
AH
;
$filesize
=
(
stat
(
AH
))[
7
];
$filesize
=
(
stat
(
AH
))[
7
];
}
}
...
@@ -556,13 +519,19 @@ sub view
...
@@ -556,13 +519,19 @@ sub view
sub
interdiff
sub
interdiff
{
{
# Retrieve and validate parameters
my
(
$old_id
)
=
validateID
(
'oldid'
);
my
(
$new_id
)
=
validateID
(
'newid'
);
my
$format
=
validateFormat
(
'html'
,
'raw'
);
my
$context
=
validateContext
();
# Get old patch data
# Get old patch data
my
(
$old_bugid
,
$old_description
,
$old_filename
,
$old_file_list
)
=
my
(
$old_bugid
,
$old_description
,
$old_filename
,
$old_file_list
)
=
get_unified_diff
(
$
::FORM
{
'oldid'
}
);
get_unified_diff
(
$
old_id
);
# Get new patch data
# Get new patch data
my
(
$new_bugid
,
$new_description
,
$new_filename
,
$new_file_list
)
=
my
(
$new_bugid
,
$new_description
,
$new_filename
,
$new_file_list
)
=
get_unified_diff
(
$
::FORM
{
'newid'
}
);
get_unified_diff
(
$
new_id
);
my
$warning
=
warn_if_interdiff_might_fail
(
$old_file_list
,
$new_file_list
);
my
$warning
=
warn_if_interdiff_might_fail
(
$old_file_list
,
$new_file_list
);
...
@@ -574,8 +543,8 @@ sub interdiff
...
@@ -574,8 +543,8 @@ sub interdiff
$ENV
{
'PATH'
}
=
$::diffpath
;
$ENV
{
'PATH'
}
=
$::diffpath
;
open
my
$interdiff_fh
,
"$::interdiffbin $old_filename $new_filename|"
;
open
my
$interdiff_fh
,
"$::interdiffbin $old_filename $new_filename|"
;
binmode
$interdiff_fh
;
binmode
$interdiff_fh
;
my
(
$reader
,
$last_reader
)
=
setup_patch_readers
(
""
);
my
(
$reader
,
$last_reader
)
=
setup_patch_readers
(
""
,
$context
);
if
(
$::FORM
{
'format'
}
eq
"raw"
)
if
(
$format
eq
'raw'
)
{
{
require
PatchReader::DiffPrinter::
raw
;
require
PatchReader::DiffPrinter::
raw
;
$last_reader
->
sends_data_to
(
new
PatchReader::DiffPrinter::
raw
());
$last_reader
->
sends_data_to
(
new
PatchReader::DiffPrinter::
raw
());
...
@@ -587,16 +556,16 @@ sub interdiff
...
@@ -587,16 +556,16 @@ sub interdiff
{
{
$vars
->
{
warning
}
=
$warning
if
$warning
;
$vars
->
{
warning
}
=
$warning
if
$warning
;
$vars
->
{
bugid
}
=
$new_bugid
;
$vars
->
{
bugid
}
=
$new_bugid
;
$vars
->
{
oldid
}
=
$
::FORM
{
'oldid'
}
;
$vars
->
{
oldid
}
=
$
old_id
;
$vars
->
{
old_desc
}
=
$old_description
;
$vars
->
{
old_desc
}
=
$old_description
;
$vars
->
{
newid
}
=
$
::FORM
{
'newid'
}
;
$vars
->
{
newid
}
=
$
new_id
;
$vars
->
{
new_desc
}
=
$new_description
;
$vars
->
{
new_desc
}
=
$new_description
;
delete
$vars
->
{
attachid
};
delete
$vars
->
{
attachid
};
delete
$vars
->
{
do_context
};
delete
$vars
->
{
do_context
};
delete
$vars
->
{
context
};
delete
$vars
->
{
context
};
setup_template_patch_reader
(
$last_reader
);
setup_template_patch_reader
(
$last_reader
,
$format
,
$context
);
}
}
$reader
->
iterate_fh
(
$interdiff_fh
,
"interdiff #$
::FORM{'oldid'} #$::FORM{'newid'}
"
);
$reader
->
iterate_fh
(
$interdiff_fh
,
"interdiff #$
old_id #$new_id
"
);
close
$interdiff_fh
;
close
$interdiff_fh
;
$ENV
{
'PATH'
}
=
''
;
$ENV
{
'PATH'
}
=
''
;
...
@@ -676,7 +645,7 @@ sub warn_if_interdiff_might_fail {
...
@@ -676,7 +645,7 @@ sub warn_if_interdiff_might_fail {
}
}
sub
setup_patch_readers
{
sub
setup_patch_readers
{
my
(
$diff_root
)
=
@_
;
my
(
$diff_root
,
$context
)
=
@_
;
#
#
# Parameters:
# Parameters:
...
@@ -700,11 +669,11 @@ sub setup_patch_readers {
...
@@ -700,11 +669,11 @@ sub setup_patch_readers {
$last_reader
=
$last_reader
->
sends_data_to
;
$last_reader
=
$last_reader
->
sends_data_to
;
}
}
# Add in cvs context if we have the necessary info to do it
# Add in cvs context if we have the necessary info to do it
if
(
$
::FORM
{
'context'
}
ne
"patch"
&&
$::cvsbin
&&
Param
(
'cvsroot_get'
))
if
(
$
context
ne
"patch"
&&
$::cvsbin
&&
Param
(
'cvsroot_get'
))
{
{
require
PatchReader::
AddCVSContext
;
require
PatchReader::
AddCVSContext
;
$last_reader
->
sends_data_to
(
$last_reader
->
sends_data_to
(
new
PatchReader::
AddCVSContext
(
$::FORM
{
'context'
}
,
new
PatchReader::
AddCVSContext
(
$context
,
Param
(
'cvsroot_get'
)));
Param
(
'cvsroot_get'
)));
$last_reader
=
$last_reader
->
sends_data_to
;
$last_reader
=
$last_reader
->
sends_data_to
;
}
}
...
@@ -713,20 +682,18 @@ sub setup_patch_readers {
...
@@ -713,20 +682,18 @@ sub setup_patch_readers {
sub
setup_template_patch_reader
sub
setup_template_patch_reader
{
{
my
(
$last_reader
)
=
@_
;
my
(
$last_reader
,
$format
,
$context
)
=
@_
;
require
PatchReader::DiffPrinter::
template
;
require
PatchReader::DiffPrinter::
template
;
my
$format
=
$::FORM
{
'format'
};
# Define the vars for templates
# Define the vars for templates
if
(
defined
(
$::FORM
{
'headers'
}
))
{
if
(
defined
$cgi
->
param
(
'headers'
))
{
$vars
->
{
headers
}
=
$
::FORM
{
'headers'
}
;
$vars
->
{
headers
}
=
$
cgi
->
param
(
'headers'
)
;
}
else
{
}
else
{
$vars
->
{
headers
}
=
1
if
!
defined
(
$::FORM
{
'headers'
}
);
$vars
->
{
headers
}
=
1
if
!
defined
$cgi
->
param
(
'headers'
);
}
}
$vars
->
{
collapsed
}
=
$
::FORM
{
'collapsed'
}
;
$vars
->
{
collapsed
}
=
$
cgi
->
param
(
'collapsed'
)
;
$vars
->
{
context
}
=
$
::FORM
{
'context'
}
;
$vars
->
{
context
}
=
$
context
;
$vars
->
{
do_context
}
=
$::cvsbin
&&
Param
(
'cvsroot_get'
)
&&
!
$vars
->
{
'newid'
};
$vars
->
{
do_context
}
=
$::cvsbin
&&
Param
(
'cvsroot_get'
)
&&
!
$vars
->
{
'newid'
};
# Print everything out
# Print everything out
...
@@ -745,8 +712,14 @@ sub setup_template_patch_reader
...
@@ -745,8 +712,14 @@ sub setup_template_patch_reader
sub
diff
sub
diff
{
{
# Retrieve and validate parameters
my
(
$attach_id
)
=
validateID
();
my
$format
=
validateFormat
(
'html'
,
'raw'
);
my
$context
=
validateContext
();
# Get patch data
# Get patch data
SendSQL
(
"SELECT bug_id, description, ispatch, thedata FROM attachments WHERE attach_id = $::FORM{'id'}"
);
SendSQL
(
"SELECT bug_id, description, ispatch, thedata FROM attachments "
.
"WHERE attach_id = $attach_id"
);
my
(
$bugid
,
$description
,
$ispatch
,
$thedata
)
=
FetchSQLData
();
my
(
$bugid
,
$description
,
$ispatch
,
$thedata
)
=
FetchSQLData
();
# If it is not a patch, view normally
# If it is not a patch, view normally
...
@@ -756,9 +729,9 @@ sub diff
...
@@ -756,9 +729,9 @@ sub diff
return
;
return
;
}
}
my
(
$reader
,
$last_reader
)
=
setup_patch_readers
();
my
(
$reader
,
$last_reader
)
=
setup_patch_readers
(
undef
,
$context
);
if
(
$
::FORM
{
'format'
}
eq
"raw"
)
if
(
$
format
eq
'raw'
)
{
{
require
PatchReader::DiffPrinter::
raw
;
require
PatchReader::DiffPrinter::
raw
;
$last_reader
->
sends_data_to
(
new
PatchReader::DiffPrinter::
raw
());
$last_reader
->
sends_data_to
(
new
PatchReader::DiffPrinter::
raw
());
...
@@ -766,7 +739,7 @@ sub diff
...
@@ -766,7 +739,7 @@ sub diff
use
vars
qw($cgi)
;
use
vars
qw($cgi)
;
print
$cgi
->
header
(
-
type
=>
'text/plain'
,
print
$cgi
->
header
(
-
type
=>
'text/plain'
,
-
expires
=>
'+3M'
);
-
expires
=>
'+3M'
);
$reader
->
iterate_string
(
"Attachment
"
.
$::FORM
{
'id'
}
,
$thedata
);
$reader
->
iterate_string
(
"Attachment
$attach_id"
,
$thedata
);
}
}
else
else
{
{
...
@@ -778,7 +751,7 @@ sub diff
...
@@ -778,7 +751,7 @@ sub diff
SendSQL
(
"SELECT attach_id, description FROM attachments WHERE bug_id = $bugid AND ispatch = 1 ORDER BY creation_ts DESC"
);
SendSQL
(
"SELECT attach_id, description FROM attachments WHERE bug_id = $bugid AND ispatch = 1 ORDER BY creation_ts DESC"
);
my
$select_next_patch
=
0
;
my
$select_next_patch
=
0
;
while
(
my
(
$other_id
,
$other_desc
)
=
FetchSQLData
())
{
while
(
my
(
$other_id
,
$other_desc
)
=
FetchSQLData
())
{
if
(
$other_id
eq
$
::FORM
{
'id'
}
)
{
if
(
$other_id
eq
$
attach_id
)
{
$select_next_patch
=
1
;
$select_next_patch
=
1
;
}
else
{
}
else
{
push
@
{
$vars
->
{
other_patches
}},
{
id
=>
$other_id
,
desc
=>
$other_desc
,
selected
=>
$select_next_patch
};
push
@
{
$vars
->
{
other_patches
}},
{
id
=>
$other_id
,
desc
=>
$other_desc
,
selected
=>
$select_next_patch
};
...
@@ -790,20 +763,24 @@ sub diff
...
@@ -790,20 +763,24 @@ sub diff
}
}
$vars
->
{
bugid
}
=
$bugid
;
$vars
->
{
bugid
}
=
$bugid
;
$vars
->
{
attachid
}
=
$
::FORM
{
'id'
}
;
$vars
->
{
attachid
}
=
$
attach_id
;
$vars
->
{
description
}
=
$description
;
$vars
->
{
description
}
=
$description
;
setup_template_patch_reader
(
$last_reader
);
setup_template_patch_reader
(
$last_reader
,
$format
,
$context
);
# Actually print out the patch
# Actually print out the patch
$reader
->
iterate_string
(
"Attachment
"
.
$::FORM
{
'id'
}
,
$thedata
);
$reader
->
iterate_string
(
"Attachment
$attach_id"
,
$thedata
);
}
}
}
}
# Display all attachments for a given bug in a series of IFRAMEs within one
# HTML page.
sub
viewall
sub
viewall
{
{
# Display all attachments for a given bug in a series of IFRAMEs within one HTML page.
# Retrieve and validate parameters
my
$bugid
=
$cgi
->
param
(
'bugid'
);
ValidateBugID
(
$bugid
);
# Retrieve the attachments from the database and write them into an array
# Retrieve the attachments from the database and write them into an array
# of hashes where each hash represents one attachment.
# of hashes where each hash represents one attachment.
my
$privacy
=
""
;
my
$privacy
=
""
;
my
$dbh
=
Bugzilla
->
dbh
;
my
$dbh
=
Bugzilla
->
dbh
;
...
@@ -814,7 +791,7 @@ sub viewall
...
@@ -814,7 +791,7 @@ sub viewall
$dbh
->
sql_date_format
(
'creation_ts'
,
'%Y.%m.%d %H:%i'
)
.
",
$dbh
->
sql_date_format
(
'creation_ts'
,
'%Y.%m.%d %H:%i'
)
.
",
mimetype, description, ispatch, isobsolete, isprivate,
mimetype, description, ispatch, isobsolete, isprivate,
LENGTH(thedata)
LENGTH(thedata)
FROM attachments WHERE bug_id = $
::FORM{'bugid'}
$privacy
FROM attachments WHERE bug_id = $
bugid
$privacy
ORDER BY attach_id"
);
ORDER BY attach_id"
);
my
@attachments
;
# the attachments array
my
@attachments
;
# the attachments array
while
(
MoreSQLData
())
while
(
MoreSQLData
())
...
@@ -833,11 +810,11 @@ sub viewall
...
@@ -833,11 +810,11 @@ sub viewall
# Retrieve the bug summary (for displaying on screen) and assignee.
# Retrieve the bug summary (for displaying on screen) and assignee.
SendSQL
(
"SELECT short_desc, assigned_to FROM bugs "
.
SendSQL
(
"SELECT short_desc, assigned_to FROM bugs "
.
"WHERE bug_id = $
::FORM{'bugid'}
"
);
"WHERE bug_id = $
bugid
"
);
my
(
$bugsummary
,
$assignee_id
)
=
FetchSQLData
();
my
(
$bugsummary
,
$assignee_id
)
=
FetchSQLData
();
# Define the variables and functions that will be passed to the UI template.
# Define the variables and functions that will be passed to the UI template.
$vars
->
{
'bugid'
}
=
$
::FORM
{
'bugid'
}
;
$vars
->
{
'bugid'
}
=
$
bugid
;
$vars
->
{
'attachments'
}
=
\
@attachments
;
$vars
->
{
'attachments'
}
=
\
@attachments
;
$vars
->
{
'bugassignee_id'
}
=
$assignee_id
;
$vars
->
{
'bugassignee_id'
}
=
$assignee_id
;
$vars
->
{
'bugsummary'
}
=
$bugsummary
;
$vars
->
{
'bugsummary'
}
=
$bugsummary
;
...
@@ -850,20 +827,23 @@ sub viewall
...
@@ -850,20 +827,23 @@ sub viewall
||
ThrowTemplateError
(
$template
->
error
());
||
ThrowTemplateError
(
$template
->
error
());
}
}
# Display a form for entering a new attachment.
sub
enter
sub
enter
{
{
# Display a form for entering a new attachment.
# Retrieve and validate parameters
my
$bugid
=
$cgi
->
param
(
'bugid'
);
ValidateBugID
(
$bugid
);
validateCanChangeBug
(
$bugid
);
# Retrieve the attachments the user can edit from the database and write
# Retrieve the attachments the user can edit from the database and write
# them into an array of hashes where each hash represents one attachment.
# them into an array of hashes where each hash represents one attachment.
my
$canEdit
=
""
;
my
$canEdit
=
""
;
if
(
!
UserInGroup
(
"editbugs"
))
{
if
(
!
UserInGroup
(
"editbugs"
))
{
$canEdit
=
"AND submitter_id =
$::userid"
;
$canEdit
=
"AND submitter_id =
"
.
Bugzilla
->
user
->
id
;
}
}
SendSQL
(
"SELECT attach_id, description, isprivate
SendSQL
(
"SELECT attach_id, description, isprivate
FROM attachments
FROM attachments
WHERE bug_id = $
::FORM{'bugid'}
WHERE bug_id = $
bugid
AND isobsolete = 0 $canEdit
AND isobsolete = 0 $canEdit
ORDER BY attach_id"
);
ORDER BY attach_id"
);
my
@attachments
;
# the attachments array
my
@attachments
;
# the attachments array
...
@@ -877,18 +857,18 @@ sub enter
...
@@ -877,18 +857,18 @@ sub enter
# Retrieve the bug summary (for displaying on screen) and assignee.
# Retrieve the bug summary (for displaying on screen) and assignee.
SendSQL
(
"SELECT short_desc, assigned_to FROM bugs
SendSQL
(
"SELECT short_desc, assigned_to FROM bugs
WHERE bug_id = $
::FORM{'bugid'}
"
);
WHERE bug_id = $
bugid
"
);
my
(
$bugsummary
,
$assignee_id
)
=
FetchSQLData
();
my
(
$bugsummary
,
$assignee_id
)
=
FetchSQLData
();
# Define the variables and functions that will be passed to the UI template.
# Define the variables and functions that will be passed to the UI template.
$vars
->
{
'bugid'
}
=
$
::FORM
{
'bugid'
}
;
$vars
->
{
'bugid'
}
=
$
bugid
;
$vars
->
{
'attachments'
}
=
\
@attachments
;
$vars
->
{
'attachments'
}
=
\
@attachments
;
$vars
->
{
'bugassignee_id'
}
=
$assignee_id
;
$vars
->
{
'bugassignee_id'
}
=
$assignee_id
;
$vars
->
{
'bugsummary'
}
=
$bugsummary
;
$vars
->
{
'bugsummary'
}
=
$bugsummary
;
$vars
->
{
'GetBugLink'
}
=
\&
GetBugLink
;
$vars
->
{
'GetBugLink'
}
=
\&
GetBugLink
;
SendSQL
(
"SELECT product_id, component_id FROM bugs
SendSQL
(
"SELECT product_id, component_id FROM bugs
WHERE bug_id = $
::FORM{'bugid'}
"
);
WHERE bug_id = $
bugid
"
);
my
(
$product_id
,
$component_id
)
=
FetchSQLData
();
my
(
$product_id
,
$component_id
)
=
FetchSQLData
();
my
$flag_types
=
Bugzilla::FlagType::
match
({
'target_type'
=>
'attachment'
,
my
$flag_types
=
Bugzilla::FlagType::
match
({
'target_type'
=>
'attachment'
,
'product_id'
=>
$product_id
,
'product_id'
=>
$product_id
,
...
@@ -904,19 +884,40 @@ sub enter
...
@@ -904,19 +884,40 @@ sub enter
||
ThrowTemplateError
(
$template
->
error
());
||
ThrowTemplateError
(
$template
->
error
());
}
}
# Insert a new attachment into the database.
sub
insert
sub
insert
{
{
my
(
$data
)
=
@_
;
my
$dbh
=
Bugzilla
->
dbh
;
my
$userid
=
Bugzilla
->
user
->
id
;
# Insert a new attachment into the database.
# Retrieve and validate parameters
my
$dbh
=
Bugzilla
->
dbh
;
my
$bugid
=
$cgi
->
param
(
'bugid'
);
ValidateBugID
(
$bugid
);
# Escape characters in strings that will be used in SQL statements.
validateCanChangeBug
(
$bugid
);
$filename
=
SqlQuote
(
$filename
);
ValidateComment
(
scalar
$cgi
->
param
(
'comment'
));
my
$description
=
SqlQuote
(
$::FORM
{
'description'
});
my
$filename
=
validateFilename
();
my
$contenttype
=
SqlQuote
(
$::FORM
{
'contenttype'
});
validateIsPatch
();
my
$isprivate
=
$::FORM
{
'isprivate'
}
?
1
:
0
;
my
$data
=
validateData
();
validateDescription
();
validateContentType
()
unless
$cgi
->
param
(
'ispatch'
);
my
@obsolete_ids
=
();
@obsolete_ids
=
validateObsolete
()
if
$cgi
->
param
(
'obsolete'
);
# The order of these function calls is important, as both Flag::validate
# and FlagType::validate assume User::match_field has ensured that the
# values in the requestee fields are legitimate user email addresses.
Bugzilla::User::
match_field
(
$cgi
,
{
'^requestee(_type)?-(\d+)$'
=>
{
'type'
=>
'single'
}
});
Bugzilla::Flag::
validate
(
$cgi
,
$bugid
);
Bugzilla::FlagType::
validate
(
$cgi
,
$bugid
,
$cgi
->
param
(
'id'
));
# Escape characters in strings that will be used in SQL statements.
my
$sql_filename
=
SqlQuote
(
$filename
);
my
$description
=
SqlQuote
(
$cgi
->
param
(
'description'
));
my
$contenttype
=
SqlQuote
(
$cgi
->
param
(
'contenttype'
));
my
$isprivate
=
$cgi
->
param
(
'isprivate'
)
?
1
:
0
;
# Figure out when the changes were made.
# Figure out when the changes were made.
my
(
$timestamp
)
=
Bugzilla
->
dbh
->
selectrow_array
(
"SELECT NOW()"
);
my
(
$timestamp
)
=
Bugzilla
->
dbh
->
selectrow_array
(
"SELECT NOW()"
);
...
@@ -926,9 +927,9 @@ sub insert
...
@@ -926,9 +927,9 @@ sub insert
my
$sth
=
$dbh
->
prepare
(
"INSERT INTO attachments
my
$sth
=
$dbh
->
prepare
(
"INSERT INTO attachments
(thedata, bug_id, creation_ts, filename, description,
(thedata, bug_id, creation_ts, filename, description,
mimetype, ispatch, isprivate, submitter_id)
mimetype, ispatch, isprivate, submitter_id)
VALUES (?, $
::FORM{'bugid'}, $sql_timestamp, $filename,
VALUES (?, $
bugid, $sql_timestamp, $sql_filename,
$description, $contenttype,
$::FORM{'ispatch'}
,
$description, $contenttype,
"
.
$cgi
->
param
(
'ispatch'
)
.
"
,
$isprivate, $
::
userid)"
);
$isprivate, $userid)"
);
# We only use $data here in this INSERT with a placeholder,
# We only use $data here in this INSERT with a placeholder,
# so it's safe.
# so it's safe.
trick_taint
(
$data
);
trick_taint
(
$data
);
...
@@ -940,7 +941,7 @@ sub insert
...
@@ -940,7 +941,7 @@ sub insert
# If the file is to be stored locally, stream the file from the webserver
# If the file is to be stored locally, stream the file from the webserver
# to the local file without reading it into a local variable.
# to the local file without reading it into a local variable.
if
(
$
::FORM
{
'bigfile'
}
)
if
(
$
cgi
->
param
(
'bigfile'
)
)
{
{
my
$fh
=
$cgi
->
upload
(
'data'
);
my
$fh
=
$cgi
->
upload
(
'data'
);
my
$hash
=
(
$attachid
%
100
)
+
100
;
my
$hash
=
(
$attachid
%
100
)
+
100
;
...
@@ -967,10 +968,11 @@ sub insert
...
@@ -967,10 +968,11 @@ sub insert
# Insert a comment about the new attachment into the database.
# Insert a comment about the new attachment into the database.
my
$comment
=
"Created an attachment (id=$attachid)\n$::FORM{'description'}\n"
;
my
$comment
=
"Created an attachment (id=$attachid)\n"
.
$comment
.=
(
"\n"
.
$::FORM
{
'comment'
})
if
$::FORM
{
'comment'
};
$cgi
->
param
(
'description'
)
.
"\n"
;
$comment
.=
(
"\n"
.
$cgi
->
param
(
'comment'
))
if
defined
$cgi
->
param
(
'comment'
);
AppendComment
(
$
::FORM
{
'bugid'
}
,
AppendComment
(
$
bugid
,
Bugzilla
->
user
->
login
,
Bugzilla
->
user
->
login
,
$comment
,
$comment
,
$isprivate
,
$isprivate
,
...
@@ -978,20 +980,23 @@ sub insert
...
@@ -978,20 +980,23 @@ sub insert
# Make existing attachments obsolete.
# Make existing attachments obsolete.
my
$fieldid
=
GetFieldID
(
'attachments.isobsolete'
);
my
$fieldid
=
GetFieldID
(
'attachments.isobsolete'
);
foreach
my
$obsolete_id
(
@
{
$::MFORM
{
'obsolete'
}}
)
{
foreach
my
$obsolete_id
(
@
obsolete_ids
)
{
# If the obsolete attachment has request flags, cancel them.
# If the obsolete attachment has request flags, cancel them.
# This call must be done before updating the 'attachments' table.
# This call must be done before updating the 'attachments' table.
Bugzilla::Flag::
CancelRequests
(
$::FORM
{
'bugid'
},
$obsolete_id
,
$sql_timestamp
);
Bugzilla::Flag::
CancelRequests
(
$bugid
,
$obsolete_id
,
$sql_timestamp
);
SendSQL
(
"UPDATE attachments SET isobsolete = 1 WHERE attach_id = $obsolete_id"
);
SendSQL
(
"UPDATE attachments SET isobsolete = 1 "
.
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
"WHERE attach_id = $obsolete_id"
);
VALUES ($::FORM{'bugid'}, $obsolete_id, $::userid, $sql_timestamp, $fieldid, '0', '1')"
);
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
fieldid, removed, added)
VALUES ($bugid, $obsolete_id, $userid, $sql_timestamp, $fieldid,
'0', '1')"
);
}
}
# Assign the bug to the user, if they are allowed to take it
# Assign the bug to the user, if they are allowed to take it
my
$owner
=
""
;
my
$owner
=
""
;
if
(
$
::FORM
{
'takebug'
}
&&
UserInGroup
(
"editbugs"
))
{
if
(
$
cgi
->
param
(
'takebug'
)
&&
UserInGroup
(
"editbugs"
))
{
my
@fields
=
(
"assigned_to"
,
"bug_status"
,
"resolution"
,
"login_name"
);
my
@fields
=
(
"assigned_to"
,
"bug_status"
,
"resolution"
,
"login_name"
);
...
@@ -1000,10 +1005,10 @@ sub insert
...
@@ -1000,10 +1005,10 @@ sub insert
"FROM bugs "
.
"FROM bugs "
.
"INNER JOIN profiles "
.
"INNER JOIN profiles "
.
"ON profiles.userid = bugs.assigned_to "
.
"ON profiles.userid = bugs.assigned_to "
.
"WHERE bugs.bug_id = $
::FORM{'bugid'}
"
);
"WHERE bugs.bug_id = $
bugid
"
);
my
@oldvalues
=
FetchSQLData
();
my
@oldvalues
=
FetchSQLData
();
my
@newvalues
=
(
$
::userid
,
"ASSIGNED"
,
""
,
DBID_to_name
(
$::userid
)
);
my
@newvalues
=
(
$
userid
,
"ASSIGNED"
,
""
,
Bugzilla
->
user
->
login
);
# Make sure the person we are taking the bug from gets mail.
# Make sure the person we are taking the bug from gets mail.
$owner
=
$oldvalues
[
3
];
$owner
=
$oldvalues
[
3
];
...
@@ -1014,7 +1019,7 @@ sub insert
...
@@ -1014,7 +1019,7 @@ sub insert
# Update the bug record. Note that this doesn't involve login_name.
# Update the bug record. Note that this doesn't involve login_name.
SendSQL
(
"UPDATE bugs SET delta_ts = $sql_timestamp, "
.
SendSQL
(
"UPDATE bugs SET delta_ts = $sql_timestamp, "
.
join
(
", "
,
map
(
"$fields[$_] = $newvalues[$_]"
,
(
0
..
2
)))
.
join
(
", "
,
map
(
"$fields[$_] = $newvalues[$_]"
,
(
0
..
2
)))
.
" WHERE bug_id = $
::FORM{'bugid'}
"
);
" WHERE bug_id = $
bugid
"
);
# We store email addresses in the bugs_activity table rather than IDs.
# We store email addresses in the bugs_activity table rather than IDs.
$oldvalues
[
0
]
=
$oldvalues
[
3
];
$oldvalues
[
0
]
=
$oldvalues
[
3
];
...
@@ -1026,9 +1031,8 @@ sub insert
...
@@ -1026,9 +1031,8 @@ sub insert
my
$fieldid
=
GetFieldID
(
$fields
[
$i
]);
my
$fieldid
=
GetFieldID
(
$fields
[
$i
]);
SendSQL
(
"INSERT INTO bugs_activity "
.
SendSQL
(
"INSERT INTO bugs_activity "
.
"(bug_id, who, bug_when, fieldid, removed, added) "
.
"(bug_id, who, bug_when, fieldid, removed, added) "
.
" VALUES ($::FORM{'bugid'}, $::userid, "
.
"VALUES ($bugid, $userid, $sql_timestamp, "
.
"$sql_timestamp "
.
"$fieldid, $oldvalues[$i], $newvalues[$i])"
);
", $fieldid, $oldvalues[$i], $newvalues[$i])"
);
}
}
}
}
}
}
...
@@ -1040,17 +1044,11 @@ sub insert
...
@@ -1040,17 +1044,11 @@ sub insert
# Define the variables and functions that will be passed to the UI template.
# Define the variables and functions that will be passed to the UI template.
$vars
->
{
'mailrecipients'
}
=
{
'changer'
=>
Bugzilla
->
user
->
login
,
$vars
->
{
'mailrecipients'
}
=
{
'changer'
=>
Bugzilla
->
user
->
login
,
'owner'
=>
$owner
};
'owner'
=>
$owner
};
my
$bugid
=
$::FORM
{
'bugid'
};
detaint_natural
(
$bugid
);
# don't bother with error condition, we know it'll work
# because of ValidateBugID above. This is only needed
# for Perl 5.6.0. If we ever require Perl 5.6.1 or
# newer, or detaint something other than $::FORM{'bugid'}
# in ValidateBugID above, then this can go away.
$vars
->
{
'bugid'
}
=
$bugid
;
$vars
->
{
'bugid'
}
=
$bugid
;
$vars
->
{
'attachid'
}
=
$attachid
;
$vars
->
{
'attachid'
}
=
$attachid
;
$vars
->
{
'description'
}
=
$description
;
$vars
->
{
'description'
}
=
$description
;
$vars
->
{
'contenttypemethod'
}
=
$
::FORM
{
'contenttypemethod'
}
;
$vars
->
{
'contenttypemethod'
}
=
$
cgi
->
param
(
'contenttypemethod'
)
;
$vars
->
{
'contenttype'
}
=
$
::FORM
{
'contenttype'
}
;
$vars
->
{
'contenttype'
}
=
$
cgi
->
param
(
'contenttype'
)
;
print
Bugzilla
->
cgi
->
header
();
print
Bugzilla
->
cgi
->
header
();
...
@@ -1059,18 +1057,20 @@ sub insert
...
@@ -1059,18 +1057,20 @@ sub insert
||
ThrowTemplateError
(
$template
->
error
());
||
ThrowTemplateError
(
$template
->
error
());
}
}
# Edit an attachment record. Users with "editbugs" privileges, (or the
# original attachment's submitter) can edit the attachment's description,
# content type, ispatch and isobsolete flags, and statuses, and they can
# also submit a comment that appears in the bug.
# Users cannot edit the content of the attachment itself.
sub
edit
sub
edit
{
{
# Edit an attachment record. Users with "editbugs" privileges, (or the
# Retrieve and validate parameters
# original attachment's submitter) can edit the attachment's description,
my
(
$attach_id
)
=
validateID
();
# content type, ispatch and isobsolete flags, and statuses, and they can
validateCanEdit
(
$attach_id
);
# also submit a comment that appears in the bug.
# Users cannot edit the content of the attachment itself.
# Retrieve the attachment from the database.
# Retrieve the attachment from the database.
SendSQL
(
"SELECT description, mimetype, filename, bug_id, ispatch, isobsolete, isprivate, LENGTH(thedata)
SendSQL
(
"SELECT description, mimetype, filename, bug_id, ispatch, isobsolete, isprivate, LENGTH(thedata)
FROM attachments WHERE attach_id = $
::FORM{'id'}
"
);
FROM attachments WHERE attach_id = $
attach_id
"
);
my
(
$description
,
$contenttype
,
$filename
,
$bugid
,
$ispatch
,
$isobsolete
,
$isprivate
,
$datasize
)
=
FetchSQLData
();
my
(
$description
,
$contenttype
,
$filename
,
$bugid
,
$ispatch
,
$isobsolete
,
$isprivate
,
$datasize
)
=
FetchSQLData
();
my
$isviewable
=
isViewable
(
$contenttype
);
my
$isviewable
=
isViewable
(
$contenttype
);
...
@@ -1091,14 +1091,14 @@ sub edit
...
@@ -1091,14 +1091,14 @@ sub edit
'component_id'
=>
$component_id
});
'component_id'
=>
$component_id
});
foreach
my
$flag_type
(
@$flag_types
)
{
foreach
my
$flag_type
(
@$flag_types
)
{
$flag_type
->
{
'flags'
}
=
Bugzilla::Flag::
match
({
'type_id'
=>
$flag_type
->
{
'id'
},
$flag_type
->
{
'flags'
}
=
Bugzilla::Flag::
match
({
'type_id'
=>
$flag_type
->
{
'id'
},
'attach_id'
=>
$
::FORM
{
'id'
}
,
'attach_id'
=>
$
attach_id
,
'is_active'
=>
1
});
'is_active'
=>
1
});
}
}
$vars
->
{
'flag_types'
}
=
$flag_types
;
$vars
->
{
'flag_types'
}
=
$flag_types
;
$vars
->
{
'any_flags_requesteeble'
}
=
grep
(
$_
->
{
'is_requesteeble'
},
@$flag_types
);
$vars
->
{
'any_flags_requesteeble'
}
=
grep
(
$_
->
{
'is_requesteeble'
},
@$flag_types
);
# Define the variables and functions that will be passed to the UI template.
# Define the variables and functions that will be passed to the UI template.
$vars
->
{
'attachid'
}
=
$
::FORM
{
'id'
}
;
$vars
->
{
'attachid'
}
=
$
attach_id
;
$vars
->
{
'description'
}
=
$description
;
$vars
->
{
'description'
}
=
$description
;
$vars
->
{
'contenttype'
}
=
$contenttype
;
$vars
->
{
'contenttype'
}
=
$contenttype
;
$vars
->
{
'filename'
}
=
$filename
;
$vars
->
{
'filename'
}
=
$filename
;
...
@@ -1124,15 +1124,31 @@ sub edit
...
@@ -1124,15 +1124,31 @@ sub edit
||
ThrowTemplateError
(
$template
->
error
());
||
ThrowTemplateError
(
$template
->
error
());
}
}
# Updates an attachment record.
sub
update
sub
update
{
{
# Updates an attachment record.
my
$dbh
=
Bugzilla
->
dbh
;
my
$dbh
=
Bugzilla
->
dbh
;
my
$userid
=
Bugzilla
->
user
->
id
;
# Get the bug ID for the bug to which this attachment is attached.
SendSQL
(
"SELECT bug_id FROM attachments WHERE attach_id = $::FORM{'id'}"
);
# Retrieve and validate parameters
my
$bugid
=
FetchSQLData
();
ValidateComment
(
scalar
$cgi
->
param
(
'comment'
));
my
(
$attach_id
,
$bugid
)
=
validateID
();
validateCanEdit
(
$attach_id
);
validateCanChangeAttachment
(
$attach_id
);
validateDescription
();
validateIsPatch
();
validateContentType
()
unless
$cgi
->
param
(
'ispatch'
);
validateIsObsolete
();
validatePrivate
();
# The order of these function calls is important, as both Flag::validate
# and FlagType::validate assume User::match_field has ensured that the
# values in the requestee fields are legitimate user email addresses.
Bugzilla::User::
match_field
(
$cgi
,
{
'^requestee(_type)?-(\d+)$'
=>
{
'type'
=>
'single'
}
});
Bugzilla::Flag::
validate
(
$cgi
,
$bugid
);
Bugzilla::FlagType::
validate
(
$cgi
,
$bugid
,
$attach_id
);
# Lock database tables in preparation for updating the attachment.
# Lock database tables in preparation for updating the attachment.
$dbh
->
bz_lock_tables
(
'attachments WRITE'
,
'flags WRITE'
,
$dbh
->
bz_lock_tables
(
'attachments WRITE'
,
'flags WRITE'
,
...
@@ -1152,14 +1168,14 @@ sub update
...
@@ -1152,14 +1168,14 @@ sub update
# Get a copy of the attachment record before we make changes
# Get a copy of the attachment record before we make changes
# so we can record those changes in the activity table.
# so we can record those changes in the activity table.
SendSQL
(
"SELECT description, mimetype, filename, ispatch, isobsolete, isprivate
SendSQL
(
"SELECT description, mimetype, filename, ispatch, isobsolete, isprivate
FROM attachments WHERE attach_id = $
::FORM{'id'}
"
);
FROM attachments WHERE attach_id = $
attach_id
"
);
my
(
$olddescription
,
$oldcontenttype
,
$oldfilename
,
$oldispatch
,
my
(
$olddescription
,
$oldcontenttype
,
$oldfilename
,
$oldispatch
,
$oldisobsolete
,
$oldisprivate
)
=
FetchSQLData
();
$oldisobsolete
,
$oldisprivate
)
=
FetchSQLData
();
# Quote the description and content type for use in the SQL UPDATE statement.
# Quote the description and content type for use in the SQL UPDATE statement.
my
$quoteddescription
=
SqlQuote
(
$
::FORM
{
'description'
}
);
my
$quoteddescription
=
SqlQuote
(
$
cgi
->
param
(
'description'
)
);
my
$quotedcontenttype
=
SqlQuote
(
$
::FORM
{
'contenttype'
}
);
my
$quotedcontenttype
=
SqlQuote
(
$
cgi
->
param
(
'contenttype'
)
);
my
$quotedfilename
=
SqlQuote
(
$
::FORM
{
'filename'
}
);
my
$quotedfilename
=
SqlQuote
(
$
cgi
->
param
(
'filename'
)
);
# Figure out when the changes were made.
# Figure out when the changes were made.
SendSQL
(
"SELECT NOW()"
);
SendSQL
(
"SELECT NOW()"
);
...
@@ -1169,7 +1185,7 @@ sub update
...
@@ -1169,7 +1185,7 @@ sub update
# to attachments so that we can delete pending requests if the user
# to attachments so that we can delete pending requests if the user
# is obsoleting this attachment without deleting any requests
# is obsoleting this attachment without deleting any requests
# the user submits at the same time.
# the user submits at the same time.
my
$target
=
Bugzilla::Flag::
GetTarget
(
undef
,
$
::FORM
{
'id'
}
);
my
$target
=
Bugzilla::Flag::
GetTarget
(
undef
,
$
attach_id
);
Bugzilla::Flag::
process
(
$target
,
$timestamp
,
$cgi
);
Bugzilla::Flag::
process
(
$target
,
$timestamp
,
$cgi
);
# Update the attachment record in the database.
# Update the attachment record in the database.
...
@@ -1177,71 +1193,83 @@ sub update
...
@@ -1177,71 +1193,83 @@ sub update
SET description = $quoteddescription ,
SET description = $quoteddescription ,
mimetype = $quotedcontenttype ,
mimetype = $quotedcontenttype ,
filename = $quotedfilename ,
filename = $quotedfilename ,
ispatch =
$::FORM{'ispatch'}
,
ispatch =
"
.
$cgi
->
param
(
'ispatch'
)
.
"
,
isobsolete =
$::FORM{'isobsolete'}
,
isobsolete =
"
.
$cgi
->
param
(
'isobsolete'
)
.
"
,
isprivate =
$::FORM{'isprivate'}
isprivate =
"
.
$cgi
->
param
(
'isprivate'
)
.
"
WHERE attach_id = $
::FORM{'id'}
WHERE attach_id = $
attach_id
"
);
"
);
# Record changes in the activity table.
# Record changes in the activity table.
my
$sql_timestamp
=
SqlQuote
(
$timestamp
);
my
$sql_timestamp
=
SqlQuote
(
$timestamp
);
if
(
$olddescription
ne
$
::FORM
{
'description'
}
)
{
if
(
$olddescription
ne
$
cgi
->
param
(
'description'
)
)
{
my
$quotedolddescription
=
SqlQuote
(
$olddescription
);
my
$quotedolddescription
=
SqlQuote
(
$olddescription
);
my
$fieldid
=
GetFieldID
(
'attachments.description'
);
my
$fieldid
=
GetFieldID
(
'attachments.description'
);
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
VALUES ($bugid, $::FORM{'id'}, $::userid, $sql_timestamp, $fieldid, $quotedolddescription, $quoteddescription)"
);
fieldid, removed, added)
VALUES ($bugid, $attach_id, $userid, $sql_timestamp, $fieldid,
$quotedolddescription, $quoteddescription)"
);
}
}
if
(
$oldcontenttype
ne
$
::FORM
{
'contenttype'
}
)
{
if
(
$oldcontenttype
ne
$
cgi
->
param
(
'contenttype'
)
)
{
my
$quotedoldcontenttype
=
SqlQuote
(
$oldcontenttype
);
my
$quotedoldcontenttype
=
SqlQuote
(
$oldcontenttype
);
my
$fieldid
=
GetFieldID
(
'attachments.mimetype'
);
my
$fieldid
=
GetFieldID
(
'attachments.mimetype'
);
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
VALUES ($bugid, $::FORM{'id'}, $::userid, $sql_timestamp, $fieldid, $quotedoldcontenttype, $quotedcontenttype)"
);
fieldid, removed, added)
VALUES ($bugid, $attach_id, $userid, $sql_timestamp, $fieldid,
$quotedoldcontenttype, $quotedcontenttype)"
);
}
}
if
(
$oldfilename
ne
$
::FORM
{
'filename'
}
)
{
if
(
$oldfilename
ne
$
cgi
->
param
(
'filename'
)
)
{
my
$quotedoldfilename
=
SqlQuote
(
$oldfilename
);
my
$quotedoldfilename
=
SqlQuote
(
$oldfilename
);
my
$fieldid
=
GetFieldID
(
'attachments.filename'
);
my
$fieldid
=
GetFieldID
(
'attachments.filename'
);
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
VALUES ($bugid, $::FORM{'id'}, $::userid, $sql_timestamp, $fieldid, $quotedoldfilename, $quotedfilename)"
);
fieldid, removed, added)
VALUES ($bugid, $attach_id, $userid, $sql_timestamp, $fieldid,
$quotedoldfilename, $quotedfilename)"
);
}
}
if
(
$oldispatch
ne
$
::FORM
{
'ispatch'
}
)
{
if
(
$oldispatch
ne
$
cgi
->
param
(
'ispatch'
)
)
{
my
$fieldid
=
GetFieldID
(
'attachments.ispatch'
);
my
$fieldid
=
GetFieldID
(
'attachments.ispatch'
);
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
VALUES ($bugid, $::FORM{'id'}, $::userid, $sql_timestamp, $fieldid, $oldispatch, $::FORM{'ispatch'})"
);
fieldid, removed, added)
VALUES ($bugid, $attach_id, $userid, $sql_timestamp, $fieldid,
$oldispatch, "
.
$cgi
->
param
(
'ispatch'
)
.
")"
);
}
}
if
(
$oldisobsolete
ne
$
::FORM
{
'isobsolete'
}
)
{
if
(
$oldisobsolete
ne
$
cgi
->
param
(
'isobsolete'
)
)
{
my
$fieldid
=
GetFieldID
(
'attachments.isobsolete'
);
my
$fieldid
=
GetFieldID
(
'attachments.isobsolete'
);
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
VALUES ($bugid, $::FORM{'id'}, $::userid, $sql_timestamp, $fieldid, $oldisobsolete, $::FORM{'isobsolete'})"
);
fieldid, removed, added)
VALUES ($bugid, $attach_id, $userid, $sql_timestamp, $fieldid,
$oldisobsolete, "
.
$cgi
->
param
(
'isobsolete'
)
.
")"
);
}
}
if
(
$oldisprivate
ne
$
::FORM
{
'isprivate'
}
)
{
if
(
$oldisprivate
ne
$
cgi
->
param
(
'isprivate'
)
)
{
my
$fieldid
=
GetFieldID
(
'attachments.isprivate'
);
my
$fieldid
=
GetFieldID
(
'attachments.isprivate'
);
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
VALUES ($bugid, $::FORM{'id'}, $::userid, $sql_timestamp, $fieldid, $oldisprivate, $::FORM{'isprivate'})"
);
fieldid, removed, added)
VALUES ($bugid, $attach_id, $userid, $sql_timestamp, $fieldid,
$oldisprivate, "
.
$cgi
->
param
(
'isprivate'
)
.
")"
);
}
}
# Unlock all database tables now that we are finished updating the database.
# Unlock all database tables now that we are finished updating the database.
$dbh
->
bz_unlock_tables
();
$dbh
->
bz_unlock_tables
();
# Get the user's login name since the AppendComment and header functions
# need it.
my
$who
=
Bugzilla
->
user
->
login
;
# If the user submitted a comment while editing the attachment,
# If the user submitted a comment while editing the attachment,
# add the comment to the bug.
# add the comment to the bug.
if
(
$::FORM
{
'comment'
}
)
if
(
defined
$cgi
->
param
(
'comment'
)
)
{
{
# Prepend a string to the comment to let users know that the comment came from
# Prepend a string to the comment to let users know that the comment came
# the "edit attachment" screen.
# from the "edit attachment" screen.
my
$comment
=
qq|(From update of attachment $::FORM{'id'})\n|
.
$::FORM
{
'comment'
};
my
$comment
=
qq|(From update of attachment $attach_id)\n|
.
$cgi
->
param
(
'comment'
);
# Get the user's login name since the AppendComment function needs it.
my
$who
=
DBID_to_name
(
$::userid
);
# Mention $::userid again so Perl doesn't give me a warning about it.
my
$neverused
=
$::userid
;
# Append the comment to the list of comments in the database.
# Append the comment to the list of comments in the database.
AppendComment
(
$bugid
,
$who
,
$comment
,
$
::FORM
{
'isprivate'
}
,
$timestamp
);
AppendComment
(
$bugid
,
$who
,
$comment
,
$
cgi
->
param
(
'isprivate'
)
,
$timestamp
);
}
}
# Define the variables and functions that will be passed to the UI template.
# Define the variables and functions that will be passed to the UI template.
$vars
->
{
'mailrecipients'
}
=
{
'changer'
=>
Bugzilla
->
user
->
login
};
$vars
->
{
'mailrecipients'
}
=
{
'changer'
=>
$who
};
$vars
->
{
'attachid'
}
=
$
::FORM
{
'id'
}
;
$vars
->
{
'attachid'
}
=
$
attach_id
;
$vars
->
{
'bugid'
}
=
$bugid
;
$vars
->
{
'bugid'
}
=
$bugid
;
print
Bugzilla
->
cgi
->
header
();
print
Bugzilla
->
cgi
->
header
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment